From 6c87448b57890eabd11103fcb2ab8f5e687a02cc Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 21 Jun 2023 20:49:18 +0200 Subject: [PATCH 001/297] optimize Cstr/EscapeAscii display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit old: ascii::bench_ascii_escape_display_mixed 17.97µs/iter +/- 204.00ns ascii::bench_ascii_escape_display_no_escape 545.00ns/iter +/- 6.00ns new: ascii::bench_ascii_escape_display_mixed 4.99µs/iter +/- 56.00ns ascii::bench_ascii_escape_display_no_escape 91.00ns/iter +/- 1.00ns --- library/core/benches/ascii.rs | 28 ++++++++++++++++ library/core/src/ascii.rs | 11 ++++++ library/core/src/iter/adapters/flatten.rs | 8 +++++ library/core/src/iter/adapters/fuse.rs | 4 +++ library/core/src/iter/adapters/map.rs | 4 +++ library/core/src/slice/ascii.rs | 41 ++++++++++++++++++++++- library/core/tests/ascii.rs | 10 ++++++ 7 files changed, 105 insertions(+), 1 deletion(-) diff --git a/library/core/benches/ascii.rs b/library/core/benches/ascii.rs index 64938745a4a1..71ec9fed2fe7 100644 --- a/library/core/benches/ascii.rs +++ b/library/core/benches/ascii.rs @@ -63,6 +63,7 @@ macro_rules! benches { } } +use std::fmt::Write; use test::black_box; use test::Bencher; @@ -351,3 +352,30 @@ static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [ N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, ]; + +const ASCII_PATH: &[u8] = b"home/kyubey/rust/build/x86_64-unknown-linux-gnu/stage0/lib:/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-tools/release/deps"; +const RUST_INCANTATION: &[u8] = br#"AR_x86_64_unknown_linux_gnu="ar" CARGO_INCREMENTAL="0" CARGO_PROFILE_RELEASE_DEBUG="1" CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="false" CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="false" CARGO_TARGET_DIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-std" CC_x86_64_unknown_linux_gnu="cc" CFG_COMPILER_HOST_TRIPLE="x86_64-unknown-linux-gnu" CFG_RELEASE_CHANNEL="dev" CFLAGS_x86_64_unknown_linux_gnu="-ffunction-sections -fdata-sections -fPIC -m64" CXXFLAGS_x86_64_unknown_linux_gnu="-ffunction-sections -fdata-sections -fPIC -m64" CXX_x86_64_unknown_linux_gnu="c++" LD_LIBRARY_PATH="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-sysroot/lib/rustlib/x86_64-unknown-linux-gnu/lib" LIBC_CHECK_CFG="1" RANLIB_x86_64_unknown_linux_gnu="ar s" REAL_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" RUSTBUILD_NATIVE_DIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/native" RUSTC="/home/kyubey/workspace/rust/build/bootstrap/debug/rustc" RUSTC_BOOTSTRAP="1" RUSTC_BREAK_ON_ICE="1" RUSTC_ERROR_METADATA_DST="/home/kyubey/workspace/rust/build/tmp/extended-error-metadata" RUSTC_FORCE_UNSTABLE="1" RUSTC_HOST_FUSE_LD_LLD="1" RUSTC_INSTALL_BINDIR="bin" RUSTC_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTC_LINT_FLAGS="-Wrust_2018_idioms -Wunused_lifetimes -Wsemicolon_in_expressions_from_macros" RUSTC_REAL="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" RUSTC_SNAPSHOT="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" RUSTC_SNAPSHOT_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTC_STAGE="0" RUSTC_SYSROOT="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-sysroot" RUSTC_VERBOSE="0" RUSTDOC="/home/kyubey/workspace/rust/build/bootstrap/debug/rustdoc" RUSTDOCFLAGS="-C target-cpu=native --cfg=bootstrap -Csymbol-mangling-version=legacy -Zunstable-options -Zunstable-options --check-cfg=values(bootstrap) --check-cfg=values(stdarch_intel_sde) --check-cfg=values(no_fp_fmt_parse) --check-cfg=values(no_global_oom_handling) --check-cfg=values(no_rc) --check-cfg=values(no_sync) --check-cfg=values(freebsd12) --check-cfg=values(freebsd13) --check-cfg=values(backtrace_in_libstd) --check-cfg=values(target_env,\"libnx\") --check-cfg=values(target_arch,\"asmjs\",\"spirv\",\"nvptx\",\"xtensa\") -Clink-arg=-fuse-ld=lld -Clink-arg=-Wl,--threads=1 -Wrustdoc::invalid_codeblock_attributes --crate-version 1.72.0-dev -Zcrate-attr=doc(html_root_url=\"https://doc.rust-lang.org/nightly/\") -Zcrate-attr=warn(rust_2018_idioms)" RUSTDOC_FUSE_LD_LLD="1" RUSTDOC_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTDOC_REAL="/path/to/nowhere/rustdoc/not/required" RUSTFLAGS="-C target-cpu=native --cfg=bootstrap -Csymbol-mangling-version=legacy -Zunstable-options -Zunstable-options --check-cfg=values(bootstrap) --check-cfg=values(stdarch_intel_sde) --check-cfg=values(no_fp_fmt_parse) --check-cfg=values(no_global_oom_handling) --check-cfg=values(no_rc) --check-cfg=values(no_sync) --check-cfg=values(freebsd12) --check-cfg=values(freebsd13) --check-cfg=values(backtrace_in_libstd) --check-cfg=values(target_env,\"libnx\") --check-cfg=values(target_arch,\"asmjs\",\"spirv\",\"nvptx\",\"xtensa\") -Zmacro-backtrace -Clink-args=-Wl,-z,origin -Clink-args=-Wl,-rpath,$ORIGIN/../lib -Clink-args=-fuse-ld=lld -Csplit-debuginfo=off -Cprefer-dynamic -Zinline-mir -Clto=off -Zcrate-attr=doc(html_root_url=\"https://doc.rust-lang.org/nightly/\")" RUST_COMPILER_RT_ROOT="/home/kyubey/workspace/rust/src/llvm-project/compiler-rt" RUST_TEST_THREADS="48" WINAPI_NO_BUNDLED_LIBRARIES="1" __CARGO_DEFAULT_LIB_METADATA="bootstrapstd" "/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "bench" "--target" "x86_64-unknown-linux-gnu" "-Zcheck-cfg=names,values,output" "-Zbinary-dep-depinfo" "-j" "48" "--features" " panic-unwind backtrace compiler-builtins-c" "--manifest-path" "/home/kyubey/workspace/rust/library/sysroot/Cargo.toml" "-p" "core" "--" "bench_ascii_escape_display" "--quiet" "-Z" "unstable-options" "--format" "json""#; + +#[bench] +fn bench_ascii_escape_display_no_escape(b: &mut Bencher) { + let mut writer = String::with_capacity(8 * 1024); + + b.iter(move || { + writer.clear(); + let iter = ASCII_PATH.escape_ascii(); + write!(writer, "{}", iter).unwrap(); + writer.len() + }) +} + +#[bench] +fn bench_ascii_escape_display_mixed(b: &mut Bencher) { + let mut writer = String::with_capacity(8 * 1024); + + b.iter(move || { + writer.clear(); + let iter = RUST_INCANTATION.escape_ascii(); + write!(writer, "{}", iter).unwrap(); + writer.len() + }) +} diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index ef8e4d098ed9..02867789b79d 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -96,6 +96,17 @@ pub fn escape_default(c: u8) -> EscapeDefault { EscapeDefault(escape::EscapeIterInner::new(data, range)) } +impl EscapeDefault { + pub(crate) fn empty() -> Self { + let data = [Char::Null; 4]; + EscapeDefault(escape::EscapeIterInner::new(data, 0..0)) + } + + pub(crate) fn as_str(&self) -> &str { + self.0.as_str() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeDefault { type Item = u8; diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 2568aaf34f3f..f3992b500adf 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -18,6 +18,14 @@ impl U> FlatMap { pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap { FlatMap { inner: FlattenCompat::new(iter.map(f)) } } + + pub(crate) fn into_parts(self) -> (Option, Option, Option) { + ( + self.inner.frontiter, + self.inner.iter.into_inner().map(Map::into_inner), + self.inner.backiter, + ) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index b1fa4f92117b..e38234eae499 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -24,6 +24,10 @@ impl Fuse { pub(in crate::iter) fn new(iter: I) -> Fuse { Fuse { iter: Some(iter) } } + + pub(crate) fn into_inner(self) -> Option { + self.iter + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 31d02a4da6ea..2563f27d1693 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -68,6 +68,10 @@ impl Map { pub(in crate::iter) fn new(iter: I, f: F) -> Map { Map { iter, f } } + + pub(crate) fn into_inner(self) -> I { + self.iter + } } #[stable(feature = "core_impl_debug", since = "1.9.0")] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index f3311f76a7f0..324bf5c05af2 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -5,6 +5,7 @@ use crate::fmt::{self, Write}; use crate::iter; use crate::mem; use crate::ops; +use core::ascii::EscapeDefault; #[cfg(not(test))] impl [u8] { @@ -250,7 +251,45 @@ impl<'a> iter::FusedIterator for EscapeAscii<'a> {} #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> fmt::Display for EscapeAscii<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.clone().try_for_each(|b| f.write_char(b as char)) + // disassemble iterator, including front/back parts of flatmap in case it has been partially consumed + let (front, slice, back) = self.clone().inner.into_parts(); + let front = front.unwrap_or(EscapeDefault::empty()); + let mut bytes = slice.unwrap_or_default().as_slice(); + let back = back.unwrap_or(EscapeDefault::empty()); + + // usually empty, so the formatter won't have to do any work + for byte in front { + f.write_char(byte as char)?; + } + + fn needs_escape(b: u8) -> bool { + b > 0x7E || b < 0x20 || b == b'\\' || b == b'\'' || b == b'"' + } + + while bytes.len() > 0 { + // fast path for the printable, non-escaped subset of ascii + let prefix = bytes.iter().take_while(|&&b| !needs_escape(b)).count(); + // SAFETY: prefix length was derived by counting bytes in the same splice, so it's in-bounds + let (prefix, remainder) = unsafe { bytes.split_at_unchecked(prefix) }; + // SAFETY: prefix is a valid utf8 sequence, as it's a subset of ASCII + let prefix = unsafe { crate::str::from_utf8_unchecked(prefix) }; + + f.write_str(prefix)?; // the fast part + + bytes = remainder; + + if let Some(&b) = bytes.first() { + // guaranteed to be non-empty, better to write it as a str + f.write_str(ascii::escape_default(b).as_str())?; + bytes = &bytes[1..]; + } + } + + // also usually empty + for byte in back { + f.write_char(byte as char)?; + } + Ok(()) } } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index f5f2dd047788..3d3f8ac10c60 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -479,3 +479,13 @@ fn ascii_ctype_const() { is_ascii_control => [false, false, false, false, false]; } } + +#[test] +fn test_ascii_display() { + assert_eq!(b"foo'bar".escape_ascii().to_string(), r#"foo\'bar"#); + assert_eq!(b"\0\xff".escape_ascii().to_string(), r#"\x00\xff"#); + let mut it = b"\0fastpath\xffremainder\xff".escape_ascii(); + let _ = it.advance_by(4); + let _ = it.advance_back_by(4); + assert_eq!(it.to_string(), r#"fastpath\xffremainder"#); +} From 9ced08956902e7aeb6fd52c05fbac935de11c699 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sat, 29 Jul 2023 19:42:22 -0700 Subject: [PATCH 002/297] [rustc_data_structures] Use partition_point to find binary_search_slice end. --- .../src/binary_search_util/mod.rs | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs index bc8a6b9eac0c..332ad8af33bc 100644 --- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs +++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs @@ -14,31 +14,18 @@ where let start = data.partition_point(|x| key_fn(x) < *key); // At this point `start` either points at the first entry with equal or // greater key or is equal to `size` in case all elements have smaller keys + // Invariant: start == size || key_fn(&data[start]) >= *key if start == size || key_fn(&data[start]) != *key { return &[]; }; + // Invariant: start < size && key_fn(&data[start]) == *key - // Now search forward to find the *last* one. - let mut end = start; - let mut previous = start; - let mut step = 1; - loop { - end = end.saturating_add(step).min(size); - if end == size || key_fn(&data[end]) != *key { - break; - } - previous = end; - step *= 2; - } - step = end - previous; - while step > 1 { - let half = step / 2; - let mid = end - half; - if key_fn(&data[mid]) != *key { - end = mid; - } - step -= half; - } + // Find the first entry with key > `key`. Skip `start` entries since + // key_fn(&data[start]) == *key + // Invariant: offset == size || key_fn(&data[offset]) >= *key + let offset = start + 1; + let end = data[offset..].partition_point(|x| key_fn(x) <= *key) + offset; + // Invariant: end == size || key_fn(&data[end]) > *key &data[start..end] } From 55020c6f2f4aeac24e24d9bf4a623415c83c4608 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 19:59:26 -0500 Subject: [PATCH 003/297] Reverse ordering of `split_{first,last}_chunk` to be `(preceding, last)` These methods currently return `(last_chunk, preceding_slice)`, which matches the existing `split_x` methods that remove one item. Change these to instead return `(preceding_slice, last_chunk)` which matches string split methods, should be more intuitive, and will allow for consistency with methods that split more items. --- library/core/src/slice/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 45080eda2ce2..970b1cb4f1d7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -456,15 +456,15 @@ impl [T] { /// /// let x = &[0, 1, 2]; /// - /// if let Some((last, elements)) = x.split_last_chunk::<2>() { - /// assert_eq!(last, &[1, 2]); + /// if let Some((elements, last)) = x.split_last_chunk::<2>() { /// assert_eq!(elements, &[0]); + /// assert_eq!(last, &[1, 2]); /// } /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] - pub const fn split_last_chunk(&self) -> Option<(&[T; N], &[T])> { + pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { if self.len() < N { None } else { @@ -473,7 +473,7 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((unsafe { &*(last.as_ptr() as *const [T; N]) }, init)) + Some((init, unsafe { &*(last.as_ptr() as *const [T; N]) })) } } @@ -486,7 +486,7 @@ impl [T] { /// /// let x = &mut [0, 1, 2]; /// - /// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() { + /// if let Some((elements, last)) = x.split_last_chunk_mut::<2>() { /// last[0] = 3; /// last[1] = 4; /// elements[0] = 5; @@ -498,7 +498,7 @@ impl [T] { #[inline] pub const fn split_last_chunk_mut( &mut self, - ) -> Option<(&mut [T; N], &mut [T])> { + ) -> Option<(&mut [T], &mut [T; N])> { if self.len() < N { None } else { @@ -508,7 +508,7 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }, init)) + Some((init, unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) })) } } From 6e8ec852f77f1ee21eaa6bdfffd63d5ae69d9002 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 20:22:53 -0500 Subject: [PATCH 004/297] Make documentation of `slice_first_last_chunk` more consistent Clarify that these functions return array references. Also change from doing `as` casting to using the less misuseable `.cast()`. --- library/core/src/slice/mod.rs | 56 ++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 970b1cb4f1d7..7c07a86e2dd0 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -300,7 +300,7 @@ impl [T] { if let [.., last] = self { Some(last) } else { None } } - /// Returns a mutable pointer to the last item in the slice. + /// Returns a mutable reference to the last item in the slice. /// /// # Examples /// @@ -320,7 +320,9 @@ impl [T] { if let [.., last] = self { Some(last) } else { None } } - /// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements. + /// Return an array reference to the first `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -345,12 +347,13 @@ impl [T] { } else { // SAFETY: We explicitly check for the correct number of elements, // and do not let the reference outlive the slice. - Some(unsafe { &*(self.as_ptr() as *const [T; N]) }) + Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) }) } } - /// Returns a mutable reference to the first `N` elements of the slice, - /// or `None` if it has fewer than `N` elements. + /// Return a mutable array reference to the first `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -375,12 +378,13 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(self.as_mut_ptr() as *mut [T; N]) }) + Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) }) } } - /// Returns the first `N` elements of the slice and the remainder, - /// or `None` if it has fewer than `N` elements. + /// Return an array reference to the first `N` items in the slice and the remaining slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -406,12 +410,14 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((unsafe { &*(first.as_ptr() as *const [T; N]) }, tail)) + Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) } } - /// Returns a mutable reference to the first `N` elements of the slice and the remainder, - /// or `None` if it has fewer than `N` elements. + /// Return a mutable array reference to the first `N` items in the slice and the remaining + /// slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -442,12 +448,13 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(first.as_mut_ptr() as *mut [T; N]) }, tail)) + Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) } } - /// Returns the last `N` elements of the slice and the remainder, - /// or `None` if it has fewer than `N` elements. + /// Return an array reference to the last `N` items in the slice and the remaining slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -473,11 +480,14 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((init, unsafe { &*(last.as_ptr() as *const [T; N]) })) + Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) } } - /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. + /// Return a mutable array reference to the last `N` items in the slice and the remaining + /// slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -508,11 +518,13 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((init, unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) })) + Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) } } - /// Returns the last element of the slice, or `None` if it is empty. + /// Return an array reference to the last `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -541,11 +553,13 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some(unsafe { &*(last.as_ptr() as *const [T; N]) }) + Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) } } - /// Returns a mutable pointer to the last item in the slice. + /// Return a mutable array reference to the last `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// @@ -574,7 +588,7 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }) + Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) } } From 97bc528877b698df2f61dd743b1a155ca3f5eead Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sun, 5 Nov 2023 17:35:37 -0600 Subject: [PATCH 005/297] Remove invariant comments --- compiler/rustc_data_structures/src/binary_search_util/mod.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs index 332ad8af33bc..1c6e227cec40 100644 --- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs +++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs @@ -14,18 +14,14 @@ where let start = data.partition_point(|x| key_fn(x) < *key); // At this point `start` either points at the first entry with equal or // greater key or is equal to `size` in case all elements have smaller keys - // Invariant: start == size || key_fn(&data[start]) >= *key if start == size || key_fn(&data[start]) != *key { return &[]; }; - // Invariant: start < size && key_fn(&data[start]) == *key // Find the first entry with key > `key`. Skip `start` entries since // key_fn(&data[start]) == *key - // Invariant: offset == size || key_fn(&data[offset]) >= *key let offset = start + 1; let end = data[offset..].partition_point(|x| key_fn(x) <= *key) + offset; - // Invariant: end == size || key_fn(&data[end]) > *key &data[start..end] } From 27f419bc7dfb777f984595ffbc800331f591ce66 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 22 Sep 2023 16:42:08 -0700 Subject: [PATCH 006/297] implement strict_* operations for signed integer types --- library/core/src/lib.rs | 1 + library/core/src/num/int_macros.rs | 508 +++++++++++++++++++++++++ library/core/src/num/mod.rs | 1 + library/core/src/num/overflow_panic.rs | 47 +++ 4 files changed, 557 insertions(+) create mode 100644 library/core/src/num/overflow_panic.rs diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 921a0fb6a9f8..44ba6c58c670 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -162,6 +162,7 @@ #![feature(const_slice_ptr_len)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] +#![feature(const_strict_overflow_ops)] #![feature(const_swap)] #![feature(const_try)] #![feature(const_type_id)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index fd01f1b26101..8b3f742bf919 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -454,6 +454,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_add(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_add(rhs); + if unlikely!(b) {overflow_panic::add()} else {a} + } + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow /// cannot occur. /// @@ -501,6 +533,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict addition with an unsigned integer. Computes `self + rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self { + let (a, b) = self.overflowing_add_unsigned(rhs); + if unlikely!(b) {overflow_panic::add()} else {a} + } + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if /// overflow occurred. /// @@ -522,6 +586,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_sub(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_sub(rhs); + if unlikely!(b) {overflow_panic::sub()} else {a} + } + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow /// cannot occur. /// @@ -569,6 +665,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict subtraction with an unsigned integer. Computes `self - rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self { + let (a, b) = self.overflowing_sub_unsigned(rhs); + if unlikely!(b) {overflow_panic::sub()} else {a} + } + /// Checked integer multiplication. Computes `self * rhs`, returning `None` if /// overflow occurred. /// @@ -590,6 +718,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")] + /// ``` + /// + /// ``` should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_mul(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_mul(rhs); + if unlikely!(b) {overflow_panic::mul()} else {a} + } + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow /// cannot occur. /// @@ -642,6 +802,49 @@ macro_rules! int_impl { } } + /// Strict integer division. Computes `self / rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_div(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_div(rhs); + if unlikely!(b) {overflow_panic::div()} else {a} + } + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, /// returning `None` if `rhs == 0` or the division results in overflow. /// @@ -668,6 +871,49 @@ macro_rules! int_impl { } } + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_div_euclid(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_div_euclid(rhs); + if unlikely!(b) {overflow_panic::div()} else {a} + } + /// Checked integer remainder. Computes `self % rhs`, returning `None` if /// `rhs == 0` or the division results in overflow. /// @@ -694,6 +940,48 @@ macro_rules! int_impl { } } + /// Strict integer remainder. Computes `self % rhs`, panicking if + /// the division results in overflow. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a + /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_rem(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_rem(rhs); + if unlikely!(b) {overflow_panic::rem()} else {a} + } + /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` /// if `rhs == 0` or the division results in overflow. /// @@ -720,6 +1008,48 @@ macro_rules! int_impl { } } + /// Strict Euclidean remainder. Computes `self.rem_euclid(rhs)`, panicking if + /// the division results in overflow. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a + /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_rem_euclid(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_rem_euclid(rhs); + if unlikely!(b) {overflow_panic::rem()} else {a} + } + /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. /// /// # Examples @@ -765,6 +1095,37 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_sub(0, self) } } + /// Strict negation. Computes `-self`, panicking if `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] + /// + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_neg(self) -> Self { + let (a, b) = self.overflowing_neg(); + if unlikely!(b) {overflow_panic::neg()} else {a} + } + /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger /// than or equal to the number of bits in `self`. /// @@ -786,6 +1147,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_shl(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shl(rhs); + if unlikely!(b) {overflow_panic::shl()} else {a} + } + /// Unchecked shift left. Computes `self << rhs`, assuming that /// `rhs` is less than the number of bits in `self`. /// @@ -834,6 +1227,38 @@ macro_rules! int_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_shr(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shr(rhs); + if unlikely!(b) {overflow_panic::shr()} else {a} + } + /// Unchecked shift right. Computes `self >> rhs`, assuming that /// `rhs` is less than the number of bits in `self`. /// @@ -885,6 +1310,41 @@ macro_rules! int_impl { } } + /// Strict absolute value. Computes `self.abs()`, panicking if + /// `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_abs(self) -> Self { + if self.is_negative() { + self.strict_neg() + } else { + self + } + } + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if /// overflow occurred. /// @@ -923,6 +1383,54 @@ macro_rules! int_impl { acc.checked_mul(base) } + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.strict_mul(base); + } + exp /= 2; + base = base.strict_mul(base); + } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.strict_mul(base) + } + /// Returns the square root of the number, rounded down. /// /// Returns `None` if `self` is negative. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 2a0b31404f03..96de7673c6f2 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -44,6 +44,7 @@ mod uint_macros; // import uint_impl! mod error; mod int_log10; mod nonzero; +mod overflow_panic; mod saturating; mod wrapping; diff --git a/library/core/src/num/overflow_panic.rs b/library/core/src/num/overflow_panic.rs new file mode 100644 index 000000000000..b941fdb212a8 --- /dev/null +++ b/library/core/src/num/overflow_panic.rs @@ -0,0 +1,47 @@ +#[cold] +#[track_caller] +pub const fn add() -> ! { + panic!("attempt to add with overflow") +} + +#[cold] +#[track_caller] +pub const fn sub() -> ! { + panic!("attempt to subtract with overflow") +} + +#[cold] +#[track_caller] +pub const fn mul() -> ! { + panic!("attempt to multiply with overflow") +} + +#[cold] +#[track_caller] +pub const fn div() -> ! { + panic!("attempt to divide with overflow") +} + +#[cold] +#[track_caller] +pub const fn rem() -> ! { + panic!("attempt to calculate the remainder with overflow") +} + +#[cold] +#[track_caller] +pub const fn neg() -> ! { + panic!("attempt to negate with overflow") +} + +#[cold] +#[track_caller] +pub const fn shr() -> ! { + panic!("attempt to shift right with overflow") +} + +#[cold] +#[track_caller] +pub const fn shl() -> ! { + panic!("attempt to shift left with overflow") +} From fb349a2b7a753640e3eb577554641f8c75a6df49 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 22 Sep 2023 20:34:54 -0700 Subject: [PATCH 007/297] implement strict_* operations for unsigned integer types --- library/core/src/num/uint_macros.rs | 394 ++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 11a53aaf122e..2d8dbbe1f508 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -462,6 +462,38 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_add(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_add(rhs); + if unlikely!(b) {overflow_panic::add()} else {a} + } + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow /// cannot occur. /// @@ -510,6 +542,43 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict addition with a signed integer. Computes `self + rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_add_signed(self, rhs: $SignedT) -> Self { + let (a, b) = self.overflowing_add_signed(rhs); + if unlikely!(b) {overflow_panic::add()} else {a} + } + /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if overflow occurred. /// @@ -531,6 +600,38 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_sub(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_sub(rhs); + if unlikely!(b) {overflow_panic::sub()} else {a} + } + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow /// cannot occur. /// @@ -578,6 +679,38 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")] + /// ``` + /// + /// ``` should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_mul(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_mul(rhs); + if unlikely!(b) {overflow_panic::mul()} else {a} + } + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow /// cannot occur. /// @@ -630,6 +763,33 @@ macro_rules! uint_impl { } } + /// Strict integer division. Computes `self / rhs`. + /// Strict division on unsigned types is just normal division. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn strict_div(self, rhs: Self) -> Self { + self / rhs + } + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` /// if `rhs == 0`. /// @@ -654,6 +814,35 @@ macro_rules! uint_impl { } } + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`. + /// Strict division on unsigned types is just normal division. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.strict_div(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn strict_div_euclid(self, rhs: Self) -> Self { + self / rhs + } /// Checked integer remainder. Computes `self % rhs`, returning `None` /// if `rhs == 0`. @@ -681,6 +870,34 @@ macro_rules! uint_impl { } } + /// Strict integer remainder. Computes `self % rhs`. + /// Strict remainder calculation on unsigned types is + /// just the regular remainder calculation. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn strict_rem(self, rhs: Self) -> Self { + self % rhs + } + /// Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` /// if `rhs == 0`. /// @@ -705,6 +922,37 @@ macro_rules! uint_impl { } } + /// Strict Euclidean modulo. Computes `self.rem_euclid(rhs)`. + /// Strict modulo calculation on unsigned types is + /// just the regular remainder calculation. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.strict_rem(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn strict_rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + /// Returns the logarithm of the number with respect to an arbitrary base, /// rounded down. /// @@ -894,6 +1142,40 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict negation. Computes `-self`, panicking unless `self == + /// 0`. + /// + /// Note that negating any positive integer will overflow. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] + /// + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_neg(self) -> Self { + let (a, b) = self.overflowing_neg(); + if unlikely!(b) {overflow_panic::neg()} else {a} + } + /// Checked shift left. Computes `self << rhs`, returning `None` /// if `rhs` is larger than or equal to the number of bits in `self`. /// @@ -915,6 +1197,38 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_shl(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shl(rhs); + if unlikely!(b) {overflow_panic::shl()} else {a} + } + /// Unchecked shift left. Computes `self << rhs`, assuming that /// `rhs` is less than the number of bits in `self`. /// @@ -963,6 +1277,38 @@ macro_rules! uint_impl { if unlikely!(b) {None} else {Some(a)} } + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_shr(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shr(rhs); + if unlikely!(b) {overflow_panic::shr()} else {a} + } + /// Unchecked shift right. Computes `self >> rhs`, assuming that /// `rhs` is less than the number of bits in `self`. /// @@ -1029,6 +1375,54 @@ macro_rules! uint_impl { acc.checked_mul(base) } + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn strict_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.strict_mul(base); + } + exp /= 2; + base = base.strict_mul(base); + } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.strict_mul(base) + } + /// Saturating integer addition. Computes `self + rhs`, saturating at /// the numeric bounds instead of overflowing. /// From 8c7a5b0338f3f168c8b5c8447f132e8983c26105 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 23 Sep 2023 11:50:02 -0700 Subject: [PATCH 008/297] add `#[track_caller]` to improve panic locations --- library/core/src/num/int_macros.rs | 14 ++++++++++++++ library/core/src/num/uint_macros.rs | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 8b3f742bf919..b9f794431fb1 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -481,6 +481,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_add(self, rhs: Self) -> Self { let (a, b) = self.overflowing_add(rhs); if unlikely!(b) {overflow_panic::add()} else {a} @@ -560,6 +561,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self { let (a, b) = self.overflowing_add_unsigned(rhs); if unlikely!(b) {overflow_panic::add()} else {a} @@ -613,6 +615,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_sub(self, rhs: Self) -> Self { let (a, b) = self.overflowing_sub(rhs); if unlikely!(b) {overflow_panic::sub()} else {a} @@ -692,6 +695,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self { let (a, b) = self.overflowing_sub_unsigned(rhs); if unlikely!(b) {overflow_panic::sub()} else {a} @@ -745,6 +749,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_mul(self, rhs: Self) -> Self { let (a, b) = self.overflowing_mul(rhs); if unlikely!(b) {overflow_panic::mul()} else {a} @@ -840,6 +845,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_div(self, rhs: Self) -> Self { let (a, b) = self.overflowing_div(rhs); if unlikely!(b) {overflow_panic::div()} else {a} @@ -909,6 +915,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_div_euclid(self, rhs: Self) -> Self { let (a, b) = self.overflowing_div_euclid(rhs); if unlikely!(b) {overflow_panic::div()} else {a} @@ -977,6 +984,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_rem(self, rhs: Self) -> Self { let (a, b) = self.overflowing_rem(rhs); if unlikely!(b) {overflow_panic::rem()} else {a} @@ -1045,6 +1053,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_rem_euclid(self, rhs: Self) -> Self { let (a, b) = self.overflowing_rem_euclid(rhs); if unlikely!(b) {overflow_panic::rem()} else {a} @@ -1121,6 +1130,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_neg(self) -> Self { let (a, b) = self.overflowing_neg(); if unlikely!(b) {overflow_panic::neg()} else {a} @@ -1174,6 +1184,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_shl(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shl(rhs); if unlikely!(b) {overflow_panic::shl()} else {a} @@ -1254,6 +1265,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_shr(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shr(rhs); if unlikely!(b) {overflow_panic::shr()} else {a} @@ -1337,6 +1349,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_abs(self) -> Self { if self.is_negative() { self.strict_neg() @@ -1410,6 +1423,7 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 2d8dbbe1f508..8d9713856057 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -489,6 +489,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_add(self, rhs: Self) -> Self { let (a, b) = self.overflowing_add(rhs); if unlikely!(b) {overflow_panic::add()} else {a} @@ -574,6 +575,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_add_signed(self, rhs: $SignedT) -> Self { let (a, b) = self.overflowing_add_signed(rhs); if unlikely!(b) {overflow_panic::add()} else {a} @@ -627,6 +629,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_sub(self, rhs: Self) -> Self { let (a, b) = self.overflowing_sub(rhs); if unlikely!(b) {overflow_panic::sub()} else {a} @@ -706,6 +709,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_mul(self, rhs: Self) -> Self { let (a, b) = self.overflowing_mul(rhs); if unlikely!(b) {overflow_panic::mul()} else {a} @@ -786,6 +790,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] + #[track_caller] pub const fn strict_div(self, rhs: Self) -> Self { self / rhs } @@ -840,6 +845,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] + #[track_caller] pub const fn strict_div_euclid(self, rhs: Self) -> Self { self / rhs } @@ -894,6 +900,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] + #[track_caller] pub const fn strict_rem(self, rhs: Self) -> Self { self % rhs } @@ -949,6 +956,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] + #[track_caller] pub const fn strict_rem_euclid(self, rhs: Self) -> Self { self % rhs } @@ -1171,6 +1179,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_neg(self) -> Self { let (a, b) = self.overflowing_neg(); if unlikely!(b) {overflow_panic::neg()} else {a} @@ -1224,6 +1233,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_shl(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shl(rhs); if unlikely!(b) {overflow_panic::shl()} else {a} @@ -1304,6 +1314,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_shr(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shr(rhs); if unlikely!(b) {overflow_panic::shr()} else {a} @@ -1402,6 +1413,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] pub const fn strict_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; From a43dc2b67cee8e56cbe73d36ec0a99c6b0f2dd59 Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Mon, 27 Nov 2023 12:49:09 +0530 Subject: [PATCH 009/297] stabilise bound_map --- library/core/src/ops/range.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index b419a738fbe3..e809273c9ed9 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -710,7 +710,6 @@ impl Bound { /// # Examples /// /// ``` - /// #![feature(bound_map)] /// use std::ops::Bound::*; /// /// let bound_string = Included("Hello, World!"); @@ -719,7 +718,6 @@ impl Bound { /// ``` /// /// ``` - /// #![feature(bound_map)] /// use std::ops::Bound; /// use Bound::*; /// @@ -728,7 +726,7 @@ impl Bound { /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); /// ``` #[inline] - #[unstable(feature = "bound_map", issue = "86026")] + #[stable(feature = "bound_map", since = "CURRENT_RUSTC_VERSION")] pub fn map U>(self, f: F) -> Bound { match self { Unbounded => Unbounded, From 6d17169104575315c7801ec7bc55dd3cb932fde8 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Tue, 28 Nov 2023 08:34:55 -0800 Subject: [PATCH 010/297] reword panic comments and add spaces to unlikely branches --- library/core/src/num/int_macros.rs | 68 +++++++++++++------------- library/core/src/num/overflow_panic.rs | 4 ++ library/core/src/num/uint_macros.rs | 52 ++++++++++---------- 3 files changed, 64 insertions(+), 60 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index b9f794431fb1..451a2e14fe95 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -451,7 +451,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict integer addition. Computes `self + rhs`, panicking @@ -461,7 +461,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -484,7 +484,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_add(self, rhs: Self) -> Self { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {overflow_panic::add()} else {a} + if unlikely!(b) { overflow_panic::add() } else { a } } /// Unchecked integer addition. Computes `self + rhs`, assuming overflow @@ -531,7 +531,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option { let (a, b) = self.overflowing_add_unsigned(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict addition with an unsigned integer. Computes `self + rhs`, @@ -541,7 +541,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -564,7 +564,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self { let (a, b) = self.overflowing_add_unsigned(rhs); - if unlikely!(b) {overflow_panic::add()} else {a} + if unlikely!(b) { overflow_panic::add() } else { a } } /// Checked integer subtraction. Computes `self - rhs`, returning `None` if @@ -585,7 +585,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict integer subtraction. Computes `self - rhs`, panicking if @@ -595,7 +595,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -618,7 +618,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_sub(self, rhs: Self) -> Self { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {overflow_panic::sub()} else {a} + if unlikely!(b) { overflow_panic::sub() } else { a } } /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow @@ -665,7 +665,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option { let (a, b) = self.overflowing_sub_unsigned(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict subtraction with an unsigned integer. Computes `self - rhs`, @@ -675,7 +675,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -698,7 +698,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self { let (a, b) = self.overflowing_sub_unsigned(rhs); - if unlikely!(b) {overflow_panic::sub()} else {a} + if unlikely!(b) { overflow_panic::sub() } else { a } } /// Checked integer multiplication. Computes `self * rhs`, returning `None` if @@ -719,7 +719,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict integer multiplication. Computes `self * rhs`, panicking if @@ -729,7 +729,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -752,7 +752,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_mul(self, rhs: Self) -> Self { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {overflow_panic::mul()} else {a} + if unlikely!(b) { overflow_panic::mul() } else { a } } /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow @@ -816,7 +816,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value @@ -848,7 +848,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_div(self, rhs: Self) -> Self { let (a, b) = self.overflowing_div(rhs); - if unlikely!(b) {overflow_panic::div()} else {a} + if unlikely!(b) { overflow_panic::div() } else { a } } /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, @@ -886,7 +886,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value @@ -918,7 +918,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_div_euclid(self, rhs: Self) -> Self { let (a, b) = self.overflowing_div_euclid(rhs); - if unlikely!(b) {overflow_panic::div()} else {a} + if unlikely!(b) { overflow_panic::div() } else { a } } /// Checked integer remainder. Computes `self % rhs`, returning `None` if @@ -956,7 +956,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. @@ -987,7 +987,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_rem(self, rhs: Self) -> Self { let (a, b) = self.overflowing_rem(rhs); - if unlikely!(b) {overflow_panic::rem()} else {a} + if unlikely!(b) { overflow_panic::rem() } else { a } } /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` @@ -1025,7 +1025,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. @@ -1056,7 +1056,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_rem_euclid(self, rhs: Self) -> Self { let (a, b) = self.overflowing_rem_euclid(rhs); - if unlikely!(b) {overflow_panic::rem()} else {a} + if unlikely!(b) { overflow_panic::rem() } else { a } } /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. @@ -1076,7 +1076,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Unchecked negation. Computes `-self`, assuming overflow cannot occur. @@ -1110,7 +1110,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1133,7 +1133,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_neg(self) -> Self { let (a, b) = self.overflowing_neg(); - if unlikely!(b) {overflow_panic::neg()} else {a} + if unlikely!(b) { overflow_panic::neg() } else { a } } /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger @@ -1154,7 +1154,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger @@ -1164,7 +1164,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1187,7 +1187,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_shl(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {overflow_panic::shl()} else {a} + if unlikely!(b) { overflow_panic::shl() } else { a } } /// Unchecked shift left. Computes `self << rhs`, assuming that @@ -1235,7 +1235,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is @@ -1245,7 +1245,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1268,7 +1268,7 @@ macro_rules! int_impl { #[track_caller] pub const fn strict_shr(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {overflow_panic::shr()} else {a} + if unlikely!(b) { overflow_panic::shr() } else { a } } /// Unchecked shift right. Computes `self >> rhs`, assuming that @@ -1329,7 +1329,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1403,7 +1403,7 @@ macro_rules! int_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// diff --git a/library/core/src/num/overflow_panic.rs b/library/core/src/num/overflow_panic.rs index b941fdb212a8..203037ffb43e 100644 --- a/library/core/src/num/overflow_panic.rs +++ b/library/core/src/num/overflow_panic.rs @@ -1,3 +1,7 @@ +//! Functions for panicking on overflow. +//! +//! In particular, these are used by the `strict_` methods on integers. + #[cold] #[track_caller] pub const fn add() -> ! { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 8d9713856057..9915ce385d94 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -459,7 +459,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict integer addition. Computes `self + rhs`, panicking @@ -469,7 +469,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -492,8 +492,8 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_add(self, rhs: Self) -> Self { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {overflow_panic::add()} else {a} - } + if unlikely!(b) { overflow_panic ::add()} else {a} + } /// Unchecked integer addition. Computes `self + rhs`, assuming overflow /// cannot occur. @@ -540,7 +540,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_add_signed(self, rhs: $SignedT) -> Option { let (a, b) = self.overflowing_add_signed(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict addition with a signed integer. Computes `self + rhs`, @@ -550,7 +550,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -578,8 +578,8 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_add_signed(self, rhs: $SignedT) -> Self { let (a, b) = self.overflowing_add_signed(rhs); - if unlikely!(b) {overflow_panic::add()} else {a} - } + if unlikely!(b) { overflow_panic ::add()} else {a} + } /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if overflow occurred. @@ -599,7 +599,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict integer subtraction. Computes `self - rhs`, panicking if @@ -609,7 +609,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -632,8 +632,8 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_sub(self, rhs: Self) -> Self { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {overflow_panic::sub()} else {a} - } + if unlikely!(b) { overflow_panic ::sub()} else {a} + } /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow /// cannot occur. @@ -679,7 +679,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict integer multiplication. Computes `self * rhs`, panicking if @@ -689,7 +689,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -712,8 +712,8 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_mul(self, rhs: Self) -> Self { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {overflow_panic::mul()} else {a} - } + if unlikely!(b) { overflow_panic ::mul()} else {a} + } /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow /// cannot occur. @@ -1147,7 +1147,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict negation. Computes `-self`, panicking unless `self == @@ -1159,7 +1159,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1182,7 +1182,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_neg(self) -> Self { let (a, b) = self.overflowing_neg(); - if unlikely!(b) {overflow_panic::neg()} else {a} + if unlikely!(b) { overflow_panic::neg() } else { a } } /// Checked shift left. Computes `self << rhs`, returning `None` @@ -1203,7 +1203,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger @@ -1213,7 +1213,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1236,7 +1236,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_shl(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {overflow_panic::shl()} else {a} + if unlikely!(b) { overflow_panic::shl() } else { a } } /// Unchecked shift left. Computes `self << rhs`, assuming that @@ -1284,7 +1284,7 @@ macro_rules! uint_impl { #[inline] pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is @@ -1294,7 +1294,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// @@ -1317,7 +1317,7 @@ macro_rules! uint_impl { #[track_caller] pub const fn strict_shr(self, rhs: u32) -> Self { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {overflow_panic::shr()} else {a} + if unlikely!(b) { overflow_panic::shr() } else { a } } /// Unchecked shift right. Computes `self >> rhs`, assuming that @@ -1393,7 +1393,7 @@ macro_rules! uint_impl { /// /// ## Overflow behavior /// - /// This function will always panic on overflow, regardless of if overflow checks are enabled. + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// # Examples /// From 01337bf1fda37e8fde134454394e27e2ae719a24 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 20:38:30 -0500 Subject: [PATCH 011/297] Remove `{,r}split_array_ref{,_mut}` methods from slices The functionality of these methods from `split_array` has been absorbed by the `slice_first_last_chunk` feature. This only affects the methods on slices, not those with the same name that are implemented on array types. Also adjusts testing to reflect this change. --- library/core/src/array/mod.rs | 8 +- library/core/src/slice/mod.rs | 170 +++------------------------------- library/core/tests/lib.rs | 1 + library/core/tests/slice.rs | 52 +++-------- 4 files changed, 31 insertions(+), 200 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index ebd4a8c05fe3..4f6eef4ef0d5 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -647,7 +647,7 @@ impl [T; N] { )] #[inline] pub fn split_array_ref(&self) -> (&[T; M], &[T]) { - (&self[..]).split_array_ref::() + (&self[..]).split_first_chunk::().unwrap() } /// Divides one mutable array reference into two at an index. @@ -680,7 +680,7 @@ impl [T; N] { )] #[inline] pub fn split_array_mut(&mut self) -> (&mut [T; M], &mut [T]) { - (&mut self[..]).split_array_mut::() + (&mut self[..]).split_first_chunk_mut::().unwrap() } /// Divides one array reference into two at an index from the end. @@ -725,7 +725,7 @@ impl [T; N] { )] #[inline] pub fn rsplit_array_ref(&self) -> (&[T], &[T; M]) { - (&self[..]).rsplit_array_ref::() + (&self[..]).split_last_chunk::().unwrap() } /// Divides one mutable array reference into two at an index from the end. @@ -758,7 +758,7 @@ impl [T; N] { )] #[inline] pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; M]) { - (&mut self[..]).rsplit_array_mut::() + (&mut self[..]).split_last_chunk_mut::().unwrap() } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 7c07a86e2dd0..9512d45740fd 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -367,6 +367,8 @@ impl [T] { /// first[1] = 4; /// } /// assert_eq!(x, &[5, 4, 2]); + /// + /// assert_eq!(None, x.first_chunk_mut::<4>()); /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] @@ -397,6 +399,8 @@ impl [T] { /// assert_eq!(first, &[0, 1]); /// assert_eq!(elements, &[2]); /// } + /// + /// assert_eq!(None, x.split_first_chunk::<4>()); /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] @@ -432,6 +436,8 @@ impl [T] { /// elements[0] = 5; /// } /// assert_eq!(x, &[3, 4, 5]); + /// + /// assert_eq!(None, x.split_first_chunk_mut::<4>()); /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] @@ -467,6 +473,8 @@ impl [T] { /// assert_eq!(elements, &[0]); /// assert_eq!(last, &[1, 2]); /// } + /// + /// assert_eq!(None, x.split_last_chunk::<4>()); /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] @@ -502,6 +510,8 @@ impl [T] { /// elements[0] = 5; /// } /// assert_eq!(x, &[5, 3, 4]); + /// + /// assert_eq!(None, x.split_last_chunk_mut::<4>()); /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] @@ -573,6 +583,8 @@ impl [T] { /// last[1] = 20; /// } /// assert_eq!(x, &[0, 10, 20]); + /// + /// assert_eq!(None, x.last_chunk_mut::<4>()); /// ``` #[unstable(feature = "slice_first_last_chunk", issue = "111774")] #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] @@ -2035,164 +2047,6 @@ impl [T] { } } - /// Divides one slice into an array and a remainder slice at an index. - /// - /// The array will contain all indices from `[0, N)` (excluding - /// the index `N` itself) and the slice will contain all - /// indices from `[N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let v = &[1, 2, 3, 4, 5, 6][..]; - /// - /// { - /// let (left, right) = v.split_array_ref::<0>(); - /// assert_eq!(left, &[]); - /// assert_eq!(right, [1, 2, 3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_array_ref::<2>(); - /// assert_eq!(left, &[1, 2]); - /// assert_eq!(right, [3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_array_ref::<6>(); - /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); - /// assert_eq!(right, []); - /// } - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[track_caller] - #[must_use] - pub fn split_array_ref(&self) -> (&[T; N], &[T]) { - let (a, b) = self.split_at(N); - // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) - unsafe { (&*(a.as_ptr() as *const [T; N]), b) } - } - - /// Divides one mutable slice into an array and a remainder slice at an index. - /// - /// The array will contain all indices from `[0, N)` (excluding - /// the index `N` itself) and the slice will contain all - /// indices from `[N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; - /// let (left, right) = v.split_array_mut::<2>(); - /// assert_eq!(left, &mut [1, 0]); - /// assert_eq!(right, [3, 0, 5, 6]); - /// left[1] = 2; - /// right[1] = 4; - /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[track_caller] - #[must_use] - pub fn split_array_mut(&mut self) -> (&mut [T; N], &mut [T]) { - let (a, b) = self.split_at_mut(N); - // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) - unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) } - } - - /// Divides one slice into an array and a remainder slice at an index from - /// the end. - /// - /// The slice will contain all indices from `[0, len - N)` (excluding - /// the index `len - N` itself) and the array will contain all - /// indices from `[len - N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let v = &[1, 2, 3, 4, 5, 6][..]; - /// - /// { - /// let (left, right) = v.rsplit_array_ref::<0>(); - /// assert_eq!(left, [1, 2, 3, 4, 5, 6]); - /// assert_eq!(right, &[]); - /// } - /// - /// { - /// let (left, right) = v.rsplit_array_ref::<2>(); - /// assert_eq!(left, [1, 2, 3, 4]); - /// assert_eq!(right, &[5, 6]); - /// } - /// - /// { - /// let (left, right) = v.rsplit_array_ref::<6>(); - /// assert_eq!(left, []); - /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); - /// } - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[must_use] - pub fn rsplit_array_ref(&self) -> (&[T], &[T; N]) { - assert!(N <= self.len()); - let (a, b) = self.split_at(self.len() - N); - // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at) - unsafe { (a, &*(b.as_ptr() as *const [T; N])) } - } - - /// Divides one mutable slice into an array and a remainder slice at an - /// index from the end. - /// - /// The slice will contain all indices from `[0, len - N)` (excluding - /// the index `N` itself) and the array will contain all - /// indices from `[len - N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; - /// let (left, right) = v.rsplit_array_mut::<4>(); - /// assert_eq!(left, [1, 0]); - /// assert_eq!(right, &mut [3, 0, 5, 6]); - /// left[1] = 2; - /// right[1] = 4; - /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[must_use] - pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; N]) { - assert!(N <= self.len()); - let (a, b) = self.split_at_mut(self.len() - N); - // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) - unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) } - } - /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. /// diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index df7b34ce73b4..15e58a4e53fb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -46,6 +46,7 @@ #![feature(pattern)] #![feature(sort_internals)] #![feature(slice_take)] +#![feature(slice_first_last_chunk)] #![feature(slice_from_ptr_range)] #![feature(slice_split_once)] #![feature(split_as_slice)] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 666452ead3f5..8bcb7ad1386a 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2399,37 +2399,45 @@ mod swap_panics { } #[test] -fn slice_split_array_mut() { +fn slice_split_first_chunk_mut() { let v = &mut [1, 2, 3, 4, 5, 6][..]; { - let (left, right) = v.split_array_mut::<0>(); + let (left, right) = v.split_first_chunk_mut::<0>().unwrap(); assert_eq!(left, &mut []); assert_eq!(right, [1, 2, 3, 4, 5, 6]); } { - let (left, right) = v.split_array_mut::<6>(); + let (left, right) = v.split_first_chunk_mut::<6>().unwrap(); assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); assert_eq!(right, []); } + + { + assert!(v.split_first_chunk_mut::<7>().is_none()); + } } #[test] -fn slice_rsplit_array_mut() { +fn slice_split_last_chunk_mut() { let v = &mut [1, 2, 3, 4, 5, 6][..]; { - let (left, right) = v.rsplit_array_mut::<0>(); + let (left, right) = v.split_last_chunk_mut::<0>().unwrap(); assert_eq!(left, [1, 2, 3, 4, 5, 6]); assert_eq!(right, &mut []); } { - let (left, right) = v.rsplit_array_mut::<6>(); + let (left, right) = v.split_last_chunk_mut::<6>().unwrap(); assert_eq!(left, []); assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); } + + { + assert!(v.split_last_chunk_mut::<7>().is_none()); + } } #[test] @@ -2444,38 +2452,6 @@ fn split_as_slice() { assert_eq!(split.as_slice(), &[]); } -#[should_panic] -#[test] -fn slice_split_array_ref_out_of_bounds() { - let v = &[1, 2, 3, 4, 5, 6][..]; - - let _ = v.split_array_ref::<7>(); -} - -#[should_panic] -#[test] -fn slice_split_array_mut_out_of_bounds() { - let v = &mut [1, 2, 3, 4, 5, 6][..]; - - let _ = v.split_array_mut::<7>(); -} - -#[should_panic] -#[test] -fn slice_rsplit_array_ref_out_of_bounds() { - let v = &[1, 2, 3, 4, 5, 6][..]; - - let _ = v.rsplit_array_ref::<7>(); -} - -#[should_panic] -#[test] -fn slice_rsplit_array_mut_out_of_bounds() { - let v = &mut [1, 2, 3, 4, 5, 6][..]; - - let _ = v.rsplit_array_mut::<7>(); -} - #[test] fn slice_split_once() { let v = &[1, 2, 3, 2, 4][..]; From 6318cbbe49f916c33bc3f4e5febe6cf0fcb7095a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Thu, 9 Nov 2023 16:21:03 +0100 Subject: [PATCH 012/297] `HashMap`/`HashSet`: forward `fold` implementations of iterators --- library/std/src/collections/hash/map.rs | 72 +++++++++++++++++++++++++ library/std/src/collections/hash/set.rs | 58 ++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 39e94902cfe5..b83c4d89c1e8 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2232,6 +2232,14 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Iter<'_, K, V> { @@ -2256,6 +2264,14 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IterMut<'_, K, V> { @@ -2290,6 +2306,14 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { @@ -2320,6 +2344,14 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (k, _)| f(acc, k)) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Keys<'_, K, V> { @@ -2343,6 +2375,14 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (_, v)| f(acc, v)) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Values<'_, K, V> { @@ -2366,6 +2406,14 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (_, v)| f(acc, v)) + } } #[stable(feature = "map_values_mut", since = "1.10.0")] impl ExactSizeIterator for ValuesMut<'_, K, V> { @@ -2396,6 +2444,14 @@ impl Iterator for IntoKeys { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (k, _)| f(acc, k)) + } } #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl ExactSizeIterator for IntoKeys { @@ -2426,6 +2482,14 @@ impl Iterator for IntoValues { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (_, v)| f(acc, v)) + } } #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl ExactSizeIterator for IntoValues { @@ -2456,6 +2520,14 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "drain", since = "1.6.0")] impl ExactSizeIterator for Drain<'_, K, V> { diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 8bc596082906..ea9239f0c476 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1500,6 +1500,14 @@ impl<'a, K> Iterator for Iter<'a, K> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Iter<'_, K> { @@ -1530,6 +1538,14 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { @@ -1560,6 +1576,14 @@ impl<'a, K> Iterator for Drain<'a, K> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Drain<'_, K> { @@ -1639,6 +1663,15 @@ where let (_, upper) = self.iter.size_hint(); (0, upper) } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, |acc, elt| if self.other.contains(elt) { f(acc, elt) } else { acc }) + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -1691,6 +1724,15 @@ where let (_, upper) = self.iter.size_hint(); (0, upper) } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, |acc, elt| if self.other.contains(elt) { acc } else { f(acc, elt) }) + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1736,6 +1778,14 @@ where fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1800,6 +1850,14 @@ where fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } } #[allow(dead_code)] From 7d369f98301047ca66d761549b53bde33b45ab7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Mon, 27 Nov 2023 10:30:12 +0100 Subject: [PATCH 013/297] Specialize `count` too --- library/std/src/collections/hash/map.rs | 32 +++++++++++++++++++++++++ library/std/src/collections/hash/set.rs | 12 ++++++++++ 2 files changed, 44 insertions(+) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index b83c4d89c1e8..fc27b6a67bfc 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2233,6 +2233,10 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { self.base.size_hint() } #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] fn fold(self, init: B, f: F) -> B where Self: Sized, @@ -2265,6 +2269,10 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { self.base.size_hint() } #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] fn fold(self, init: B, f: F) -> B where Self: Sized, @@ -2307,6 +2315,10 @@ impl Iterator for IntoIter { self.base.size_hint() } #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] fn fold(self, init: B, f: F) -> B where Self: Sized, @@ -2345,6 +2357,10 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { self.inner.size_hint() } #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] fn fold(self, init: B, mut f: F) -> B where Self: Sized, @@ -2376,6 +2392,10 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { self.inner.size_hint() } #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] fn fold(self, init: B, mut f: F) -> B where Self: Sized, @@ -2407,6 +2427,10 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { self.inner.size_hint() } #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] fn fold(self, init: B, mut f: F) -> B where Self: Sized, @@ -2445,6 +2469,10 @@ impl Iterator for IntoKeys { self.inner.size_hint() } #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] fn fold(self, init: B, mut f: F) -> B where Self: Sized, @@ -2483,6 +2511,10 @@ impl Iterator for IntoValues { self.inner.size_hint() } #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] fn fold(self, init: B, mut f: F) -> B where Self: Sized, diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index ea9239f0c476..dcb2fa0f771b 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1501,6 +1501,10 @@ impl<'a, K> Iterator for Iter<'a, K> { self.base.size_hint() } #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] fn fold(self, init: B, f: F) -> B where Self: Sized, @@ -1539,6 +1543,10 @@ impl Iterator for IntoIter { self.base.size_hint() } #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] fn fold(self, init: B, f: F) -> B where Self: Sized, @@ -1851,6 +1859,10 @@ where self.iter.size_hint() } #[inline] + fn count(self) -> usize { + self.iter.count() + } + #[inline] fn fold(self, init: B, f: F) -> B where Self: Sized, From 8bc123e321b82359c80ce50dae62e13db39c96cc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Feb 2022 15:09:37 +0100 Subject: [PATCH 014/297] Rework doc blocks headings by not turning them into links anymore and putting an anchor to their left side --- src/librustdoc/html/markdown.rs | 8 ++-- src/librustdoc/html/markdown/tests.rs | 53 +++++++++++++++++----- src/librustdoc/html/static/css/rustdoc.css | 3 ++ 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index abc27bcdf078..6a48b9367b85 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -558,12 +558,10 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator let level = std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL); - self.buf.push_back((Event::Html(format!("").into()), 0..0)); + self.buf.push_back((Event::Html(format!("").into()), 0..0)); - let start_tags = format!( - "\ - ", - ); + let start_tags = + format!("§"); return Some((Event::Html(start_tags.into()), 0..0)); } event diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 5eba1d0609f3..fcf777830246 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -311,24 +311,29 @@ fn test_header() { assert_eq!(output, expect, "original: {}", input); } - t("# Foo bar", "

Foo bar

"); + t( + "# Foo bar", + "

§Foo bar

", + ); t( "## Foo-bar_baz qux", "

\ - Foo-bar_baz qux

", + §\ + Foo-bar_baz qux\ + ", ); t( "### **Foo** *bar* baz!?!& -_qux_-%", "

\ - Foo \ - bar baz!?!& -qux-%\ + §\ + Foo bar baz!?!& -qux-%\

", ); t( "#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux", "
\ - Foo? & *bar?!* \ - baz ❤ #qux\ + §\ + Foo? & *bar?!* baz ❤ #qux\
", ); } @@ -351,12 +356,36 @@ fn test_header_ids_multiple_blocks() { assert_eq!(output, expect, "original: {}", input); } - t(&mut map, "# Example", "

Example

"); - t(&mut map, "# Panics", "

Panics

"); - t(&mut map, "# Example", "

Example

"); - t(&mut map, "# Search", "

Search

"); - t(&mut map, "# Example", "

Example

"); - t(&mut map, "# Panics", "

Panics

"); + t( + &mut map, + "# Example", + "

§Example

", + ); + t( + &mut map, + "# Panics", + "

§Panics

", + ); + t( + &mut map, + "# Example", + "

§Example

", + ); + t( + &mut map, + "# Search", + "

§Search

", + ); + t( + &mut map, + "# Example", + "

§Example

", + ); + t( + &mut map, + "# Panics", + "

§Panics

", + ); } #[test] diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b898eb5d381e..22fe5d8b0cfc 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -765,6 +765,9 @@ nav.sub { h2.section-header > .anchor { padding-right: 6px; } +.doc-anchor { + margin-right: 6px; +} .main-heading a:hover, .example-wrap .rust a:hover, From d1dd589a1df3d0e2b392a1bd4034efa43326a4c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Feb 2022 15:35:10 +0100 Subject: [PATCH 015/297] Allow links in doc blocks headings --- src/librustdoc/html/markdown.rs | 1 - src/librustdoc/html/markdown/tests.rs | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 6a48b9367b85..71ad9fc243c3 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -539,7 +539,6 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for event in &mut self.inner { match &event.0 { Event::End(Tag::Heading(..)) => break, - Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {} Event::Text(text) | Event::Code(text) => { id.extend(text.chars().filter_map(slugify)); self.buf.push_back(event); diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index fcf777830246..4dd176b3a692 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -336,6 +336,13 @@ fn test_header() { Foo? & *bar?!* baz ❤ #qux\ ", ); + t( + "# Foo [bar](https://hello.yo)", + "

\ + §\ + Foo bar\ +

", + ); } #[test] From 13b2156c68aa8e6565923dfad336461a393b75fa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Feb 2022 15:57:01 +0100 Subject: [PATCH 016/297] Update rustdoc headings tests --- tests/rustdoc-gui/docblock-details.goml | 2 +- .../rustdoc/disambiguate-anchors-header-29449.rs | 15 ++++++++++----- tests/rustdoc/remove-url-from-headings.rs | 11 +++++++---- tests/rustdoc/short-docblock.rs | 6 ++++-- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/rustdoc-gui/docblock-details.goml b/tests/rustdoc-gui/docblock-details.goml index 8e6d2ba824f7..4b8f5b54fac5 100644 --- a/tests/rustdoc-gui/docblock-details.goml +++ b/tests/rustdoc-gui/docblock-details.goml @@ -6,7 +6,7 @@ reload: // We first check that the headers in the `.top-doc` doc block still have their // bottom border. -assert-text: (".top-doc .docblock > h3", "Hello") +assert-text: (".top-doc .docblock > h3", "§Hello") assert-css: ( ".top-doc .docblock > h3", {"border-bottom": "1px solid #d2d2d2"}, diff --git a/tests/rustdoc/disambiguate-anchors-header-29449.rs b/tests/rustdoc/disambiguate-anchors-header-29449.rs index 38a4954fc139..1388af7df4b2 100644 --- a/tests/rustdoc/disambiguate-anchors-header-29449.rs +++ b/tests/rustdoc/disambiguate-anchors-header-29449.rs @@ -5,18 +5,23 @@ pub struct Foo; impl Foo { - // @has - '//*[@id="examples"]//a' 'Examples' - // @has - '//*[@id="panics"]//a' 'Panics' + // @has - '//*[@id="examples"]' 'Examples' + // @has - '//*[@id="examples"]/a[@href="#examples"]' '§' + // @has - '//*[@id="panics"]' 'Panics' + // @has - '//*[@id="panics"]/a[@href="#panics"]' '§' /// # Examples /// # Panics pub fn bar() {} - // @has - '//*[@id="examples-1"]//a' 'Examples' + // @has - '//*[@id="examples-1"]' 'Examples' + // @has - '//*[@id="examples-1"]/a[@href="#examples-1"]' '§' /// # Examples pub fn bar_1() {} - // @has - '//*[@id="examples-2"]//a' 'Examples' - // @has - '//*[@id="panics-1"]//a' 'Panics' + // @has - '//*[@id="examples-2"]' 'Examples' + // @has - '//*[@id="examples-2"]/a[@href="#examples-2"]' '§' + // @has - '//*[@id="panics-1"]' 'Panics' + // @has - '//*[@id="panics-1"]/a[@href="#panics-1"]' '§' /// # Examples /// # Panics pub fn bar_2() {} diff --git a/tests/rustdoc/remove-url-from-headings.rs b/tests/rustdoc/remove-url-from-headings.rs index 599c429a6e1d..8f4770286192 100644 --- a/tests/rustdoc/remove-url-from-headings.rs +++ b/tests/rustdoc/remove-url-from-headings.rs @@ -1,9 +1,12 @@ +// It actually checks that the link is kept in the headings as expected now. + #![crate_name = "foo"] // @has foo/fn.foo.html -// @!has - '//a[@href="http://a.a"]' '' -// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere' -// @has - '//a[@href="#another-one-urg"]' 'Another one urg' +// @has - '//a[@href="http://a.a"]' 'stuff' +// @has - '//*[@id="implementing-stuff-somewhere"]' 'Implementing stuff somewhere' +// @has - '//a[@href="http://b.b"]' 'one' +// @has - '//*[@id="another-one-urg"]' 'Another one urg' /// fooo /// @@ -13,5 +16,5 @@ /// /// # Another [one][two] urg /// -/// [two]: http://a.a +/// [two]: http://b.b pub fn foo() {} diff --git a/tests/rustdoc/short-docblock.rs b/tests/rustdoc/short-docblock.rs index 791d3547c9fe..151a42a9c9ee 100644 --- a/tests/rustdoc/short-docblock.rs +++ b/tests/rustdoc/short-docblock.rs @@ -2,8 +2,9 @@ // @has foo/index.html '//*[@class="desc docblock-short"]' 'fooo' // @!has foo/index.html '//*[@class="desc docblock-short"]/h1' 'fooo' -// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' '§' /// # fooo /// /// foo @@ -11,8 +12,9 @@ pub fn foo() {} // @has foo/index.html '//*[@class="desc docblock-short"]' 'mooood' // @!has foo/index.html '//*[@class="desc docblock-short"]/h2' 'mooood' -// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' '§' /// ## mooood /// /// foo mod From a4e5e074ac0dfb478c362af2dc37a9e333d86547 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Nov 2023 15:40:31 +0100 Subject: [PATCH 017/297] Make headings anchor hidden by default and show on hover --- src/librustdoc/html/static/css/rustdoc.css | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 22fe5d8b0cfc..52af572f7709 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -765,14 +765,30 @@ nav.sub { h2.section-header > .anchor { padding-right: 6px; } -.doc-anchor { - margin-right: 6px; +a.doc-anchor { + color: var(--main-color); + display: none; + position: absolute; + left: -17px; + /* We add this padding so that when the cursor moves from the heading's text to the anchor, + the anchor doesn't disappear. */ + padding-right: 5px; + /* And this padding is used to make the anchor larger and easier to click on. */ + padding-left: 3px; +} +*:hover > .doc-anchor { + display: block; +} +/* If the first element of the top doc block is a heading, we don't want to ever display its anchor +because of the `[-]` element which would overlap with it. */ +.top-doc > .docblock > *:first-child > .doc-anchor { + display: none !important; } .main-heading a:hover, .example-wrap .rust a:hover, .all-items a:hover, -.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, +.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover:not(.doc-anchor), .docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, .item-info a { text-decoration: underline; From 42fcba7a6731ec2a0fc6e75383fbd35dd75db41d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Nov 2023 16:40:48 +0100 Subject: [PATCH 018/297] Add tests for headings anchor and links in headings --- tests/rustdoc-gui/headers-color.goml | 8 +++---- tests/rustdoc-gui/headings-anchor.goml | 32 ++++++++++++++++++++++++++ tests/rustdoc/links-in-headings.rs | 14 +++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 tests/rustdoc-gui/headings-anchor.goml create mode 100644 tests/rustdoc/links-in-headings.rs diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml index 19185818f407..80d11c9c849c 100644 --- a/tests/rustdoc-gui/headers-color.goml +++ b/tests/rustdoc-gui/headers-color.goml @@ -1,4 +1,4 @@ -// This test check for headers text and background colors for the different themes. +// This test check for headings text and background colors for the different themes. define-function: ( "check-colors", @@ -45,7 +45,7 @@ call-function: ( "color": "#c5c5c5", "code_header_color": "#e6e1cf", "focus_background_color": "rgba(255, 236, 164, 0.06)", - "headings_color": "#39afd7", + "headings_color": "#c5c5c5", }, ) call-function: ( @@ -55,7 +55,7 @@ call-function: ( "color": "#ddd", "code_header_color": "#ddd", "focus_background_color": "#494a3d", - "headings_color": "#d2991d", + "headings_color": "#ddd", }, ) call-function: ( @@ -65,6 +65,6 @@ call-function: ( "color": "black", "code_header_color": "black", "focus_background_color": "#fdffd3", - "headings_color": "#3873ad", + "headings_color": "black", }, ) diff --git a/tests/rustdoc-gui/headings-anchor.goml b/tests/rustdoc-gui/headings-anchor.goml new file mode 100644 index 000000000000..f568caa3b07f --- /dev/null +++ b/tests/rustdoc-gui/headings-anchor.goml @@ -0,0 +1,32 @@ +// Test to ensure that the headings anchor behave as expected. +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" +show-text: true + +define-function: ( + "check-heading-anchor", + (heading_id), + block { + // The anchor should not be displayed by default. + assert-css: ("#" + |heading_id| + " .doc-anchor", { "display": "none" }) + // We ensure that hovering the heading makes the anchor visible. + move-cursor-to: "#" + |heading_id| + assert-css: ("#" + |heading_id| + ":hover .doc-anchor", { "display": "block" }) + // We then ensure that moving from the heading to the anchor doesn't make the anchor + // disappear. + move-cursor-to: "#" + |heading_id| + " .doc-anchor" + assert-css: ("#" + |heading_id| + " .doc-anchor:hover", { + "display": "block", + // We also ensure that there is no underline decoration. + "text-decoration-line": "none", + }) + } +) + +move-cursor-to: "#top-doc-prose-title" +// If the top documentation block first element is a heading, we should never display its anchor +// to prevent it from overlapping with the `[-]` element. +assert-css: ("#top-doc-prose-title:hover .doc-anchor", { "display": "none" }) + +call-function: ("check-heading-anchor", ("top-doc-prose-sub-heading")) +call-function: ("check-heading-anchor", ("top-doc-prose-sub-sub-heading")) +call-function: ("check-heading-anchor", ("you-know-the-drill")) diff --git a/tests/rustdoc/links-in-headings.rs b/tests/rustdoc/links-in-headings.rs new file mode 100644 index 000000000000..c5bee1a79750 --- /dev/null +++ b/tests/rustdoc/links-in-headings.rs @@ -0,0 +1,14 @@ +#![crate_name = "foo"] + +//! # Heading with [a link](https://a.com) inside +//! +//! And even with +//! +//! ## [multiple](https://b.com) [links](https://c.com) +//! +//! ! + +// @has 'foo/index.html' +// @has - '//h2/a[@href="https://a.com"]' 'a link' +// @has - '//h3/a[@href="https://b.com"]' 'multiple' +// @has - '//h3/a[@href="https://c.com"]' 'links' From d7c5358a57ec81449f52479f83e2de32f01d696e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 5 Dec 2023 16:10:23 +0100 Subject: [PATCH 019/297] Make all headings display the same by creating an anchor right beside them --- src/librustdoc/html/render/print_item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 131b1d608e68..b9a60a3fbdd1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -431,7 +431,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: write!( w, "

\ - {name}\ + {name}§\

{ITEM_TABLE_OPEN}", id = cx.derive_id(my_section.id()), name = my_section.name(), From bf4a20cfca442f211932e181a27baa070e3062cd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 5 Dec 2023 16:45:21 +0100 Subject: [PATCH 020/297] Generate section headings all from one place --- src/librustdoc/html/render/mod.rs | 20 +++- src/librustdoc/html/render/print_item.rs | 112 +++++++++++------------ 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index e076c1b92e6e..7c9be214d13e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1142,17 +1142,31 @@ impl<'a> AssocItemLink<'a> { } } -fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) { +pub fn write_section_heading( + w: &mut impl fmt::Write, + title: &str, + id: &str, + extra_class: Option<&str>, + extra: impl fmt::Display, +) { + let (extra_class, whitespace) = match extra_class { + Some(extra) => (extra, " "), + None => ("", ""), + }; write!( w, - "

\ + "

\ {title}\ §\ -

" + {extra}", ) .unwrap(); } +fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) { + write_section_heading(w, title, id, None, "") +} + pub(crate) fn render_all_impls( mut w: impl Write, cx: &mut Context<'_>, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index b9a60a3fbdd1..a50e59de0fb2 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -22,8 +22,8 @@ use super::{ item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw, - render_stability_since_raw_with_extra, AssocItemLink, AssocItemRender, Context, - ImplRenderingParameters, RenderMode, + render_stability_since_raw_with_extra, write_section_heading, AssocItemLink, AssocItemRender, + Context, ImplRenderingParameters, RenderMode, }; use crate::clean; use crate::config::ModuleSorting; @@ -428,13 +428,12 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: w.write_str(ITEM_TABLE_CLOSE); } last_section = Some(my_section); - write!( + write_section_heading( w, - "

\ - {name}§\ -

{ITEM_TABLE_OPEN}", - id = cx.derive_id(my_section.id()), - name = my_section.name(), + my_section.name(), + &cx.derive_id(my_section.id()), + None, + ITEM_TABLE_OPEN, ); } @@ -824,16 +823,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // Trait documentation write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) { - write!( - w, - "

\ - {1}§\ -

{2}", - id, title, extra_content - ) - } - fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) { let name = m.name.unwrap(); info!("Documenting {name} on {ty_name:?}", ty_name = t.name); @@ -867,10 +856,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_types.is_empty() { - write_small_section_header( + write_section_heading( w, - "required-associated-types", "Required Associated Types", + "required-associated-types", + None, "
", ); for t in required_types { @@ -879,10 +869,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); } if !provided_types.is_empty() { - write_small_section_header( + write_section_heading( w, - "provided-associated-types", "Provided Associated Types", + "provided-associated-types", + None, "
", ); for t in provided_types { @@ -892,10 +883,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_consts.is_empty() { - write_small_section_header( + write_section_heading( w, - "required-associated-consts", "Required Associated Constants", + "required-associated-consts", + None, "
", ); for t in required_consts { @@ -904,10 +896,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); } if !provided_consts.is_empty() { - write_small_section_header( + write_section_heading( w, - "provided-associated-consts", "Provided Associated Constants", + "provided-associated-consts", + None, "
", ); for t in provided_consts { @@ -918,10 +911,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // Output the documentation for each function individually if !required_methods.is_empty() || must_implement_one_of_functions.is_some() { - write_small_section_header( + write_section_heading( w, - "required-methods", "Required Methods", + "required-methods", + None, "
", ); @@ -939,10 +933,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); } if !provided_methods.is_empty() { - write_small_section_header( + write_section_heading( w, - "provided-methods", "Provided Methods", + "provided-methods", + None, "
", ); for m in provided_methods { @@ -959,10 +954,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let mut extern_crates = FxHashSet::default(); if !t.is_object_safe(cx.tcx()) { - write_small_section_header( + write_section_heading( w, - "object-safety", "Object Safety", + "object-safety", + None, &format!( "
This trait is not \ \ @@ -1006,7 +1002,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: foreign.sort_by_cached_key(|i| ImplString::new(i, cx)); if !foreign.is_empty() { - write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); + write_section_heading(w, "Implementations on Foreign Types", "foreign-impls", None, ""); for implementor in foreign { let provided_methods = implementor.inner_impl().provided_trait_methods(tcx); @@ -1031,10 +1027,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } } - write_small_section_header( + write_section_heading( w, - "implementors", "Implementors", + "implementors", + None, "
", ); for implementor in concrete { @@ -1043,10 +1040,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); if t.is_auto(tcx) { - write_small_section_header( + write_section_heading( w, - "synthetic-implementors", "Auto implementors", + "synthetic-implementors", + None, "
", ); for implementor in synthetic { @@ -1064,18 +1062,20 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } else { // even without any implementations to write in, we still want the heading and list, so the // implementors javascript file pulled in below has somewhere to write the impls into - write_small_section_header( + write_section_heading( w, - "implementors", "Implementors", + "implementors", + None, "
", ); if t.is_auto(tcx) { - write_small_section_header( + write_section_heading( w, - "synthetic-implementors", "Auto implementors", + "synthetic-implementors", + None, "
", ); } @@ -1258,11 +1258,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if let Some(inner_type) = &t.inner_type { - write!( - w, - "

\ - Aliased Type§

" - ); + write_section_heading(w, "Aliased Type", "aliased-type", None, ""); match inner_type { clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { @@ -1683,16 +1679,14 @@ fn item_variants( enum_def_id: DefId, ) { let tcx = cx.tcx(); - write!( + write_section_heading( w, - "

\ - Variants{}§\ -

\ - {}\ -
", - document_non_exhaustive_header(it), - document_non_exhaustive(it) + &format!("Variants{}", document_non_exhaustive_header(it)), + "variants", + Some("variants"), + format!("{}
", document_non_exhaustive(it)), ); + let should_show_enum_discriminant = should_show_enum_discriminant(cx, enum_def_id, variants); for (index, variant) in variants.iter_enumerated() { if variant.is_stripped() { @@ -1933,16 +1927,12 @@ fn item_fields( .peekable(); if let None | Some(CtorKind::Fn) = ctor_kind { if fields.peek().is_some() { - write!( - w, - "

\ - {}{}§\ -

\ - {}", + let title = format!( + "{}{}", if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, document_non_exhaustive_header(it), - document_non_exhaustive(it) ); + write_section_heading(w, &title, "fields", Some("fields"), document_non_exhaustive(it)); for (index, (field, ty)) in fields.enumerate() { let field_name = field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); From 17edbe7cad199e04345db5e810970576e8dc6f40 Mon Sep 17 00:00:00 2001 From: David Thomas Date: Sun, 10 Dec 2023 11:36:56 +0000 Subject: [PATCH 021/297] Use AtomicU8 instead of AtomicUsize in backtrace.rs --- library/std/src/backtrace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 7fcf2ee358c4..34ac09530502 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -93,7 +93,7 @@ use crate::env; use crate::ffi::c_void; use crate::fmt; use crate::panic::UnwindSafe; -use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use crate::sync::atomic::{AtomicU8, Ordering::Relaxed}; use crate::sync::LazyLock; use crate::sys_common::backtrace::{lock, output_filename, set_image_base}; use crate::vec::Vec; @@ -255,7 +255,7 @@ impl Backtrace { // Cache the result of reading the environment variables to make // backtrace captures speedy, because otherwise reading environment // variables every time can be somewhat slow. - static ENABLED: AtomicUsize = AtomicUsize::new(0); + static ENABLED: AtomicU8 = AtomicU8::new(0); match ENABLED.load(Relaxed) { 0 => {} 1 => return false, @@ -268,7 +268,7 @@ impl Backtrace { Err(_) => false, }, }; - ENABLED.store(enabled as usize + 1, Relaxed); + ENABLED.store(enabled as u8 + 1, Relaxed); enabled } From 605504c5bf5b02026dee02bfe682ff9adf3e22cd Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Sat, 19 Jun 2021 16:41:38 +0200 Subject: [PATCH 022/297] Add Ipv6Addr::is_ipv4_mapped This change consists of cherry-picking the content from the original PR[1], which got closed due to inactivity, and applying the following changes: * Resolving merge conflicts (obviously) * Linked to to_ipv4_mapped instead of to_ipv4 in the documentation (seems more appropriate) * Added the must_use and rustc_const_unstable attributes the original didn't have I think it's a reasonably useful method. [1] https://github.com/rust-lang/rust/pull/86490 --- library/core/src/net/ip_addr.rs | 25 +++++++++++++++++++++++++ library/core/tests/net/ip_addr.rs | 12 +++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 8bf15c736c34..65debde100a4 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1777,6 +1777,31 @@ impl Ipv6Addr { (self.segments()[0] & 0xff00) == 0xff00 } + /// Returns [`true`] if the address is an IPv4-mapped address (`::ffff:0:0/96`). + /// + /// IPv4-mapped addresses can be converted to their canonical IPv4 address with + /// [`to_ipv4_mapped`](Ipv6Addr::to_ipv4_mapped). + /// + /// # Examples + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// let ipv4_mapped = Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(); + /// assert_eq!(ipv4_mapped.is_ipv4_mapped(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff).is_ipv4_mapped(), true); + /// + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_ipv4_mapped(&self) -> bool { + matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + } + /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address, /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`]. /// diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index 7530fc084874..12ef678735d4 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -508,6 +508,7 @@ fn ipv6_properties() { | multicast_realm_local | multicast_site_local | multicast_organization_local; + let ipv4_mapped: u32 = 1 << 17; if ($mask & unspecified) == unspecified { assert!(ip!($s).is_unspecified()); @@ -584,6 +585,11 @@ fn ipv6_properties() { assert_eq!(ip!($s).multicast_scope().unwrap(), Ipv6MulticastScope::Global); } + if ($mask & ipv4_mapped) == ipv4_mapped { + assert!(ip!($s).is_ipv4_mapped()); + } else { + assert!(!ip!($s).is_ipv4_mapped()); + } } } @@ -602,6 +608,7 @@ fn ipv6_properties() { let multicast_site_local: u32 = 1 << 13; let multicast_organization_local: u32 = 1 << 14; let multicast_global: u32 = 1 << 15; + let ipv4_mapped: u32 = 1 << 17; check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified); @@ -614,7 +621,7 @@ fn ipv6_properties() { check!( "::ffff:127.0.0.1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1], - unicast_global + unicast_global | ipv4_mapped ); check!( @@ -982,6 +989,9 @@ fn ipv6_const() { const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); assert!(!IS_MULTICAST); + const IS_IPV4_MAPPED: bool = IP_ADDRESS.is_ipv4_mapped(); + assert!(!IS_IPV4_MAPPED); + const IP_V4: Option = IP_ADDRESS.to_ipv4(); assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1)); } From 1c5b2ce67cb8d698350b93143b8de342805145cc Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Tue, 19 Dec 2023 22:08:48 +0100 Subject: [PATCH 023/297] Docs: Use non-SeqCst in module example of atomics I done this for this reasons: 1. The example now shows that there is more Orderings than just SeqCst. 2. People who would copy from example would now have more suitable orderings for the job. 3. SeqCst is both much harder to reason about and not needed in most situations. IMHO, we should encourage people to think and use memory orderings that is suitable to task instead of blindly defaulting to SeqCst. --- library/core/src/sync/atomic.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5f1f41e68658..ad8c70c6a3ca 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -138,7 +138,7 @@ //! //! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting //! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only -//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since +//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault //! on read-only memory. //! @@ -181,12 +181,13 @@ //! let spinlock = Arc::new(AtomicUsize::new(1)); //! //! let spinlock_clone = Arc::clone(&spinlock); +//! //! let thread = thread::spawn(move|| { -//! spinlock_clone.store(0, Ordering::SeqCst); +//! spinlock_clone.store(0, Ordering::Release); //! }); //! //! // Wait for the other thread to release the lock -//! while spinlock.load(Ordering::SeqCst) != 0 { +//! while spinlock.load(Ordering::Acquire) != 0 { //! hint::spin_loop(); //! } //! @@ -203,7 +204,11 @@ //! //! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0); //! -//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst); +//! // Note that Relaxed ordering doesn't synchronize anything +//! // except the global thread counter itself. +//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed); +//! // Note that this number may not be true at the moment of printing +//! // because some other thread may have changed static value already. //! println!("live threads: {}", old_thread_count + 1); //! ``` From 7fee0881db85600a4a31442555a305d215064283 Mon Sep 17 00:00:00 2001 From: Yu Zeng Date: Fri, 29 Dec 2023 18:32:37 +0800 Subject: [PATCH 024/297] complete merge_nested_if with bugs. --- .../src/handlers/merge_nested_if.rs | 230 ++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + crates/ide-assists/src/tests/generated.rs | 15 ++ 3 files changed, 247 insertions(+) create mode 100644 crates/ide-assists/src/handlers/merge_nested_if.rs diff --git a/crates/ide-assists/src/handlers/merge_nested_if.rs b/crates/ide-assists/src/handlers/merge_nested_if.rs new file mode 100644 index 000000000000..af99d6fdef0b --- /dev/null +++ b/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -0,0 +1,230 @@ +use ide_db::syntax_helpers::node_ext::is_pattern_cond; +use syntax::{ + ast::{self, AstNode, BinaryOp}, + T, +}; + +use crate::{ + assist_context::{AssistContext, Assists}, + AssistId, AssistKind, +}; +/// Assist: merge_nested_if +/// +/// This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}` +/// This assist can only be applied with the cursor on `if`. +/// +/// ``` +/// fn main() { +/// i$0f x == 3 { if y == 4 { 1 } } +/// } +/// ``` +/// -> +/// ``` +/// fn main() { +/// if x == 3 && y == 4 { 1 } +/// } +/// ``` +pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let if_keyword = ctx.find_token_syntax_at_offset(T![if])?; + let expr = ast::IfExpr::cast(if_keyword.parent()?)?; + let if_range = if_keyword.text_range(); + let cursor_in_range = if_range.contains_range(ctx.selection_trimmed()); + if !cursor_in_range { + return None; + } + + //should not apply to if with else branch. + if expr.else_branch().is_some() { + return None; + } + + let cond = expr.condition()?; + let cond_range = cond.syntax().text_range(); + //should not apply for if-let + if is_pattern_cond(cond.clone()) { + return None; + } + + //check if the then branch is a nested if + let then_branch = expr.then_branch()?; + + let nested_if_to_merge = then_branch.syntax().descendants().find_map(ast::IfExpr::cast)?; + // should not apply to nested if with else branch. + if nested_if_to_merge.else_branch().is_some() { + return None; + } + let nested_if_cond = nested_if_to_merge.condition()?; + if is_pattern_cond(nested_if_cond.clone()) { + return None; + } + + let nested_if_then_branch = nested_if_to_merge.then_branch()?; + let then_branch_range = then_branch.syntax().text_range(); + + acc.add( + AssistId("merge_nested_if", AssistKind::RefactorRewrite), + "Merge nested if", + if_range, + |edit| { + let cond_text = if has_logic_op_or(&cond) { + format!("({})", cond.syntax().text()) + } else { + cond.syntax().text().to_string() + }; + + let nested_if_cond_text = if has_logic_op_or(&nested_if_cond) { + format!("({})", nested_if_cond.syntax().text()) + } else { + nested_if_cond.syntax().text().to_string() + }; + + let replace_cond = format!("{} && {}", cond_text, nested_if_cond_text); + + edit.replace(cond_range, replace_cond); + edit.replace(then_branch_range, nested_if_then_branch.syntax().text()); + }, + ) +} + +/// Returns whether the given if condition has logical operators. +fn has_logic_op_or(expr: &ast::Expr) -> bool { + match expr { + ast::Expr::BinExpr(bin_expr) => { + if let Some(kind) = bin_expr.op_kind() { + matches!(kind, BinaryOp::LogicOp(ast::LogicOp::Or)) + } else { + false + } + } + _ => false, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn merge_nested_if_test1() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } } }", + "fn f() { if x == 3 && y == 4 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test2() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 || y == 1 { if z == 4 { 1 } } }", + "fn f() { if (x == 3 || y == 1) && z == 4 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test3() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 && y == 1 { if z == 4 { 1 } } }", + "fn f() { if x == 3 && y == 1 && z == 4 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test4() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 && y == 1 { if z == 4 && q == 3 { 1 } } }", + "fn f() { if x == 3 && y == 1 && z == 4 && q == 3 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test5() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 && y == 1 { if z == 4 || q == 3 { 1 } } }", + "fn f() { if x == 3 && y == 1 && (z == 4 || q == 3) { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test6() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 || y == 1 { if z == 4 || q == 3 { 1 } } }", + "fn f() { if (x == 3 || y == 1) && (z == 4 || q == 3) { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test7() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 || y == 1 { if z == 4 && q == 3 { 1 } } }", + "fn f() { if (x == 3 || y == 1) && z == 4 && q == 3 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_if_with_else_branch() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } } else { 2 } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_nested_if_with_else_branch() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } else { 2 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_if_let() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f let Some(x) = y { if x == 4 { 1 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_nested_if_let() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f y == 0 { if let Some(x) = y { 1 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_if_with_else_branch_and_nested_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } } else { if z == 5 { 2 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_with_cursor_not_on_if() { + check_assist_not_applicable(merge_nested_if, "fn f() { if $0x==0 { if y == 3 { 1 } } }") + } + + #[test] + fn merge_nested_if_do_not_apply_with_mulpiple_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 0 { if y == 3 { 1 } else if y == 4 { 2 } } }", + ) + } + #[test] + fn merge_nested_if_do_not_apply_with_not_only_has_nested_if(){ + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 0 { if y == 3 { foo(); } foo(); } }", + ) + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 1e4d1c94f5be..1eb4903ab203 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -217,6 +217,7 @@ mod handlers { mod unqualify_method_call; mod wrap_return_type_in_result; mod into_to_qualified_from; + mod merge_nested_if; pub(crate) fn all() -> &'static [Handler] { &[ @@ -291,6 +292,7 @@ mod handlers { invert_if::invert_if, merge_imports::merge_imports, merge_match_arms::merge_match_arms, + merge_nested_if::merge_nested_if, move_bounds::move_bounds_to_where_clause, move_const_to_impl::move_const_to_impl, move_guard::move_arm_cond_to_match_guard, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index da5822bba9c8..79958a2292fb 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2051,6 +2051,21 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_merge_nested_if() { + check_doc_test( + "merge_nested_if", + r#####" + fn main() { + i$0f x == 3 { if y == 4 { 1 } } + }"#####, + r#####" + fn main() { + if x == 3 && y == 4 { 1 } + }"#####, + ) +} + #[test] fn doctest_move_arm_cond_to_match_guard() { check_doc_test( From edb9ad21bd8f0a692d100f6d3282e2b442fabc64 Mon Sep 17 00:00:00 2001 From: l1nxy Date: Mon, 1 Jan 2024 21:53:57 +0800 Subject: [PATCH 025/297] apply to only has nested if. --- crates/ide-assists/src/handlers/merge_nested_if.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/merge_nested_if.rs b/crates/ide-assists/src/handlers/merge_nested_if.rs index af99d6fdef0b..39db42faaea4 100644 --- a/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -47,6 +47,10 @@ pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt //check if the then branch is a nested if let then_branch = expr.then_branch()?; + let stmt = then_branch.stmt_list()?; + if stmt.statements().count() != 0 { + return None; + } let nested_if_to_merge = then_branch.syntax().descendants().find_map(ast::IfExpr::cast)?; // should not apply to nested if with else branch. @@ -221,7 +225,7 @@ mod tests { ) } #[test] - fn merge_nested_if_do_not_apply_with_not_only_has_nested_if(){ + fn merge_nested_if_do_not_apply_with_not_only_has_nested_if() { check_assist_not_applicable( merge_nested_if, "fn f() { i$0f x == 0 { if y == 3 { foo(); } foo(); } }", From b6a14ce5b8d1081ea330a0b85733fc6b646dfa33 Mon Sep 17 00:00:00 2001 From: l1nxy Date: Mon, 1 Jan 2024 22:11:45 +0800 Subject: [PATCH 026/297] fix doc test. --- .../src/handlers/merge_nested_if.rs | 32 +++++++++---------- crates/ide-assists/src/tests/generated.rs | 14 ++++---- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/crates/ide-assists/src/handlers/merge_nested_if.rs b/crates/ide-assists/src/handlers/merge_nested_if.rs index 39db42faaea4..206bc3e08be0 100644 --- a/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -8,22 +8,22 @@ use crate::{ assist_context::{AssistContext, Assists}, AssistId, AssistKind, }; -/// Assist: merge_nested_if -/// -/// This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}` -/// This assist can only be applied with the cursor on `if`. -/// -/// ``` -/// fn main() { -/// i$0f x == 3 { if y == 4 { 1 } } -/// } -/// ``` -/// -> -/// ``` -/// fn main() { -/// if x == 3 && y == 4 { 1 } -/// } -/// ``` +// Assist: merge_nested_if +// +// This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}` +// This assist can only be applied with the cursor on `if`. +// +// ``` +// fn main() { +// i$0f x == 3 { if y == 4 { 1 } } +// } +// ``` +// -> +// ``` +// fn main() { +// if x == 3 && y == 4 { 1 } +// } +// ``` pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let if_keyword = ctx.find_token_syntax_at_offset(T![if])?; let expr = ast::IfExpr::cast(if_keyword.parent()?)?; diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 79958a2292fb..d8b3b32a1aba 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2056,13 +2056,15 @@ fn doctest_merge_nested_if() { check_doc_test( "merge_nested_if", r#####" - fn main() { - i$0f x == 3 { if y == 4 { 1 } } - }"#####, +fn main() { + i$0f x == 3 { if y == 4 { 1 } } +} +"#####, r#####" - fn main() { - if x == 3 && y == 4 { 1 } - }"#####, +fn main() { + if x == 3 && y == 4 { 1 } +} +"#####, ) } From a3be52cbc0ff88f2e06e117b8e0843531832a37d Mon Sep 17 00:00:00 2001 From: l1nxy Date: Mon, 1 Jan 2024 22:31:04 +0800 Subject: [PATCH 027/297] tidy. --- crates/ide-assists/src/handlers/merge_nested_if.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/merge_nested_if.rs b/crates/ide-assists/src/handlers/merge_nested_if.rs index 206bc3e08be0..5742f60a1e35 100644 --- a/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -39,12 +39,13 @@ pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt } let cond = expr.condition()?; - let cond_range = cond.syntax().text_range(); //should not apply for if-let if is_pattern_cond(cond.clone()) { return None; } + let cond_range = cond.syntax().text_range(); + //check if the then branch is a nested if let then_branch = expr.then_branch()?; let stmt = then_branch.stmt_list()?; From 161d3055d192e36b87bfb0abd2c66f1356ed8681 Mon Sep 17 00:00:00 2001 From: l1nxy Date: Wed, 3 Jan 2024 09:48:49 +0800 Subject: [PATCH 028/297] use tail_expr(). --- crates/ide-assists/src/handlers/merge_nested_if.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/merge_nested_if.rs b/crates/ide-assists/src/handlers/merge_nested_if.rs index 5742f60a1e35..2f3136f027b0 100644 --- a/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -53,7 +53,10 @@ pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt return None; } - let nested_if_to_merge = then_branch.syntax().descendants().find_map(ast::IfExpr::cast)?; + let nested_if_to_merge = then_branch.tail_expr().and_then(|e| match e { + ast::Expr::IfExpr(e) => Some(e), + _ => None, + })?; // should not apply to nested if with else branch. if nested_if_to_merge.else_branch().is_some() { return None; @@ -232,4 +235,12 @@ mod tests { "fn f() { i$0f x == 0 { if y == 3 { foo(); } foo(); } }", ) } + + #[test] + fn merge_nested_if_do_not_apply_with_multiply_nested_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 0 { if y == 3 { foo(); } if z == 3 { 2 } } }", + ) + } } From b5c9982c0a0888bfc21e3a2c5c11575ecf2d1fb8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 3 Jan 2024 14:56:10 -0700 Subject: [PATCH 029/297] Add `crate_name` and URL to test cases --- tests/rustdoc/issue-35169-2.rs | 5 +++- tests/rustdoc/issue-35169.rs | 5 +++- tests/rustdoc/issue-35488.rs | 9 ++++--- tests/rustdoc/issue-41783.rs | 5 +++- tests/rustdoc/issue-42760.rs | 5 +++- tests/rustdoc/issue-43869.rs | 27 ++++++++++--------- tests/rustdoc/issue-46377.rs | 5 +++- tests/rustdoc/issue-46380-2.rs | 5 +++- tests/rustdoc/issue-46727.rs | 5 +++- .../issue-47197-blank-line-in-doc-block.rs | 5 +++- tests/rustdoc/issue-50159.rs | 5 +++- tests/rustdoc/issue-51236.rs | 5 +++- tests/rustdoc/issue-52873.rs | 3 +++ tests/rustdoc/issue-53689.rs | 1 + tests/rustdoc/issue-53812.rs | 5 +++- tests/rustdoc/issue-54478-demo-allocator.rs | 3 +++ tests/rustdoc/issue-54705.rs | 5 +++- tests/rustdoc/issue-55001.rs | 3 +++ tests/rustdoc/issue-55321.rs | 7 +++-- tests/rustdoc/issue-55364.rs | 19 +++++++------ 20 files changed, 95 insertions(+), 37 deletions(-) diff --git a/tests/rustdoc/issue-35169-2.rs b/tests/rustdoc/issue-35169-2.rs index f08466baf8b0..c82323ddc6aa 100644 --- a/tests/rustdoc/issue-35169-2.rs +++ b/tests/rustdoc/issue-35169-2.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/35169 +#![crate_name="foo"] + use std::ops::Deref; use std::ops::DerefMut; @@ -23,7 +26,7 @@ impl DerefMut for Bar { fn deref_mut(&mut self) -> &mut Foo { loop {} } } -// @has issue_35169_2/struct.Bar.html +// @has foo/struct.Bar.html // @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)' diff --git a/tests/rustdoc/issue-35169.rs b/tests/rustdoc/issue-35169.rs index 70a2265c8063..44afaf2e903a 100644 --- a/tests/rustdoc/issue-35169.rs +++ b/tests/rustdoc/issue-35169.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/35169 +#![crate_name="foo"] + use std::ops::Deref; pub struct Foo; @@ -18,7 +21,7 @@ impl Deref for Bar { fn deref(&self) -> &Foo { loop {} } } -// @has issue_35169/struct.Bar.html +// @has foo/struct.Bar.html // @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)' diff --git a/tests/rustdoc/issue-35488.rs b/tests/rustdoc/issue-35488.rs index c1bf9ceeac1c..ed955dcd770a 100644 --- a/tests/rustdoc/issue-35488.rs +++ b/tests/rustdoc/issue-35488.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/35488 +#![crate_name="foo"] + mod foo { pub enum Foo { Bar, @@ -5,9 +8,9 @@ mod foo { pub use self::Foo::*; } -// @has 'issue_35488/index.html' '//code' 'pub use self::Foo::*;' -// @has 'issue_35488/enum.Foo.html' +// @has 'foo/index.html' '//code' 'pub use self::Foo::*;' +// @has 'foo/enum.Foo.html' pub use self::foo::*; -// @has 'issue_35488/index.html' '//code' 'pub use std::option::Option::None;' +// @has 'foo/index.html' '//code' 'pub use std::option::Option::None;' pub use std::option::Option::None; diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/issue-41783.rs index 7578d49daa50..7782e148fd9f 100644 --- a/tests/rustdoc/issue-41783.rs +++ b/tests/rustdoc/issue-41783.rs @@ -1,4 +1,7 @@ -// @has issue_41783/struct.Foo.html +// https://github.com/rust-lang/rust/issues/41783 +#![crate_name="foo"] + +// @has foo/struct.Foo.html // @!hasraw - 'space' // @!hasraw - 'comment' // @hasraw - '#[outer]' diff --git a/tests/rustdoc/issue-42760.rs b/tests/rustdoc/issue-42760.rs index a5394c7d92a9..16c1705eb00c 100644 --- a/tests/rustdoc/issue-42760.rs +++ b/tests/rustdoc/issue-42760.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/42760 +#![crate_name="foo"] + #![allow(rustdoc::invalid_rust_codeblocks)] -// @has issue_42760/struct.NonGen.html +// @has foo/struct.NonGen.html // @has - '//h2' 'Example' /// Item docs. diff --git a/tests/rustdoc/issue-43869.rs b/tests/rustdoc/issue-43869.rs index 767d09d85588..9c4ed841f797 100644 --- a/tests/rustdoc/issue-43869.rs +++ b/tests/rustdoc/issue-43869.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/43869 +#![crate_name="foo"] + pub fn g() -> impl Iterator { Some(1u8).into_iter() } @@ -58,15 +61,15 @@ pub fn test_44731_4() -> Box> { Box::new(g()) } -// @has issue_43869/fn.g.html -// @has issue_43869/fn.h.html -// @has issue_43869/fn.i.html -// @has issue_43869/fn.j.html -// @has issue_43869/fn.k.html -// @has issue_43869/fn.l.html -// @has issue_43869/fn.m.html -// @has issue_43869/fn.n.html -// @has issue_43869/fn.o.html -// @has issue_43869/fn.test_44731_0.html -// @has issue_43869/fn.test_44731_1.html -// @has issue_43869/fn.test_44731_4.html +// @has foo/fn.g.html +// @has foo/fn.h.html +// @has foo/fn.i.html +// @has foo/fn.j.html +// @has foo/fn.k.html +// @has foo/fn.l.html +// @has foo/fn.m.html +// @has foo/fn.n.html +// @has foo/fn.o.html +// @has foo/fn.test_44731_0.html +// @has foo/fn.test_44731_1.html +// @has foo/fn.test_44731_4.html diff --git a/tests/rustdoc/issue-46377.rs b/tests/rustdoc/issue-46377.rs index 1311b4721e2f..aec74f493d43 100644 --- a/tests/rustdoc/issue-46377.rs +++ b/tests/rustdoc/issue-46377.rs @@ -1,3 +1,6 @@ -// @has 'issue_46377/index.html' '//*[@class="desc docblock-short"]' 'Check out this struct!' +// https://github.com/rust-lang/rust/issues/46377 +#![crate_name="foo"] + +// @has 'foo/index.html' '//*[@class="desc docblock-short"]' 'Check out this struct!' /// # Check out this struct! pub struct SomeStruct; diff --git a/tests/rustdoc/issue-46380-2.rs b/tests/rustdoc/issue-46380-2.rs index 7004d18dc66c..96ebd888eb5c 100644 --- a/tests/rustdoc/issue-46380-2.rs +++ b/tests/rustdoc/issue-46380-2.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/46380 +#![crate_name="foo"] + pub trait PublicTrait {} -// @has issue_46380_2/struct.PublicStruct.html +// @has foo/struct.PublicStruct.html pub struct PublicStruct; // @!has - '//*[@class="impl"]' 'impl PublicTrait for PublicStruct' diff --git a/tests/rustdoc/issue-46727.rs b/tests/rustdoc/issue-46727.rs index 8cfc4827a7f4..d0ce9c34f51b 100644 --- a/tests/rustdoc/issue-46727.rs +++ b/tests/rustdoc/issue-46727.rs @@ -1,7 +1,10 @@ +// https://github.com/rust-lang/rust/issues/46727 +#![crate_name="foo"] + // aux-build:issue-46727.rs extern crate issue_46727; -// @has issue_46727/trait.Foo.html +// @has foo/trait.Foo.html // @has - '//h3[@class="code-header"]' 'impl Foo for Bar<[T; 3]>' pub use issue_46727::{Foo, Bar}; diff --git a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs b/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs index 19994475de27..79492b4fa769 100644 --- a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs +++ b/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs @@ -1,4 +1,7 @@ -// @has issue_47197_blank_line_in_doc_block/fn.whose_woods_these_are_i_think_i_know.html +// https://github.com/rust-lang/rust/issues/47197 +#![crate_name="foo"] + +// @has foo/fn.whose_woods_these_are_i_think_i_know.html /** * snow diff --git a/tests/rustdoc/issue-50159.rs b/tests/rustdoc/issue-50159.rs index 13bedd5dbb02..0663ed5fc81f 100644 --- a/tests/rustdoc/issue-50159.rs +++ b/tests/rustdoc/issue-50159.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/50159 +#![crate_name="foo"] + pub trait Signal { type Item; } @@ -10,7 +13,7 @@ impl Signal2 for B where B: Signal { type Item2 = C; } -// @has issue_50159/struct.Switch.html +// @has foo/struct.Switch.html // @has - '//h3[@class="code-header"]' 'impl Send for Switchwhere ::Item: Send' // @has - '//h3[@class="code-header"]' 'impl Sync for Switchwhere ::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 diff --git a/tests/rustdoc/issue-51236.rs b/tests/rustdoc/issue-51236.rs index 04664805a886..30c81e796013 100644 --- a/tests/rustdoc/issue-51236.rs +++ b/tests/rustdoc/issue-51236.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/51236 +#![crate_name="foo"] + use std::marker::PhantomData; pub mod traits { @@ -6,7 +9,7 @@ pub mod traits { } } -// @has issue_51236/struct.Owned.html +// @has foo/struct.Owned.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: for<'a> ::traits::Owned<'a> { diff --git a/tests/rustdoc/issue-52873.rs b/tests/rustdoc/issue-52873.rs index 8000ce73bd42..12d3e3d7f944 100644 --- a/tests/rustdoc/issue-52873.rs +++ b/tests/rustdoc/issue-52873.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/52873 +#![crate_name="foo"] + // Regression test for #52873. We used to ICE due to unexpected // overflows when checking for "blanket impl inclusion". diff --git a/tests/rustdoc/issue-53689.rs b/tests/rustdoc/issue-53689.rs index 832140e061b5..7c2edd01a609 100644 --- a/tests/rustdoc/issue-53689.rs +++ b/tests/rustdoc/issue-53689.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53689 // aux-build:issue-53689.rs #![crate_name = "foo"] diff --git a/tests/rustdoc/issue-53812.rs b/tests/rustdoc/issue-53812.rs index dc1eb304c3d1..968ae0350433 100644 --- a/tests/rustdoc/issue-53812.rs +++ b/tests/rustdoc/issue-53812.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/53812 +#![crate_name="foo"] + pub trait MyIterator {} pub struct MyStruct(T); @@ -11,7 +14,7 @@ macro_rules! array_impls { } } -// @has issue_53812/trait.MyIterator.html +// @has foo/trait.MyIterator.html // @has - '//*[@id="implementors-list"]/*[@class="impl"][1]' 'MyStruct<[T; 0]>' // @has - '//*[@id="implementors-list"]/*[@class="impl"][2]' 'MyStruct<[T; 1]>' // @has - '//*[@id="implementors-list"]/*[@class="impl"][3]' 'MyStruct<[T; 2]>' diff --git a/tests/rustdoc/issue-54478-demo-allocator.rs b/tests/rustdoc/issue-54478-demo-allocator.rs index 4811f363bc97..39acee36d889 100644 --- a/tests/rustdoc/issue-54478-demo-allocator.rs +++ b/tests/rustdoc/issue-54478-demo-allocator.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/54478 +#![crate_name="foo"] + // Issue #54478: regression test showing that we can demonstrate // `#[global_allocator]` in code blocks built by `rustdoc`. // diff --git a/tests/rustdoc/issue-54705.rs b/tests/rustdoc/issue-54705.rs index a886eb0de242..00be0042fb03 100644 --- a/tests/rustdoc/issue-54705.rs +++ b/tests/rustdoc/issue-54705.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/54705 +#![crate_name="foo"] + pub trait ScopeHandle<'scope> {} -// @has issue_54705/struct.ScopeFutureContents.html +// @has foo/struct.ScopeFutureContents.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync" // diff --git a/tests/rustdoc/issue-55001.rs b/tests/rustdoc/issue-55001.rs index f6c7f9a3d082..b7d86a1c843b 100644 --- a/tests/rustdoc/issue-55001.rs +++ b/tests/rustdoc/issue-55001.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/55001 +#![crate_name="foo"] + // Regression test for issue #55001. Previously, we would incorrectly // cache certain trait selection results when checking for blanket impls, // resulting in an ICE when we tried to confirm the cached ParamCandidate diff --git a/tests/rustdoc/issue-55321.rs b/tests/rustdoc/issue-55321.rs index d3c2070d915d..e9be1ff854e0 100644 --- a/tests/rustdoc/issue-55321.rs +++ b/tests/rustdoc/issue-55321.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/55321 +#![crate_name="foo"] + #![feature(negative_impls)] -// @has issue_55321/struct.A.html +// @has foo/struct.A.html // @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl !Send for A" // @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ @@ -10,7 +13,7 @@ pub struct A(); impl !Send for A {} impl !Sync for A {} -// @has issue_55321/struct.B.html +// @has foo/struct.B.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl !Send for B" // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ diff --git a/tests/rustdoc/issue-55364.rs b/tests/rustdoc/issue-55364.rs index 941cb3ce1ca5..c07aba628c90 100644 --- a/tests/rustdoc/issue-55364.rs +++ b/tests/rustdoc/issue-55364.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/55364 +#![crate_name="foo"] + // First a module with inner documentation -// @has issue_55364/subone/index.html +// @has foo/subone/index.html // These foo/bar links in the module's documentation should refer inside `subone` // @has - '//section[@id="main-content"]/details[@open=""]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' // @has - '//section[@id="main-content"]/details[@open=""]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' @@ -8,12 +11,12 @@ pub mod subone { //! See either [foo] or [bar]. // This should refer to subone's `bar` - // @has issue_55364/subone/fn.foo.html + // @has foo/subone/fn.foo.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' /// See [bar] pub fn foo() {} // This should refer to subone's `foo` - // @has issue_55364/subone/fn.bar.html + // @has foo/subone/fn.bar.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' /// See [foo] pub fn bar() {} @@ -21,7 +24,7 @@ pub mod subone { // A module with outer documentation -// @has issue_55364/subtwo/index.html +// @has foo/subtwo/index.html // These foo/bar links in the module's documentation should not reference inside `subtwo` // @!has - '//section[@id="main-content"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' // @!has - '//section[@id="main-content"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' @@ -36,13 +39,13 @@ pub mod subtwo { // Despite the module's docs referring to the top level foo/bar, // this should refer to subtwo's `bar` - // @has issue_55364/subtwo/fn.foo.html + // @has foo/subtwo/fn.foo.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' /// See [bar] pub fn foo() {} // Despite the module's docs referring to the top level foo/bar, // this should refer to subtwo's `foo` - // @has issue_55364/subtwo/fn.bar.html + // @has foo/subtwo/fn.bar.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' /// See [foo] pub fn bar() {} @@ -57,7 +60,7 @@ pub fn bar() {} // This module refers to the outer foo/bar by means of `super::` -// @has issue_55364/subthree/index.html +// @has foo/subthree/index.html // This module should also refer to the top level foo/bar // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo' // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar' @@ -67,7 +70,7 @@ pub mod subthree { // Next we go *deeper* - In order to ensure it's not just "this or parent" // we test `crate::` and a `super::super::...` chain -// @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html +// @has foo/subfour/subfive/subsix/subseven/subeight/index.html // @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo' // @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar' pub mod subfour { From 35830fe218f245ef4a82199b8ee371fa89a52721 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 3 Jan 2024 15:30:09 -0700 Subject: [PATCH 030/297] rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 5) --- .../issue-52873.rs => rustdoc-ui/ice-blanket-impl-52873.rs} | 0 .../ice-blanket-impl-selection-55001.rs} | 0 ...sue-50159.rs => auto-trait-bounds-by-associated-type-50159.rs} | 0 ...ue-54705.rs => auto-trait-bounds-inference-variables-54705.rs} | 0 .../rustdoc/{issue-51236.rs => auto-trait-bounds-where-51236.rs} | 0 .../rustdoc/{issue-55321.rs => auto-trait-negative-impl-55321.rs} | 0 ...lank-line-in-doc-block.rs => blank-line-in-doc-block-47197.rs} | 0 .../{issue-54478-demo-allocator.rs => demo-allocator-54478.rs} | 0 tests/rustdoc/{issue-35169-2.rs => deref-mut-35169-2.rs} | 0 tests/rustdoc/{issue-35169.rs => deref-mut-35169.rs} | 0 tests/rustdoc/{issue-42760.rs => doc-attr-comment-mix-42760.rs} | 0 .../doctest-escape-boring-41783.codeblock.html} | 0 .../{issue-41783.rs => doctest/doctest-escape-boring-41783.rs} | 0 tests/rustdoc/{issue-35488.rs => enum-variant-reexport-35488.rs} | 0 tests/rustdoc/{issue-53689.rs => impl-blanket-53689.rs} | 0 tests/rustdoc/{issue-43869.rs => impl-trait-43869.rs} | 0 tests/rustdoc/{ => inline_cross}/auxiliary/issue-46727.rs | 0 .../rustdoc/{issue-46727.rs => inline_cross/const-eval-46727.rs} | 0 .../module-scope-name-resolution-55364.rs} | 0 ...-46380-2.rs => public-impl-mention-private-generic-46380-2.rs} | 0 tests/rustdoc/{issue-53812.rs => sort-53812.rs} | 0 tests/rustdoc/{issue-46377.rs => summary-header-46377.rs} | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename tests/{rustdoc/issue-52873.rs => rustdoc-ui/ice-blanket-impl-52873.rs} (100%) rename tests/{rustdoc/issue-55001.rs => rustdoc-ui/ice-blanket-impl-selection-55001.rs} (100%) rename tests/rustdoc/{issue-50159.rs => auto-trait-bounds-by-associated-type-50159.rs} (100%) rename tests/rustdoc/{issue-54705.rs => auto-trait-bounds-inference-variables-54705.rs} (100%) rename tests/rustdoc/{issue-51236.rs => auto-trait-bounds-where-51236.rs} (100%) rename tests/rustdoc/{issue-55321.rs => auto-trait-negative-impl-55321.rs} (100%) rename tests/rustdoc/{issue-47197-blank-line-in-doc-block.rs => blank-line-in-doc-block-47197.rs} (100%) rename tests/rustdoc/{issue-54478-demo-allocator.rs => demo-allocator-54478.rs} (100%) rename tests/rustdoc/{issue-35169-2.rs => deref-mut-35169-2.rs} (100%) rename tests/rustdoc/{issue-35169.rs => deref-mut-35169.rs} (100%) rename tests/rustdoc/{issue-42760.rs => doc-attr-comment-mix-42760.rs} (100%) rename tests/rustdoc/{issue-41783.codeblock.html => doctest/doctest-escape-boring-41783.codeblock.html} (100%) rename tests/rustdoc/{issue-41783.rs => doctest/doctest-escape-boring-41783.rs} (100%) rename tests/rustdoc/{issue-35488.rs => enum-variant-reexport-35488.rs} (100%) rename tests/rustdoc/{issue-53689.rs => impl-blanket-53689.rs} (100%) rename tests/rustdoc/{issue-43869.rs => impl-trait-43869.rs} (100%) rename tests/rustdoc/{ => inline_cross}/auxiliary/issue-46727.rs (100%) rename tests/rustdoc/{issue-46727.rs => inline_cross/const-eval-46727.rs} (100%) rename tests/rustdoc/{issue-55364.rs => intra-doc/module-scope-name-resolution-55364.rs} (100%) rename tests/rustdoc/{issue-46380-2.rs => public-impl-mention-private-generic-46380-2.rs} (100%) rename tests/rustdoc/{issue-53812.rs => sort-53812.rs} (100%) rename tests/rustdoc/{issue-46377.rs => summary-header-46377.rs} (100%) diff --git a/tests/rustdoc/issue-52873.rs b/tests/rustdoc-ui/ice-blanket-impl-52873.rs similarity index 100% rename from tests/rustdoc/issue-52873.rs rename to tests/rustdoc-ui/ice-blanket-impl-52873.rs diff --git a/tests/rustdoc/issue-55001.rs b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs similarity index 100% rename from tests/rustdoc/issue-55001.rs rename to tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs diff --git a/tests/rustdoc/issue-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs similarity index 100% rename from tests/rustdoc/issue-50159.rs rename to tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs diff --git a/tests/rustdoc/issue-54705.rs b/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs similarity index 100% rename from tests/rustdoc/issue-54705.rs rename to tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs diff --git a/tests/rustdoc/issue-51236.rs b/tests/rustdoc/auto-trait-bounds-where-51236.rs similarity index 100% rename from tests/rustdoc/issue-51236.rs rename to tests/rustdoc/auto-trait-bounds-where-51236.rs diff --git a/tests/rustdoc/issue-55321.rs b/tests/rustdoc/auto-trait-negative-impl-55321.rs similarity index 100% rename from tests/rustdoc/issue-55321.rs rename to tests/rustdoc/auto-trait-negative-impl-55321.rs diff --git a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs b/tests/rustdoc/blank-line-in-doc-block-47197.rs similarity index 100% rename from tests/rustdoc/issue-47197-blank-line-in-doc-block.rs rename to tests/rustdoc/blank-line-in-doc-block-47197.rs diff --git a/tests/rustdoc/issue-54478-demo-allocator.rs b/tests/rustdoc/demo-allocator-54478.rs similarity index 100% rename from tests/rustdoc/issue-54478-demo-allocator.rs rename to tests/rustdoc/demo-allocator-54478.rs diff --git a/tests/rustdoc/issue-35169-2.rs b/tests/rustdoc/deref-mut-35169-2.rs similarity index 100% rename from tests/rustdoc/issue-35169-2.rs rename to tests/rustdoc/deref-mut-35169-2.rs diff --git a/tests/rustdoc/issue-35169.rs b/tests/rustdoc/deref-mut-35169.rs similarity index 100% rename from tests/rustdoc/issue-35169.rs rename to tests/rustdoc/deref-mut-35169.rs diff --git a/tests/rustdoc/issue-42760.rs b/tests/rustdoc/doc-attr-comment-mix-42760.rs similarity index 100% rename from tests/rustdoc/issue-42760.rs rename to tests/rustdoc/doc-attr-comment-mix-42760.rs diff --git a/tests/rustdoc/issue-41783.codeblock.html b/tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html similarity index 100% rename from tests/rustdoc/issue-41783.codeblock.html rename to tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/doctest/doctest-escape-boring-41783.rs similarity index 100% rename from tests/rustdoc/issue-41783.rs rename to tests/rustdoc/doctest/doctest-escape-boring-41783.rs diff --git a/tests/rustdoc/issue-35488.rs b/tests/rustdoc/enum-variant-reexport-35488.rs similarity index 100% rename from tests/rustdoc/issue-35488.rs rename to tests/rustdoc/enum-variant-reexport-35488.rs diff --git a/tests/rustdoc/issue-53689.rs b/tests/rustdoc/impl-blanket-53689.rs similarity index 100% rename from tests/rustdoc/issue-53689.rs rename to tests/rustdoc/impl-blanket-53689.rs diff --git a/tests/rustdoc/issue-43869.rs b/tests/rustdoc/impl-trait-43869.rs similarity index 100% rename from tests/rustdoc/issue-43869.rs rename to tests/rustdoc/impl-trait-43869.rs diff --git a/tests/rustdoc/auxiliary/issue-46727.rs b/tests/rustdoc/inline_cross/auxiliary/issue-46727.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-46727.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-46727.rs diff --git a/tests/rustdoc/issue-46727.rs b/tests/rustdoc/inline_cross/const-eval-46727.rs similarity index 100% rename from tests/rustdoc/issue-46727.rs rename to tests/rustdoc/inline_cross/const-eval-46727.rs diff --git a/tests/rustdoc/issue-55364.rs b/tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs similarity index 100% rename from tests/rustdoc/issue-55364.rs rename to tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs diff --git a/tests/rustdoc/issue-46380-2.rs b/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs similarity index 100% rename from tests/rustdoc/issue-46380-2.rs rename to tests/rustdoc/public-impl-mention-private-generic-46380-2.rs diff --git a/tests/rustdoc/issue-53812.rs b/tests/rustdoc/sort-53812.rs similarity index 100% rename from tests/rustdoc/issue-53812.rs rename to tests/rustdoc/sort-53812.rs diff --git a/tests/rustdoc/issue-46377.rs b/tests/rustdoc/summary-header-46377.rs similarity index 100% rename from tests/rustdoc/issue-46377.rs rename to tests/rustdoc/summary-header-46377.rs From a704e21c3f2ee1c9215bd088d2880c8e396eacca Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 3 Jan 2024 15:30:46 -0700 Subject: [PATCH 031/297] Add `check-pass` to ice tests --- tests/rustdoc-ui/ice-blanket-impl-52873.rs | 1 + tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/rustdoc-ui/ice-blanket-impl-52873.rs b/tests/rustdoc-ui/ice-blanket-impl-52873.rs index 12d3e3d7f944..2520957bd005 100644 --- a/tests/rustdoc-ui/ice-blanket-impl-52873.rs +++ b/tests/rustdoc-ui/ice-blanket-impl-52873.rs @@ -1,3 +1,4 @@ +// check-pass // https://github.com/rust-lang/rust/issues/52873 #![crate_name="foo"] diff --git a/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs index b7d86a1c843b..babcb3dda143 100644 --- a/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs +++ b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs @@ -1,3 +1,4 @@ +// check-pass // https://github.com/rust-lang/rust/issues/55001 #![crate_name="foo"] From b83f487d1013f2277646cca478d5aa91d8b96f30 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 4 Jan 2024 11:02:20 +0100 Subject: [PATCH 032/297] Set the `in-rust-tree`` feature for all rust-analyzer{-proc-macro-srv} steps --- crates/mbe/Cargo.toml | 5 ++++- crates/proc-macro-srv-cli/Cargo.toml | 2 ++ crates/proc-macro-srv/Cargo.toml | 5 +++-- crates/proc-macro-srv/src/lib.rs | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/mbe/Cargo.toml b/crates/mbe/Cargo.toml index f50d796e139f..2046fa943a8a 100644 --- a/crates/mbe/Cargo.toml +++ b/crates/mbe/Cargo.toml @@ -27,5 +27,8 @@ span.workspace = true [dev-dependencies] test-utils.workspace = true +[features] +in-rust-tree = ["parser/in-rust-tree", "syntax/in-rust-tree"] + [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/proc-macro-srv-cli/Cargo.toml b/crates/proc-macro-srv-cli/Cargo.toml index 980eab2696bf..b9e4e534924b 100644 --- a/crates/proc-macro-srv-cli/Cargo.toml +++ b/crates/proc-macro-srv-cli/Cargo.toml @@ -14,6 +14,8 @@ proc-macro-api.workspace = true [features] sysroot-abi = ["proc-macro-srv/sysroot-abi"] +in-rust-tree = ["proc-macro-srv/in-rust-tree"] + [[bin]] name = "rust-analyzer-proc-macro-srv" diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index b6686fa5b65d..54dae4eba965 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -37,7 +37,8 @@ expect-test = "1.4.0" proc-macro-test.path = "./proc-macro-test" [features] -sysroot-abi = ["proc-macro-test/sysroot-abi"] +sysroot-abi = [] +in-rust-tree = ["mbe/in-rust-tree"] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index 7cd6df2df86d..f1575a5b0bd8 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -11,11 +11,12 @@ //! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)… #![cfg(any(feature = "sysroot-abi", rust_analyzer))] -#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)] +#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unreachable_pub, internal_features)] extern crate proc_macro; +extern crate rustc_driver as _; mod dylib; mod server; From ab2286935dc37c4463f21837e70a4a51a13ef9b0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 1 Jan 2024 14:37:33 +0100 Subject: [PATCH 033/297] Imply sysroot-abi feature when in-rust-tree is set --- crates/proc-macro-srv/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index 54dae4eba965..ba17ea6f7b43 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -38,7 +38,7 @@ proc-macro-test.path = "./proc-macro-test" [features] sysroot-abi = [] -in-rust-tree = ["mbe/in-rust-tree"] +in-rust-tree = ["mbe/in-rust-tree", "sysroot-abi"] [lints] workspace = true From d480525ce8548e6220b1fc49a1078e165b485c11 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 1 Jan 2024 14:58:26 +0100 Subject: [PATCH 034/297] Add extern crate rustc_driver to proc-macro-srv-cli --- crates/proc-macro-srv-cli/Cargo.toml | 2 +- crates/proc-macro-srv-cli/src/main.rs | 4 ++++ crates/rust-analyzer/src/bin/main.rs | 3 +-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/proc-macro-srv-cli/Cargo.toml b/crates/proc-macro-srv-cli/Cargo.toml index b9e4e534924b..2caa24b70328 100644 --- a/crates/proc-macro-srv-cli/Cargo.toml +++ b/crates/proc-macro-srv-cli/Cargo.toml @@ -22,4 +22,4 @@ name = "rust-analyzer-proc-macro-srv" path = "src/main.rs" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/proc-macro-srv-cli/src/main.rs b/crates/proc-macro-srv-cli/src/main.rs index 000a526e9f99..87f7555b02ce 100644 --- a/crates/proc-macro-srv-cli/src/main.rs +++ b/crates/proc-macro-srv-cli/src/main.rs @@ -1,5 +1,9 @@ //! A standalone binary for `proc-macro-srv`. //! Driver for proc macro server +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#[cfg(feature = "in-rust-tree")] +extern crate rustc_driver as _; + use std::io; fn main() -> std::io::Result<()> { diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 6f40a4c88ed8..7432f0f7a7ce 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -5,8 +5,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[cfg(feature = "in-rust-tree")] -#[allow(unused_extern_crates)] -extern crate rustc_driver; +extern crate rustc_driver as _; mod logger; mod rustc_wrapper; From 8390d2aca3d9845995968e47b65ae40fe06fc637 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 4 Jan 2024 10:44:18 +0100 Subject: [PATCH 035/297] Set sysroot-abi flag for proc-macro-cli when in-rust-tree is set --- crates/proc-macro-srv-cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/proc-macro-srv-cli/Cargo.toml b/crates/proc-macro-srv-cli/Cargo.toml index 2caa24b70328..a559ba017556 100644 --- a/crates/proc-macro-srv-cli/Cargo.toml +++ b/crates/proc-macro-srv-cli/Cargo.toml @@ -14,7 +14,7 @@ proc-macro-api.workspace = true [features] sysroot-abi = ["proc-macro-srv/sysroot-abi"] -in-rust-tree = ["proc-macro-srv/in-rust-tree"] +in-rust-tree = ["proc-macro-srv/in-rust-tree", "sysroot-abi"] [[bin]] From 79fa976864a2774e3b5377642d2c72147d240d2f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 4 Jan 2024 15:12:57 +0100 Subject: [PATCH 036/297] Set proc-macro-test/sysroot-abi with proc-macro-srv/sysroot-abi --- crates/proc-macro-srv/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index ba17ea6f7b43..9c4375559c11 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -37,7 +37,7 @@ expect-test = "1.4.0" proc-macro-test.path = "./proc-macro-test" [features] -sysroot-abi = [] +sysroot-abi = ["proc-macro-test/sysroot-abi"] in-rust-tree = ["mbe/in-rust-tree", "sysroot-abi"] [lints] From 4b7e0a0b56aa2446e670dfd6558380a1039a86aa Mon Sep 17 00:00:00 2001 From: Arlo Siemsen Date: Thu, 4 Jan 2024 11:40:56 -0600 Subject: [PATCH 037/297] Handle vendored sources when remapping paths --- src/bootstrap/src/core/builder.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 4e20babc55a6..3770d0687b24 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1799,15 +1799,20 @@ impl<'a> Builder<'a> { } if self.config.rust_remap_debuginfo { - // FIXME: handle vendored sources - let registry_src = t!(home::cargo_home()).join("registry").join("src"); let mut env_var = OsString::new(); - for entry in t!(std::fs::read_dir(registry_src)) { - if !env_var.is_empty() { - env_var.push("\t"); - } - env_var.push(t!(entry).path()); + if self.config.vendor { + let vendor = self.build.src.join("vendor"); + env_var.push(vendor); env_var.push("=/rust/deps"); + } else { + let registry_src = t!(home::cargo_home()).join("registry").join("src"); + for entry in t!(std::fs::read_dir(registry_src)) { + if !env_var.is_empty() { + env_var.push("\t"); + } + env_var.push(t!(entry).path()); + env_var.push("=/rust/deps"); + } } cargo.env("RUSTC_CARGO_REGISTRY_SRC_TO_REMAP", env_var); } From 08c44a6c246690304fd8d0b667af81a7a1b96e42 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 6 Jan 2024 08:41:11 +0300 Subject: [PATCH 038/297] fix ast::Path::segments implementation --- crates/syntax/src/ast/node_ext.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index a7e4899fb7ee..bc32220b4166 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -289,8 +289,15 @@ impl ast::Path { } pub fn segments(&self) -> impl Iterator + Clone { - successors(self.first_segment(), |p| { - p.parent_path().parent_path().and_then(|p| p.segment()) + let path_range = self.syntax().text_range(); + successors(self.first_segment(), move |p| { + p.parent_path().parent_path().and_then(|p| { + if path_range.contains_range(p.syntax().text_range()) { + p.segment() + } else { + None + } + }) }) } From 6403dbf0115b5cbde2e113965ecdeac38a5607ae Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 6 Jan 2024 12:51:44 +0300 Subject: [PATCH 039/297] fix ast::Path::segments callers that implicitly relied on behavior of previous implementation --- .../src/handlers/generate_constant.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/ide-assists/src/handlers/generate_constant.rs b/crates/ide-assists/src/handlers/generate_constant.rs index a4e8e7388f62..8b8c6ceee99e 100644 --- a/crates/ide-assists/src/handlers/generate_constant.rs +++ b/crates/ide-assists/src/handlers/generate_constant.rs @@ -50,6 +50,10 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O ty.original().display_source_code(ctx.db(), constant_module.into(), false).ok()?; let target = statement.syntax().parent()?.text_range(); let path = constant_token.syntax().ancestors().find_map(ast::Path::cast)?; + if path.parent_path().is_some() { + cov_mark::hit!(not_last_path_segment); + return None; + } let name_refs = path.segments().map(|s| s.name_ref()); let mut outer_exists = false; @@ -250,6 +254,18 @@ fn bar() -> i32 { } fn bar() -> i32 { foo::goo::A_CONSTANT +}"#, + ); + } + + #[test] + fn test_wont_apply_when_not_last_path_segment() { + cov_mark::check!(not_last_path_segment); + check_assist_not_applicable( + generate_constant, + r#"mod foo {} +fn bar() -> i32 { + foo::A_CON$0STANT::invalid_segment }"#, ); } From 89d6b011c4e104af34cb6f687af014c97992979e Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 6 Jan 2024 12:53:56 +0300 Subject: [PATCH 040/297] remove unnecessary ast::Path::segments alternatives --- crates/ide-db/src/imports/import_assets.rs | 5 ++--- crates/syntax/src/ast/node_ext.rs | 9 --------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index 652968d808fa..b834f517d491 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -681,11 +681,10 @@ fn path_import_candidate( Some(qualifier) => match sema.resolve_path(&qualifier) { None => { if qualifier.first_qualifier().map_or(true, |it| sema.resolve_path(&it).is_none()) { - let mut qualifier = qualifier - .segments_of_this_path_only_rev() + let qualifier = qualifier + .segments() .map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text()))) .collect::>>()?; - qualifier.reverse(); ImportCandidate::Path(PathImportCandidate { qualifier: Some(qualifier), name }) } else { return None; diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index bc32220b4166..daa463261ae3 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -283,11 +283,6 @@ impl ast::Path { self.first_qualifier_or_self().segment() } - // FIXME: Check usages of Self::segments, they might be wrong because of the logic of the bloew function - pub fn segments_of_this_path_only_rev(&self) -> impl Iterator + Clone { - self.qualifiers_and_self().filter_map(|it| it.segment()) - } - pub fn segments(&self) -> impl Iterator + Clone { let path_range = self.syntax().text_range(); successors(self.first_segment(), move |p| { @@ -305,10 +300,6 @@ impl ast::Path { successors(self.qualifier(), |p| p.qualifier()) } - pub fn qualifiers_and_self(&self) -> impl Iterator + Clone { - successors(Some(self.clone()), |p| p.qualifier()) - } - pub fn top_path(&self) -> ast::Path { let mut this = self.clone(); while let Some(path) = this.parent_path() { From 872951d2d995cda3f7817c7f505c0257c4a784d5 Mon Sep 17 00:00:00 2001 From: roife Date: Sat, 6 Jan 2024 20:07:38 +0800 Subject: [PATCH 041/297] Replace 'postorder' with 'reverse of preorder' to traverse the AST in path_transform --- crates/ide-db/src/path_transform.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 8c1a6e6e40b8..2d1af8fb7fbf 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -3,6 +3,7 @@ use crate::helpers::mod_path_to_ast; use either::Either; use hir::{AsAssocItem, HirDisplay, ModuleDef, SemanticsScope}; +use itertools::Itertools; use rustc_hash::FxHashMap; use syntax::{ ast::{self, make, AstNode}, @@ -227,11 +228,15 @@ struct Ctx<'a> { same_self_type: bool, } -fn postorder(item: &SyntaxNode) -> impl Iterator { - item.preorder().filter_map(|event| match event { - syntax::WalkEvent::Enter(_) => None, - syntax::WalkEvent::Leave(node) => Some(node), - }) +fn preorder_rev(item: &SyntaxNode) -> impl Iterator { + let x = item + .preorder() + .filter_map(|event| match event { + syntax::WalkEvent::Enter(node) => Some(node), + syntax::WalkEvent::Leave(_) => None, + }) + .collect_vec(); + x.into_iter().rev() } impl Ctx<'_> { @@ -239,12 +244,12 @@ impl Ctx<'_> { // `transform_path` may update a node's parent and that would break the // tree traversal. Thus all paths in the tree are collected into a vec // so that such operation is safe. - let paths = postorder(item).filter_map(ast::Path::cast).collect::>(); + let paths = preorder_rev(item).filter_map(ast::Path::cast).collect::>(); for path in paths { self.transform_path(path); } - postorder(item).filter_map(ast::Lifetime::cast).for_each(|lifetime| { + preorder_rev(item).filter_map(ast::Lifetime::cast).for_each(|lifetime| { if let Some(subst) = self.lifetime_substs.get(&lifetime.syntax().text().to_string()) { ted::replace(lifetime.syntax(), subst.clone_subtree().clone_for_update().syntax()); } @@ -263,7 +268,7 @@ impl Ctx<'_> { // `transform_path` may update a node's parent and that would break the // tree traversal. Thus all paths in the tree are collected into a vec // so that such operation is safe. - let paths = postorder(value).filter_map(ast::Path::cast).collect::>(); + let paths = preorder_rev(value).filter_map(ast::Path::cast).collect::>(); for path in paths { self.transform_path(path); } From ba952e65ffc09d49bb92dfe3beb4bd584c3e82e4 Mon Sep 17 00:00:00 2001 From: roife Date: Sat, 6 Jan 2024 20:09:51 +0800 Subject: [PATCH 042/297] Transform paths before make::fn_ --- .../src/handlers/generate_delegate_methods.rs | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index db1e0ceaec1e..9856c58a0b22 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -107,31 +107,48 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' |edit| { // Create the function let method_source = match ctx.sema.source(method) { - Some(source) => source.value, + Some(source) => { + let v = source.value.clone_for_update(); + let source_scope = ctx.sema.scope(v.syntax()); + let target_scope = ctx.sema.scope(strukt.syntax()); + if let (Some(s), Some(t)) = (source_scope, target_scope) { + PathTransform::generic_transformation(&t, &s).apply(v.syntax()); + } + v + } None => return, }; + let vis = method_source.visibility(); - let fn_name = make::name(&name); - let params = - method_source.param_list().unwrap_or_else(|| make::param_list(None, [])); - let type_params = method_source.generic_param_list(); - let arg_list = match method_source.param_list() { - Some(list) => convert_param_list_to_arg_list(list), - None => make::arg_list([]), - }; - let tail_expr = make::expr_method_call(field, make::name_ref(&name), arg_list); - let ret_type = method_source.ret_type(); let is_async = method_source.async_token().is_some(); let is_const = method_source.const_token().is_some(); let is_unsafe = method_source.unsafe_token().is_some(); + + let fn_name = make::name(&name); + + let type_params = method_source.generic_param_list(); + let where_clause = method_source.where_clause(); + let params = + method_source.param_list().unwrap_or_else(|| make::param_list(None, [])); + + // compute the `body` + let arg_list = method_source + .param_list() + .map(|list| convert_param_list_to_arg_list(list)) + .unwrap_or_else(|| make::arg_list([])); + + let tail_expr = make::expr_method_call(field, make::name_ref(&name), arg_list); let tail_expr_finished = if is_async { make::expr_await(tail_expr) } else { tail_expr }; let body = make::block_expr([], Some(tail_expr_finished)); + + let ret_type = method_source.ret_type(); + let f = make::fn_( vis, fn_name, type_params, - method_source.where_clause(), + where_clause, params, body, ret_type, @@ -184,12 +201,6 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let assoc_items = impl_def.get_or_create_assoc_item_list(); assoc_items.add_item(f.clone().into()); - if let Some((target, source)) = - ctx.sema.scope(strukt.syntax()).zip(ctx.sema.scope(method_source.syntax())) - { - PathTransform::generic_transformation(&target, &source).apply(f.syntax()); - } - if let Some(cap) = ctx.config.snippet_cap { edit.add_tabstop_before(cap, f) } From 05c4eef95e52f95aa938c5ec89773d0f21f9a872 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 3 May 2023 17:27:10 +0000 Subject: [PATCH 043/297] Make rev_locals a vec. --- compiler/rustc_mir_transform/src/gvn.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 2551c8aca883..e8b8baa15a9e 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -84,7 +84,7 @@ use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind}; use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar}; -use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; @@ -238,8 +238,10 @@ struct VnState<'body, 'tcx> { local_decls: &'body LocalDecls<'tcx>, /// Value stored in each local. locals: IndexVec>, - /// First local to be assigned that value. - rev_locals: FxHashMap>, + /// Locals that are assigned that value. + // This vector does not hold all the values of `VnIndex` that we create. + // It stops at the largest value created in the first phase of collecting assignments. + rev_locals: IndexVec>, values: FxIndexSet>, /// Values evaluated as constants if possible. evaluated: IndexVec>>, @@ -265,7 +267,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { param_env, local_decls, locals: IndexVec::from_elem(None, local_decls), - rev_locals: FxHashMap::default(), + rev_locals: IndexVec::default(), values: FxIndexSet::default(), evaluated: IndexVec::new(), next_opaque: Some(0), @@ -319,7 +321,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let is_sized = !self.tcx.features().unsized_locals || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); if is_sized { - self.rev_locals.entry(value).or_default().push(local); + self.rev_locals.ensure_contains_elem(value, Vec::new); + self.rev_locals[value].push(local); } } @@ -986,11 +989,11 @@ impl<'tcx> VnState<'_, 'tcx> { /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, /// return it. fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option { - let other = self.rev_locals.get(&index)?; + let other = self.rev_locals.get(index)?; other .iter() + .find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc)) .copied() - .find(|&other| self.ssa.assignment_dominates(self.dominators, other, loc)) } } From e26c9a42c6d9e0dab3eba4daf66785afeda2589b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 16 May 2023 10:19:08 +0000 Subject: [PATCH 044/297] Cache feature unsized locals + use smallvec. --- compiler/rustc_mir_transform/src/gvn.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e8b8baa15a9e..696067b1f0e6 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -99,6 +99,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut}; use rustc_span::def_id::DefId; use rustc_span::DUMMY_SP; use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT}; +use smallvec::SmallVec; use std::borrow::Cow; use crate::dataflow_const_prop::DummyMachine; @@ -241,13 +242,15 @@ struct VnState<'body, 'tcx> { /// Locals that are assigned that value. // This vector does not hold all the values of `VnIndex` that we create. // It stops at the largest value created in the first phase of collecting assignments. - rev_locals: IndexVec>, + rev_locals: IndexVec>, values: FxIndexSet>, /// Values evaluated as constants if possible. evaluated: IndexVec>>, /// Counter to generate different values. /// This is an option to stop creating opaques during replacement. next_opaque: Option, + /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. + feature_unsized_locals: bool, ssa: &'body SsaLocals, dominators: &'body Dominators, reused_locals: BitSet, @@ -271,6 +274,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { values: FxIndexSet::default(), evaluated: IndexVec::new(), next_opaque: Some(0), + feature_unsized_locals: tcx.features().unsized_locals, ssa, dominators, reused_locals: BitSet::new_empty(local_decls.len()), @@ -318,10 +322,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.locals[local] = Some(value); // Only register the value if its type is `Sized`, as we will emit copies of it. - let is_sized = !self.tcx.features().unsized_locals + let is_sized = !self.feature_unsized_locals || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); if is_sized { - self.rev_locals.ensure_contains_elem(value, Vec::new); + self.rev_locals.ensure_contains_elem(value, SmallVec::new); self.rev_locals[value].push(local); } } From 4ee01faaf074f3a985bb7325f2209f9ee224cb5e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 19:08:36 +0000 Subject: [PATCH 045/297] Do not re-simplify SSA locals. --- compiler/rustc_mir_transform/src/gvn.rs | 37 ++++++++++++------- .../issue_67019.main.GVN.panic-abort.diff | 4 -- .../issue_67019.main.GVN.panic-unwind.diff | 4 -- .../transmute.unreachable_mut.GVN.32bit.diff | 5 ++- .../transmute.unreachable_mut.GVN.64bit.diff | 5 ++- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 696067b1f0e6..e8b86d1327d6 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1015,23 +1015,32 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { } fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { - if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind + if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind { + self.simplify_place_projection(lhs, location); + // Do not try to simplify a constant, it's already in canonical shape. - && !matches!(rvalue, Rvalue::Use(Operand::Constant(_))) - { - if let Some(value) = self.simplify_rvalue(rvalue, location) { - if let Some(const_) = self.try_as_constant(value) { - *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); - } else if let Some(local) = self.try_as_local(value, location) - && *rvalue != Rvalue::Use(Operand::Move(local.into())) - { - *rvalue = Rvalue::Use(Operand::Copy(local.into())); - self.reused_locals.insert(local); - } + if matches!(rvalue, Rvalue::Use(Operand::Constant(_))) { + return; } - } else { - self.super_statement(stmt, location); + + let value = lhs + .as_local() + .and_then(|local| self.locals[local]) + .or_else(|| self.simplify_rvalue(rvalue, location)); + let Some(value) = value else { return }; + + if let Some(const_) = self.try_as_constant(value) { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + } else if let Some(local) = self.try_as_local(value, location) + && *rvalue != Rvalue::Use(Operand::Move(local.into())) + { + *rvalue = Rvalue::Use(Operand::Copy(local.into())); + self.reused_locals.insert(local); + } + + return; } + self.super_statement(stmt, location); } } diff --git a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff index fc0c8afd4cfd..dfab4959516d 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff @@ -33,10 +33,6 @@ + } + + ALLOC1 (size: 2, align: 1) { -+ 01 02 │ .. -+ } -+ -+ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff index cf4089598e73..b6d697323166 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff @@ -33,10 +33,6 @@ + } + + ALLOC1 (size: 2, align: 1) { -+ 01 02 │ .. -+ } -+ -+ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff index 93dfef96cf15..2dc3aa9afca2 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff @@ -15,10 +15,11 @@ StorageLive(_1); - StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); +- _1 = &mut (*_2); +- StorageDead(_2); + nop; + _2 = const {0x1 as &mut Never}; - _1 = &mut (*_2); -- StorageDead(_2); ++ _1 = const {0x1 as &mut Never}; + nop; unreachable; } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff index 93dfef96cf15..2dc3aa9afca2 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff @@ -15,10 +15,11 @@ StorageLive(_1); - StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); +- _1 = &mut (*_2); +- StorageDead(_2); + nop; + _2 = const {0x1 as &mut Never}; - _1 = &mut (*_2); -- StorageDead(_2); ++ _1 = const {0x1 as &mut Never}; + nop; unreachable; } From 7e39100586d717f5a350eb8704bcd8938d09419c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Dec 2023 13:00:48 +0000 Subject: [PATCH 046/297] Avoid recording no-op replacements. --- compiler/rustc_mir_transform/src/gvn.rs | 13 ++++---- .../const_allocation.main.GVN.after.32bit.mir | 4 +-- .../const_allocation.main.GVN.after.64bit.mir | 4 +-- ...const_allocation2.main.GVN.after.32bit.mir | 4 +-- ...const_allocation2.main.GVN.after.64bit.mir | 4 +-- ...const_allocation3.main.GVN.after.32bit.mir | 4 +-- ...const_allocation3.main.GVN.after.64bit.mir | 4 +-- .../const_prop/address_of_pair.fn0.GVN.diff | 6 ++-- ...for_slices.main.GVN.32bit.panic-abort.diff | 12 +++----- ...or_slices.main.GVN.32bit.panic-unwind.diff | 12 +++----- ...for_slices.main.GVN.64bit.panic-abort.diff | 12 +++----- ...or_slices.main.GVN.64bit.panic-unwind.diff | 12 +++----- .../const_prop/indirect_mutation.bar.GVN.diff | 6 ++-- .../const_prop/indirect_mutation.foo.GVN.diff | 6 ++-- ...e_variable_aggregate_mut_ref.main.GVN.diff | 6 ++-- .../mutable_variable_no_prop.main.GVN.diff | 6 ++-- ...r_expose_address.main.GVN.panic-abort.diff | 6 ++-- ..._expose_address.main.GVN.panic-unwind.diff | 6 ++-- .../const_prop/ref_deref.main.GVN.diff | 6 ++-- .../ref_deref_project.main.GVN.diff | 6 ++-- .../slice_len.main.GVN.32bit.panic-abort.diff | 6 ++-- ...slice_len.main.GVN.32bit.panic-unwind.diff | 6 ++-- .../slice_len.main.GVN.64bit.panic-abort.diff | 6 ++-- ...slice_len.main.GVN.64bit.panic-unwind.diff | 6 ++-- .../transmute.unreachable_mut.GVN.32bit.diff | 6 ++-- .../transmute.unreachable_mut.GVN.64bit.diff | 6 ++-- .../gvn.dereferences.GVN.panic-abort.diff | 18 ++++------- .../gvn.dereferences.GVN.panic-unwind.diff | 18 ++++------- tests/mir-opt/gvn.slices.GVN.panic-abort.diff | 12 +++----- .../mir-opt/gvn.slices.GVN.panic-unwind.diff | 12 +++----- ...xpression_elimination.GVN.panic-abort.diff | 30 +++++++------------ ...pression_elimination.GVN.panic-unwind.diff | 30 +++++++------------ ...variant_a-{closure#0}.PreCodegen.after.mir | 16 ++++++++++ ...mut_usize.PreCodegen.after.panic-abort.mir | 2 ++ ...ut_usize.PreCodegen.after.panic-unwind.mir | 2 ++ 35 files changed, 126 insertions(+), 189 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e8b86d1327d6..dc3af038d807 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -637,6 +637,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if place.is_indirect() && let Some(base) = self.locals[place.local] && let Some(new_local) = self.try_as_local(base, location) + && place.local != new_local { place.local = new_local; self.reused_locals.insert(new_local); @@ -646,8 +647,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { for i in 0..projection.len() { let elem = projection[i]; - if let ProjectionElem::Index(idx) = elem - && let Some(idx) = self.locals[idx] + if let ProjectionElem::Index(idx_local) = elem + && let Some(idx) = self.locals[idx_local] { if let Some(offset) = self.evaluated[idx].as_ref() && let Ok(offset) = self.ecx.read_target_usize(offset) @@ -655,9 +656,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { { projection.to_mut()[i] = ProjectionElem::ConstantIndex { offset, min_length, from_end: false }; - } else if let Some(new_idx) = self.try_as_local(idx, location) { - projection.to_mut()[i] = ProjectionElem::Index(new_idx); - self.reused_locals.insert(new_idx); + } else if let Some(new_idx_local) = self.try_as_local(idx, location) + && idx_local != new_idx_local + { + projection.to_mut()[i] = ProjectionElem::Index(new_idx_local); + self.reused_locals.insert(new_idx_local); } } } diff --git a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir index f089c6741fe8..10d99a134633 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir index 9cbbaf302bef..2f23dbe9ee4f 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir index dfa2d8081286..6499e3676aaa 100644 --- a/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir index 02b669871698..02f5ebab8477 100644 --- a/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir index 386a55ee6fa1..c95e696946a6 100644 --- a/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC4: &&Packed}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir index b9e98f8cd4c8..198bc8bd07ef 100644 --- a/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC2: &&Packed}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index 2285962fad1e..a044cfc62e20 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -24,9 +24,8 @@ bb0: { StorageLive(_2); - _2 = (const 1_i32, const false); -- StorageLive(_3); + _2 = const (1_i32, false); -+ nop; + StorageLive(_3); _3 = &raw mut (_2.1: bool); - _2 = (const 1_i32, const false); + _2 = const (1_i32, false); @@ -42,9 +41,8 @@ StorageDead(_6); _0 = _5; - StorageDead(_5); -- StorageDead(_3); -+ nop; + nop; + StorageDead(_3); StorageDead(_2); return; } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff index a42f9291324b..e1a93e314468 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff index f2d6de6621b1..91999145efb3 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff index a42f9291324b..e1a93e314468 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff index f2d6de6621b1..91999145efb3 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff index 7dd80d643607..b389080c4977 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff @@ -22,12 +22,10 @@ - _1 = (const 1_i32,); + _1 = const (1_i32,); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _3 = &raw mut (_1.0: i32); (*_3) = const 5_i32; -- StorageDead(_3); -+ nop; + StorageDead(_3); _2 = const (); StorageDead(_2); StorageLive(_4); diff --git a/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff index c4b647d9d2d2..c21869dece65 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff @@ -17,13 +17,11 @@ bb0: { StorageLive(_1); - _1 = (const 1_i32,); -- StorageLive(_2); + _1 = const (1_i32,); -+ nop; + StorageLive(_2); _2 = &mut (_1.0: i32); (*_2) = const 5_i32; -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageLive(_3); StorageLive(_4); _4 = (_1.0: i32); diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff index bc60546cd190..4ed7c9851479 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff @@ -19,17 +19,15 @@ bb0: { StorageLive(_1); - _1 = (const 42_i32, const 43_i32); -- StorageLive(_2); + _1 = const (42_i32, 43_i32); -+ nop; + StorageLive(_2); _2 = &mut _1; ((*_2).1: i32) = const 99_i32; StorageLive(_3); _3 = _1; _0 = const (); StorageDead(_3); -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff index d02c392f6bd6..e113f43a56e9 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff @@ -22,14 +22,12 @@ _1 = const 42_u32; StorageLive(_2); StorageLive(_3); -- StorageLive(_4); -+ nop; + StorageLive(_4); _4 = const {ALLOC0: *mut u32}; _3 = (*_4); _1 = move _3; StorageDead(_3); -- StorageDead(_4); -+ nop; + StorageDead(_4); _2 = const (); StorageDead(_2); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff index 425bc3ff6c1b..4e79b3ad5992 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff @@ -16,14 +16,12 @@ - StorageLive(_1); + nop; StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _3 = const _; _2 = &raw const (*_3); _1 = move _2 as usize (PointerExposeAddress); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_4); StorageLive(_5); _5 = _1; diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff index e9360ab8d629..fdc459b457ce 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff @@ -16,14 +16,12 @@ - StorageLive(_1); + nop; StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _3 = const _; _2 = &raw const (*_3); _1 = move _2 as usize (PointerExposeAddress); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_4); StorageLive(_5); _5 = _1; diff --git a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff index 8f9aa20524d0..56cbd00025ed 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -13,14 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); _4 = const _; _2 = &(*_4); - _1 = (*_2); -- StorageDead(_2); + _1 = const 4_i32; -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff index 8d38888b7d6a..d75c0c3b286b 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff @@ -13,14 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); _4 = const _; _2 = &((*_4).1: i32); - _1 = (*_2); -- StorageDead(_2); + _1 = const 5_i32; -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 8b2411e50ab0..803be994d9ae 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index 9b20d243f876..2a20e3eca599 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 8b2411e50ab0..803be994d9ae 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index 9b20d243f876..2a20e3eca599 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff index 2dc3aa9afca2..0ff31b1a9818 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff @@ -13,14 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); + StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); - _1 = &mut (*_2); -- StorageDead(_2); -+ nop; + _2 = const {0x1 as &mut Never}; + _1 = const {0x1 as &mut Never}; -+ nop; + StorageDead(_2); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff index 2dc3aa9afca2..0ff31b1a9818 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff @@ -13,14 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); + StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); - _1 = &mut (*_2); -- StorageDead(_2); -+ nop; + _2 = const {0x1 as &mut Never}; + _1 = const {0x1 as &mut Never}; -+ nop; + StorageDead(_2); unreachable; } } diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index a587b1e6b1de..46bf13985daf 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -72,8 +72,7 @@ bb2: { StorageDead(_7); StorageDead(_6); -- StorageLive(_8); -+ nop; + StorageLive(_8); _8 = &raw const (*_1); StorageLive(_9); StorageLive(_10); @@ -93,8 +92,7 @@ bb4: { StorageDead(_12); StorageDead(_11); -- StorageLive(_13); -+ nop; + StorageLive(_13); _13 = &raw mut (*_1); StorageLive(_14); StorageLive(_15); @@ -114,8 +112,7 @@ bb6: { StorageDead(_17); StorageDead(_16); -- StorageLive(_18); -+ nop; + StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); @@ -191,12 +188,9 @@ StorageDead(_32); StorageDead(_31); _0 = const (); -- StorageDead(_18); -- StorageDead(_13); -- StorageDead(_8); -+ nop; -+ nop; -+ nop; + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); return; } } diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index 6fdda5e99887..3e731ead859e 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -72,8 +72,7 @@ bb2: { StorageDead(_7); StorageDead(_6); -- StorageLive(_8); -+ nop; + StorageLive(_8); _8 = &raw const (*_1); StorageLive(_9); StorageLive(_10); @@ -93,8 +92,7 @@ bb4: { StorageDead(_12); StorageDead(_11); -- StorageLive(_13); -+ nop; + StorageLive(_13); _13 = &raw mut (*_1); StorageLive(_14); StorageLive(_15); @@ -114,8 +112,7 @@ bb6: { StorageDead(_17); StorageDead(_16); -- StorageLive(_18); -+ nop; + StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); @@ -191,12 +188,9 @@ StorageDead(_32); StorageDead(_31); _0 = const (); -- StorageDead(_18); -- StorageDead(_13); -- StorageDead(_8); -+ nop; -+ nop; -+ nop; + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); return; } } diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index ec4499803124..f3f9073909e3 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -194,15 +194,13 @@ - _23 = move _21; + _23 = const core::panicking::AssertKind::Eq; StorageLive(_24); -- StorageLive(_25); + StorageLive(_25); - _25 = &(*_15); -+ nop; + _25 = &(*_9); _24 = &(*_25); StorageLive(_26); -- StorageLive(_27); + StorageLive(_27); - _27 = &(*_16); -+ nop; + _27 = &(*_12); _26 = &(*_27); StorageLive(_28); @@ -293,15 +291,13 @@ - _49 = move _47; + _49 = const core::panicking::AssertKind::Eq; StorageLive(_50); -- StorageLive(_51); + StorageLive(_51); - _51 = &(*_41); -+ nop; + _51 = &(*_35); _50 = &(*_51); StorageLive(_52); -- StorageLive(_53); + StorageLive(_53); - _53 = &(*_42); -+ nop; + _53 = &(*_38); _52 = &(*_53); StorageLive(_54); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 56a78ca86946..383152cce5e2 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -194,15 +194,13 @@ - _23 = move _21; + _23 = const core::panicking::AssertKind::Eq; StorageLive(_24); -- StorageLive(_25); + StorageLive(_25); - _25 = &(*_15); -+ nop; + _25 = &(*_9); _24 = &(*_25); StorageLive(_26); -- StorageLive(_27); + StorageLive(_27); - _27 = &(*_16); -+ nop; + _27 = &(*_12); _26 = &(*_27); StorageLive(_28); @@ -293,15 +291,13 @@ - _49 = move _47; + _49 = const core::panicking::AssertKind::Eq; StorageLive(_50); -- StorageLive(_51); + StorageLive(_51); - _51 = &(*_41); -+ nop; + _51 = &(*_35); _50 = &(*_51); StorageLive(_52); -- StorageLive(_53); + StorageLive(_53); - _53 = &(*_42); -+ nop; + _53 = &(*_38); _52 = &(*_53); StorageLive(_54); diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index 0a747d3aef0f..3ecd4650d810 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -757,8 +757,7 @@ bb34: { StorageDead(_121); StorageDead(_120); -- StorageLive(_126); -+ nop; + StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); @@ -799,8 +798,7 @@ bb36: { StorageDead(_132); StorageDead(_131); -- StorageLive(_135); -+ nop; + StorageLive(_135); _135 = &mut _3; StorageLive(_136); StorageLive(_137); @@ -835,8 +833,7 @@ StorageDead(_141); StorageDead(_140); StorageLive(_144); -- StorageLive(_145); -+ nop; + StorageLive(_145); _145 = &raw const _3; StorageLive(_146); StorageLive(_147); @@ -870,8 +867,7 @@ bb40: { StorageDead(_151); StorageDead(_150); -- StorageLive(_154); -+ nop; + StorageLive(_154); _154 = &raw mut _3; StorageLive(_155); StorageLive(_156); @@ -906,13 +902,10 @@ StorageDead(_160); StorageDead(_159); _144 = const (); -- StorageDead(_154); -- StorageDead(_145); -+ nop; -+ nop; + StorageDead(_154); + StorageDead(_145); StorageDead(_144); -- StorageLive(_163); -+ nop; + StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); @@ -954,12 +947,9 @@ StorageDead(_169); StorageDead(_168); _0 = const (); -- StorageDead(_163); -- StorageDead(_135); -- StorageDead(_126); -+ nop; -+ nop; -+ nop; + StorageDead(_163); + StorageDead(_135); + StorageDead(_126); return; } } diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 119a4d9bbe90..bf448280b1ed 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -757,8 +757,7 @@ bb34: { StorageDead(_121); StorageDead(_120); -- StorageLive(_126); -+ nop; + StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); @@ -799,8 +798,7 @@ bb36: { StorageDead(_132); StorageDead(_131); -- StorageLive(_135); -+ nop; + StorageLive(_135); _135 = &mut _3; StorageLive(_136); StorageLive(_137); @@ -835,8 +833,7 @@ StorageDead(_141); StorageDead(_140); StorageLive(_144); -- StorageLive(_145); -+ nop; + StorageLive(_145); _145 = &raw const _3; StorageLive(_146); StorageLive(_147); @@ -870,8 +867,7 @@ bb40: { StorageDead(_151); StorageDead(_150); -- StorageLive(_154); -+ nop; + StorageLive(_154); _154 = &raw mut _3; StorageLive(_155); StorageLive(_156); @@ -906,13 +902,10 @@ StorageDead(_160); StorageDead(_159); _144 = const (); -- StorageDead(_154); -- StorageDead(_145); -+ nop; -+ nop; + StorageDead(_154); + StorageDead(_145); StorageDead(_144); -- StorageLive(_163); -+ nop; + StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); @@ -954,12 +947,9 @@ StorageDead(_169); StorageDead(_168); _0 = const (); -- StorageDead(_163); -- StorageDead(_135); -- StorageDead(_126); -+ nop; -+ nop; -+ nop; + StorageDead(_163); + StorageDead(_135); + StorageDead(_126); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index cc009e45e7e7..7370da5629c1 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -94,6 +94,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_9); _9 = _6; _10 = &_9; + StorageLive(_11); + StorageLive(_12); _11 = _4; _12 = _9; StorageLive(_13); @@ -103,6 +105,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _15 = Le(move _13, move _14); StorageDead(_14); StorageDead(_13); + StorageDead(_12); + StorageDead(_11); switchInt(move _15) -> [0: bb1, otherwise: bb2]; } @@ -124,6 +128,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_17); _17 = _5; _18 = &_17; + StorageLive(_19); + StorageLive(_20); _19 = _7; _20 = _17; StorageLive(_21); @@ -133,6 +139,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _23 = Le(move _21, move _22); StorageDead(_22); StorageDead(_21); + StorageDead(_20); + StorageDead(_19); switchInt(move _23) -> [0: bb3, otherwise: bb8]; } @@ -151,6 +159,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_25); _25 = _4; _26 = &_25; + StorageLive(_27); + StorageLive(_28); _27 = _6; _28 = _25; StorageLive(_29); @@ -160,6 +170,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _31 = Le(move _29, move _30); StorageDead(_30); StorageDead(_29); + StorageDead(_28); + StorageDead(_27); switchInt(move _31) -> [0: bb5, otherwise: bb6]; } @@ -181,6 +193,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_33); _33 = _7; _34 = &_33; + StorageLive(_35); + StorageLive(_36); _35 = _5; _36 = _33; StorageLive(_37); @@ -190,6 +204,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _0 = Le(move _37, move _38); StorageDead(_38); StorageDead(_37); + StorageDead(_36); + StorageDead(_35); StorageDead(_33); StorageDead(_34); StorageDead(_32); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir index a12411a04137..e4d9060d4cf5 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir @@ -50,6 +50,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { + StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -85,6 +86,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { bb3: { StorageDead(_4); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index a12411a04137..e4d9060d4cf5 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -50,6 +50,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { + StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -85,6 +86,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { bb3: { StorageDead(_4); + StorageDead(_7); return; } } From c4b10545250387876297777c2769b4195835b689 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Dec 2023 13:09:51 +0000 Subject: [PATCH 047/297] Move PointIndex to mir_dataflow. --- compiler/rustc_borrowck/src/nll.rs | 5 +- .../rustc_borrowck/src/region_infer/mod.rs | 6 +- .../rustc_borrowck/src/region_infer/values.rs | 104 ++---------------- .../src/type_check/liveness/local_use_map.rs | 8 +- .../src/type_check/liveness/mod.rs | 5 +- .../src/type_check/liveness/trace.rs | 9 +- compiler/rustc_borrowck/src/type_check/mod.rs | 9 +- compiler/rustc_mir_dataflow/src/lib.rs | 1 + compiler/rustc_mir_dataflow/src/points.rs | 94 ++++++++++++++++ 9 files changed, 127 insertions(+), 114 deletions(-) create mode 100644 compiler/rustc_mir_dataflow/src/points.rs diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5b764495922b..cc8208e9dc30 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -12,6 +12,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_mir_dataflow::ResultsCursor; use rustc_span::symbol::sym; use std::env; @@ -27,7 +28,7 @@ use crate::{ facts::{AllFacts, AllFactsExt, RustcFacts}, location::LocationTable, polonius, - region_infer::{values::RegionValueElements, RegionInferenceContext}, + region_infer::RegionInferenceContext, renumber, type_check::{self, MirTypeckRegionConstraints, MirTypeckResults}, universal_regions::UniversalRegions, @@ -98,7 +99,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(body)); + let elements = &Rc::new(DenseLocationMap::new(body)); // Run the MIR type-checker. let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } = diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 948221e94073..cbf01feae06a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -19,6 +19,7 @@ use rustc_middle::mir::{ use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; @@ -30,8 +31,7 @@ use crate::{ nll::PoloniusOutput, region_infer::reverse_sccs::ReverseSccGraph, region_infer::values::{ - LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, - ToElementIndex, + LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex, }, type_check::{free_region_relations::UniversalRegionRelations, Locations}, universal_regions::UniversalRegions, @@ -330,7 +330,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { universe_causes: FxIndexMap>, type_tests: Vec>, liveness_constraints: LivenessValues, - elements: &Rc, + elements: &Rc, ) -> Self { debug!("universal_regions: {:#?}", universal_regions); debug!("outlives constraints: {:#?}", outlives_constraints); diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index dc3ee849d004..01f7bfcadb6f 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -5,97 +5,13 @@ use rustc_index::bit_set::SparseBitMatrix; use rustc_index::interval::IntervalSet; use rustc_index::interval::SparseIntervalMatrix; use rustc_index::Idx; -use rustc_index::IndexVec; -use rustc_middle::mir::{BasicBlock, Body, Location}; +use rustc_middle::mir::{BasicBlock, Location}; use rustc_middle::ty::{self, RegionVid}; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use std::fmt::Debug; use std::rc::Rc; -use crate::dataflow::BorrowIndex; - -/// Maps between a `Location` and a `PointIndex` (and vice versa). -pub(crate) struct RegionValueElements { - /// For each basic block, how many points are contained within? - statements_before_block: IndexVec, - - /// Map backward from each point to the basic block that it - /// belongs to. - basic_blocks: IndexVec, - - num_points: usize, -} - -impl RegionValueElements { - pub(crate) fn new(body: &Body<'_>) -> Self { - let mut num_points = 0; - let statements_before_block: IndexVec = body - .basic_blocks - .iter() - .map(|block_data| { - let v = num_points; - num_points += block_data.statements.len() + 1; - v - }) - .collect(); - debug!("RegionValueElements: statements_before_block={:#?}", statements_before_block); - debug!("RegionValueElements: num_points={:#?}", num_points); - - let mut basic_blocks = IndexVec::with_capacity(num_points); - for (bb, bb_data) in body.basic_blocks.iter_enumerated() { - basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb)); - } - - Self { statements_before_block, basic_blocks, num_points } - } - - /// Total number of point indices - pub(crate) fn num_points(&self) -> usize { - self.num_points - } - - /// Converts a `Location` into a `PointIndex`. O(1). - pub(crate) fn point_from_location(&self, location: Location) -> PointIndex { - let Location { block, statement_index } = location; - let start_index = self.statements_before_block[block]; - PointIndex::new(start_index + statement_index) - } - - /// Converts a `Location` into a `PointIndex`. O(1). - pub(crate) fn entry_point(&self, block: BasicBlock) -> PointIndex { - let start_index = self.statements_before_block[block]; - PointIndex::new(start_index) - } - - /// Return the PointIndex for the block start of this index. - pub(crate) fn to_block_start(&self, index: PointIndex) -> PointIndex { - PointIndex::new(self.statements_before_block[self.basic_blocks[index]]) - } - - /// Converts a `PointIndex` back to a location. O(1). - pub(crate) fn to_location(&self, index: PointIndex) -> Location { - assert!(index.index() < self.num_points); - let block = self.basic_blocks[index]; - let start_index = self.statements_before_block[block]; - let statement_index = index.index() - start_index; - Location { block, statement_index } - } - - /// Sometimes we get point-indices back from bitsets that may be - /// out of range (because they round up to the nearest 2^N number - /// of bits). Use this function to filter such points out if you - /// like. - pub(crate) fn point_in_range(&self, index: PointIndex) -> bool { - index.index() < self.num_points - } -} - -rustc_index::newtype_index! { - /// A single integer representing a `Location` in the MIR control-flow - /// graph. Constructed efficiently from `RegionValueElements`. - #[orderable] - #[debug_format = "PointIndex({})"] - pub struct PointIndex {} -} +use crate::BorrowIndex; rustc_index::newtype_index! { /// A single integer representing a `ty::Placeholder`. @@ -123,7 +39,7 @@ pub(crate) enum RegionElement { /// an interval matrix storing liveness ranges for each region-vid. pub(crate) struct LivenessValues { /// The map from locations to points. - elements: Rc, + elements: Rc, /// For each region: the points where it is live. points: SparseIntervalMatrix, @@ -155,9 +71,9 @@ impl LiveLoans { impl LivenessValues { /// Create an empty map of regions to locations where they're live. - pub(crate) fn new(elements: Rc) -> Self { + pub(crate) fn new(elements: Rc) -> Self { LivenessValues { - points: SparseIntervalMatrix::new(elements.num_points), + points: SparseIntervalMatrix::new(elements.num_points()), elements, loans: None, } @@ -298,7 +214,7 @@ impl PlaceholderIndices { /// it would also contain various points from within the function. #[derive(Clone)] pub(crate) struct RegionValues { - elements: Rc, + elements: Rc, placeholder_indices: Rc, points: SparseIntervalMatrix, free_regions: SparseBitMatrix, @@ -313,14 +229,14 @@ impl RegionValues { /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. pub(crate) fn new( - elements: &Rc, + elements: &Rc, num_universal_regions: usize, placeholder_indices: &Rc, ) -> Self { let num_placeholders = placeholder_indices.len(); Self { elements: elements.clone(), - points: SparseIntervalMatrix::new(elements.num_points), + points: SparseIntervalMatrix::new(elements.num_points()), placeholder_indices: placeholder_indices.clone(), free_regions: SparseBitMatrix::new(num_universal_regions), placeholders: SparseBitMatrix::new(num_placeholders), @@ -486,7 +402,7 @@ impl ToElementIndex for ty::PlaceholderRegion { /// For debugging purposes, returns a pretty-printed string of the given points. pub(crate) fn pretty_print_points( - elements: &RegionValueElements, + elements: &DenseLocationMap, points: impl IntoIterator, ) -> String { pretty_print_region_elements( diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 7433c94a0bcd..da5456692ab1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -2,9 +2,9 @@ use rustc_data_structures::vec_linked_list as vll; use rustc_index::IndexVec; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location}; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use crate::def_use::{self, DefUse}; -use crate::region_infer::values::{PointIndex, RegionValueElements}; /// A map that cross references each local with the locations where it /// is defined (assigned), used, or dropped. Used during liveness @@ -60,7 +60,7 @@ impl vll::LinkElem for Appearance { impl LocalUseMap { pub(crate) fn build( live_locals: &[Local], - elements: &RegionValueElements, + elements: &DenseLocationMap, body: &Body<'_>, ) -> Self { let nones = IndexVec::from_elem(None, &body.local_decls); @@ -103,7 +103,7 @@ impl LocalUseMap { struct LocalUseMapBuild<'me> { local_use_map: &'me mut LocalUseMap, - elements: &'me RegionValueElements, + elements: &'me DenseLocationMap, // Vector used in `visit_local` to signal which `Local`s do we need // def/use/drop information on, constructed from `live_locals` (that @@ -144,7 +144,7 @@ impl LocalUseMapBuild<'_> { } fn insert( - elements: &RegionValueElements, + elements: &DenseLocationMap, first_appearance: &mut Option, appearances: &mut IndexVec, location: Location, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index e137bc1be0ae..51ae7d14e438 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_mir_dataflow::ResultsCursor; use std::rc::Rc; @@ -13,7 +14,7 @@ use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, location::LocationTable, - region_infer::values::{LivenessValues, RegionValueElements}, + region_infer::values::LivenessValues, universal_regions::UniversalRegions, }; @@ -34,7 +35,7 @@ mod trace; pub(super) fn generate<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, - elements: &Rc, + elements: &Rc, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, location_table: &LocationTable, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index c718d57bec39..eec128b5f1d5 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -7,6 +7,7 @@ use rustc_infer::infer::outlives::for_liveness; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::traits::query::DropckOutlivesResult; use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -17,7 +18,7 @@ use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::ResultsCursor; use crate::{ - region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements}, + region_infer::values::{self, LiveLoans}, type_check::liveness::local_use_map::LocalUseMap, type_check::liveness::polonius, type_check::NormalizeLocation, @@ -41,7 +42,7 @@ use crate::{ pub(super) fn trace<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, - elements: &Rc, + elements: &Rc, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, relevant_live_locals: Vec, @@ -105,7 +106,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { typeck: &'me mut TypeChecker<'typeck, 'tcx>, /// Defines the `PointIndex` mapping - elements: &'me RegionValueElements, + elements: &'me DenseLocationMap, /// MIR we are analyzing. body: &'me Body<'tcx>, @@ -570,7 +571,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { } fn make_all_regions_live( - elements: &RegionValueElements, + elements: &DenseLocationMap, typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeVisitable>, live_at: &IntervalSet, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9c0f53ddb86f..ea5593c09a97 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -35,6 +35,7 @@ use rustc_middle::ty::{ OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_middle::ty::{GenericArgsRef, UserArgs}; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -58,9 +59,7 @@ use crate::{ location::LocationTable, member_constraints::MemberConstraintSet, path_utils, - region_infer::values::{ - LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, - }, + region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices}, region_infer::TypeTest, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, @@ -133,7 +132,7 @@ pub(crate) fn type_check<'mir, 'tcx>( all_facts: &mut Option, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, - elements: &Rc, + elements: &Rc, upvars: &[&ty::CapturedPlace<'tcx>], use_polonius: bool, ) -> MirTypeckResults<'tcx> { @@ -545,7 +544,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let all_facts = &mut None; let mut constraints = Default::default(); let mut liveness_constraints = - LivenessValues::new(Rc::new(RegionValueElements::new(promoted_body))); + LivenessValues::new(Rc::new(DenseLocationMap::new(promoted_body))); // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index f0b21fd41847..b805f8ca23eb 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -34,6 +34,7 @@ mod errors; mod framework; pub mod impls; pub mod move_paths; +pub mod points; pub mod rustc_peek; pub mod storage; pub mod un_derefer; diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs new file mode 100644 index 000000000000..538e27ca1afb --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -0,0 +1,94 @@ +use rustc_index::Idx; +use rustc_index::IndexVec; +use rustc_middle::mir::{BasicBlock, Body, Location}; + +/// Maps between a `Location` and a `PointIndex` (and vice versa). +pub struct DenseLocationMap { + /// For each basic block, how many points are contained within? + statements_before_block: IndexVec, + + /// Map backward from each point to the basic block that it + /// belongs to. + basic_blocks: IndexVec, + + num_points: usize, +} + +impl DenseLocationMap { + #[inline] + pub fn new(body: &Body<'_>) -> Self { + let mut num_points = 0; + let statements_before_block: IndexVec = body + .basic_blocks + .iter() + .map(|block_data| { + let v = num_points; + num_points += block_data.statements.len() + 1; + v + }) + .collect(); + debug!("DenseLocationMap: statements_before_block={:#?}", statements_before_block); + debug!("DenseLocationMap: num_points={:#?}", num_points); + + let mut basic_blocks = IndexVec::with_capacity(num_points); + for (bb, bb_data) in body.basic_blocks.iter_enumerated() { + basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb)); + } + + Self { statements_before_block, basic_blocks, num_points } + } + + /// Total number of point indices + #[inline] + pub fn num_points(&self) -> usize { + self.num_points + } + + /// Converts a `Location` into a `PointIndex`. O(1). + #[inline] + pub fn point_from_location(&self, location: Location) -> PointIndex { + let Location { block, statement_index } = location; + let start_index = self.statements_before_block[block]; + PointIndex::new(start_index + statement_index) + } + + /// Converts a `Location` into a `PointIndex`. O(1). + #[inline] + pub fn entry_point(&self, block: BasicBlock) -> PointIndex { + let start_index = self.statements_before_block[block]; + PointIndex::new(start_index) + } + + /// Return the PointIndex for the block start of this index. + #[inline] + pub fn to_block_start(&self, index: PointIndex) -> PointIndex { + PointIndex::new(self.statements_before_block[self.basic_blocks[index]]) + } + + /// Converts a `PointIndex` back to a location. O(1). + #[inline] + pub fn to_location(&self, index: PointIndex) -> Location { + assert!(index.index() < self.num_points); + let block = self.basic_blocks[index]; + let start_index = self.statements_before_block[block]; + let statement_index = index.index() - start_index; + Location { block, statement_index } + } + + /// Sometimes we get point-indices back from bitsets that may be + /// out of range (because they round up to the nearest 2^N number + /// of bits). Use this function to filter such points out if you + /// like. + #[inline] + pub fn point_in_range(&self, index: PointIndex) -> bool { + index.index() < self.num_points + } +} + +rustc_index::newtype_index! { + /// A single integer representing a `Location` in the MIR control-flow + /// graph. Constructed efficiently from `DenseLocationMap`. + #[orderable] + #[debug_format = "PointIndex({})"] + pub struct PointIndex {} +} From da235ce92db7270ad66ed7cd3e7bc8260c0c9b60 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Dec 2023 13:32:02 +0000 Subject: [PATCH 048/297] Do not recompute liveness for DestinationPropagation. --- compiler/rustc_mir_dataflow/src/points.rs | 66 ++++++++++++++- compiler/rustc_mir_transform/src/dest_prop.rs | 81 +++++++++---------- 2 files changed, 102 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 538e27ca1afb..161560516da2 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -1,6 +1,9 @@ +use crate::framework::{visit_results, ResultsVisitable, ResultsVisitor}; +use rustc_index::bit_set::ChunkedBitSet; +use rustc_index::interval::SparseIntervalMatrix; use rustc_index::Idx; use rustc_index::IndexVec; -use rustc_middle::mir::{BasicBlock, Body, Location}; +use rustc_middle::mir::{self, BasicBlock, Body, Location}; /// Maps between a `Location` and a `PointIndex` (and vice versa). pub struct DenseLocationMap { @@ -92,3 +95,64 @@ rustc_index::newtype_index! { #[debug_format = "PointIndex({})"] pub struct PointIndex {} } + +/// Add points depending on the result of the given dataflow analysis. +pub fn save_as_intervals<'tcx, N, R>( + elements: &DenseLocationMap, + body: &mir::Body<'tcx>, + mut results: R, +) -> SparseIntervalMatrix +where + N: Idx, + R: ResultsVisitable<'tcx, FlowState = ChunkedBitSet>, +{ + let values = SparseIntervalMatrix::new(elements.num_points()); + let mut visitor = Visitor { elements, values }; + visit_results( + body, + body.basic_blocks.reverse_postorder().iter().copied(), + &mut results, + &mut visitor, + ); + visitor.values +} + +struct Visitor<'a, N: Idx> { + elements: &'a DenseLocationMap, + values: SparseIntervalMatrix, +} + +impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N> +where + N: Idx, +{ + type FlowState = ChunkedBitSet; + + fn visit_statement_after_primary_effect( + &mut self, + _results: &mut R, + state: &Self::FlowState, + _statement: &'mir mir::Statement<'tcx>, + location: Location, + ) { + let point = self.elements.point_from_location(location); + // Use internal iterator manually as it is much more efficient. + state.iter().fold((), |(), node| { + self.values.insert(node, point); + }); + } + + fn visit_terminator_after_primary_effect( + &mut self, + _results: &mut R, + state: &Self::FlowState, + _terminator: &'mir mir::Terminator<'tcx>, + location: Location, + ) { + let point = self.elements.point_from_location(location); + // Use internal iterator manually as it is much more efficient. + state.iter().fold((), |(), node| { + self.values.insert(node, point); + }); + } +} diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 49b0edc0db88..49bb114609c4 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -134,6 +134,7 @@ use crate::MirPass; use rustc_data_structures::fx::{FxIndexMap, IndexEntry, IndexOccupiedEntry}; use rustc_index::bit_set::BitSet; +use rustc_index::interval::SparseIntervalMatrix; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::HasLocalDecls; use rustc_middle::mir::{dump_mir, PassWhere}; @@ -143,7 +144,8 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::MaybeLiveLocals; -use rustc_mir_dataflow::{Analysis, ResultsCursor}; +use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex}; +use rustc_mir_dataflow::Analysis; pub struct DestinationPropagation; @@ -167,6 +169,13 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body); + let live = MaybeLiveLocals + .into_engine(tcx, body) + .pass_name("MaybeLiveLocals-DestinationPropagation") + .iterate_to_fixpoint(); + let points = DenseLocationMap::new(body); + let mut live = save_as_intervals(&points, body, live); + // In order to avoid having to collect data for every single pair of locals in the body, we // do not allow doing more than one merge for places that are derived from the same local at // once. To avoid missed opportunities, we instead iterate to a fixed point - we'll refer to @@ -190,22 +199,19 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { &mut allocations.candidates_reverse, ); trace!(?candidates); - let mut live = MaybeLiveLocals - .into_engine(tcx, body) - .iterate_to_fixpoint() - .into_results_cursor(body); - dest_prop_mir_dump(tcx, body, &mut live, round_count); + dest_prop_mir_dump(tcx, body, &points, &live, round_count); FilterInformation::filter_liveness( &mut candidates, - &mut live, + &points, + &live, &mut allocations.write_info, body, ); - // Because we do not update liveness information, it is unsound to use a local for more - // than one merge operation within a single round of optimizations. We store here which - // ones we have already used. + // Because we only filter once per round, it is unsound to use a local for more than + // one merge operation within a single round of optimizations. We store here which ones + // we have already used. let mut merged_locals: BitSet = BitSet::new_empty(body.local_decls.len()); // This is the set of merges we will apply this round. It is a subset of the candidates. @@ -224,9 +230,15 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { }) { break; } + + // Replace `src` by `dest` everywhere. merges.insert(*src, *dest); merged_locals.insert(*src); merged_locals.insert(*dest); + + // Update liveness information based on the merge we just performed. + // Every location where `src` was live, `dest` will be live. + live.union_rows(*src, *dest); } trace!(merging = ?merges); @@ -349,7 +361,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> { struct FilterInformation<'a, 'body, 'alloc, 'tcx> { body: &'body Body<'tcx>, - live: &'a mut ResultsCursor<'body, 'tcx, MaybeLiveLocals>, + points: &'a DenseLocationMap, + live: &'a SparseIntervalMatrix, candidates: &'a mut Candidates<'alloc>, write_info: &'alloc mut WriteInfo, at: Location, @@ -452,12 +465,14 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { /// locals as also being read from. fn filter_liveness<'b>( candidates: &mut Candidates<'alloc>, - live: &mut ResultsCursor<'b, 'tcx, MaybeLiveLocals>, + points: &DenseLocationMap, + live: &SparseIntervalMatrix, write_info_alloc: &'alloc mut WriteInfo, body: &'b Body<'tcx>, ) { let mut this = FilterInformation { body, + points, live, candidates, // We don't actually store anything at this scope, we just keep things here to be able @@ -472,13 +487,11 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { fn internal_filter_liveness(&mut self) { for (block, data) in traversal::preorder(self.body) { self.at = Location { block, statement_index: data.statements.len() }; - self.live.seek_after_primary_effect(self.at); self.write_info.for_terminator(&data.terminator().kind); self.apply_conflicts(); for (i, statement) in data.statements.iter().enumerate().rev() { self.at = Location { block, statement_index: i }; - self.live.seek_after_primary_effect(self.at); self.write_info.for_statement(&statement.kind, self.body); self.apply_conflicts(); } @@ -497,6 +510,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { None } }); + let at = self.points.point_from_location(self.at); self.candidates.filter_candidates_by( *p, |q| { @@ -508,7 +522,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { // calls or inline asm. Because of this, we also mark locals as // conflicting when both of them are written to in the same // statement. - if self.live.contains(q) || writes.contains(&q) { + if self.live.contains(q, at) || writes.contains(&q) { CandidateFilter::Remove } else { CandidateFilter::Keep @@ -801,38 +815,17 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool { fn dest_prop_mir_dump<'body, 'tcx>( tcx: TyCtxt<'tcx>, body: &'body Body<'tcx>, - live: &mut ResultsCursor<'body, 'tcx, MaybeLiveLocals>, + points: &DenseLocationMap, + live: &SparseIntervalMatrix, round: usize, ) { - let mut reachable = None; + let locals_live_at = |location| { + let location = points.point_from_location(location); + live.rows().filter(|&r| live.contains(r, location)).collect::>() + }; dump_mir(tcx, false, "DestinationPropagation-dataflow", &round, body, |pass_where, w| { - let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body)); - - match pass_where { - PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => { - live.seek_after_primary_effect(loc); - writeln!(w, " // live: {:?}", live.get())?; - } - PassWhere::AfterTerminator(bb) if reachable.contains(bb) => { - let loc = body.terminator_loc(bb); - live.seek_before_primary_effect(loc); - writeln!(w, " // live: {:?}", live.get())?; - } - - PassWhere::BeforeBlock(bb) if reachable.contains(bb) => { - live.seek_to_block_start(bb); - writeln!(w, " // live: {:?}", live.get())?; - } - - PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {} - - PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => { - writeln!(w, " // live: ")?; - } - - PassWhere::BeforeBlock(_) => { - writeln!(w, " // live: ")?; - } + if let PassWhere::BeforeLocation(loc) = pass_where { + writeln!(w, " // live: {:?}", locals_live_at(loc))?; } Ok(()) From 3082028be3707e2e4c88af2cf4d9d8ccc352a230 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Dec 2023 13:33:56 +0000 Subject: [PATCH 049/297] Fix comment. --- compiler/rustc_mir_dataflow/src/points.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 161560516da2..c111ab2b8819 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -30,8 +30,6 @@ impl DenseLocationMap { v }) .collect(); - debug!("DenseLocationMap: statements_before_block={:#?}", statements_before_block); - debug!("DenseLocationMap: num_points={:#?}", num_points); let mut basic_blocks = IndexVec::with_capacity(num_points); for (bb, bb_data) in body.basic_blocks.iter_enumerated() { @@ -55,7 +53,7 @@ impl DenseLocationMap { PointIndex::new(start_index + statement_index) } - /// Converts a `Location` into a `PointIndex`. O(1). + /// Returns the `PointIndex` for the first statement in the given `BasicBlock`. O(1). #[inline] pub fn entry_point(&self, block: BasicBlock) -> PointIndex { let start_index = self.statements_before_block[block]; From 1d6723a77a642850e60559c7d9c64b4b5233c9be Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Jan 2024 20:09:26 +0000 Subject: [PATCH 050/297] Use for_each instead of fold. --- compiler/rustc_mir_dataflow/src/points.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index c111ab2b8819..ff17ce1fe079 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -135,7 +135,7 @@ where ) { let point = self.elements.point_from_location(location); // Use internal iterator manually as it is much more efficient. - state.iter().fold((), |(), node| { + state.iter().for_each(|node| { self.values.insert(node, point); }); } @@ -149,7 +149,7 @@ where ) { let point = self.elements.point_from_location(location); // Use internal iterator manually as it is much more efficient. - state.iter().fold((), |(), node| { + state.iter().for_each(|node| { self.values.insert(node, point); }); } From 3afeb241981a37d90b2f48f87322532e5552efff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 8 Jan 2024 11:29:25 +0200 Subject: [PATCH 051/297] Merge commit 'af40101841c45aa75b56f4e9ca745369da8fb4ba' into sync-from-ra --- Cargo.lock | 1 + Cargo.toml | 4 +- crates/hir-def/src/body/lower.rs | 7 +- crates/hir-def/src/body/pretty.rs | 2 +- crates/hir-def/src/data/adt.rs | 2 +- crates/hir-def/src/hir.rs | 3 +- crates/hir-def/src/import_map.rs | 595 +++---- crates/hir-def/src/lib.rs | 9 + crates/hir-def/src/nameres/collector.rs | 2 +- crates/hir-expand/src/db.rs | 48 +- crates/hir-expand/src/lib.rs | 2 + crates/hir-ty/Cargo.toml | 3 +- crates/hir-ty/src/consteval.rs | 8 +- crates/hir-ty/src/display.rs | 4 +- crates/hir-ty/src/infer.rs | 28 +- crates/hir-ty/src/infer/closure.rs | 51 +- crates/hir-ty/src/infer/expr.rs | 61 +- crates/hir-ty/src/infer/mutability.rs | 2 +- crates/hir-ty/src/infer/pat.rs | 3 +- crates/hir-ty/src/interner.rs | 200 +-- crates/hir-ty/src/layout.rs | 16 +- crates/hir-ty/src/layout/tests.rs | 30 + crates/hir-ty/src/lib.rs | 91 +- crates/hir-ty/src/method_resolution.rs | 2 +- crates/hir-ty/src/mir.rs | 29 +- crates/hir-ty/src/mir/borrowck.rs | 2 +- crates/hir-ty/src/mir/eval.rs | 179 +- crates/hir-ty/src/mir/eval/shim.rs | 3 +- crates/hir-ty/src/mir/eval/tests.rs | 4 +- crates/hir-ty/src/mir/lower.rs | 123 +- crates/hir-ty/src/mir/lower/as_place.rs | 2 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 21 +- crates/hir-ty/src/mir/pretty.rs | 9 +- crates/hir-ty/src/tests/traits.rs | 47 + crates/hir/src/attrs.rs | 93 +- crates/hir/src/display.rs | 11 +- crates/hir/src/lib.rs | 40 +- crates/hir/src/semantics.rs | 8 +- crates/hir/src/source_analyzer.rs | 24 +- crates/hir/src/symbols.rs | 6 +- .../ide-assists/src/handlers/auto_import.rs | 15 +- .../ide-assists/src/handlers/bool_to_enum.rs | 4 +- .../src/handlers/convert_let_else_to_match.rs | 1 + .../convert_nested_function_to_closure.rs | 4 +- .../convert_tuple_return_type_to_struct.rs | 2 +- .../extract_struct_from_enum_variant.rs | 72 +- .../src/handlers/extract_variable.rs | 2 +- .../src/handlers/generate_delegate_methods.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 342 ++-- .../src/handlers/generate_function.rs | 2 +- .../src/handlers/generate_mut_trait_impl.rs | 4 +- .../src/handlers/generate_trait_from_impl.rs | 10 +- .../ide-assists/src/handlers/qualify_path.rs | 9 +- .../src/handlers/remove_parentheses.rs | 2 +- .../replace_derive_with_manual_impl.rs | 1 - .../src/completions/flyimport.rs | 36 +- crates/ide-completion/src/lib.rs | 1 - crates/ide-completion/src/tests/flyimport.rs | 1 + crates/ide-db/src/defs.rs | 180 +- crates/ide-db/src/imports/import_assets.rs | 90 +- crates/ide-db/src/items_locator.rs | 39 +- crates/ide-db/src/path_transform.rs | 2 +- crates/ide-db/src/rename.rs | 1 + crates/ide-db/src/search.rs | 2 +- crates/ide-db/src/source_change.rs | 4 +- crates/ide-db/src/symbol_index.rs | 121 +- .../trait_impl_redundant_assoc_item.rs | 213 ++- .../src/handlers/unresolved_method.rs | 2 +- .../src/handlers/unresolved_module.rs | 102 +- crates/ide-diagnostics/src/tests.rs | 17 +- crates/ide/src/doc_links.rs | 2 + crates/ide/src/doc_links/tests.rs | 16 +- crates/ide/src/goto_definition.rs | 2 +- crates/ide/src/hover/render.rs | 298 +--- crates/ide/src/inlay_hints.rs | 39 +- crates/ide/src/inlay_hints/chaining.rs | 268 ++- crates/ide/src/inlay_hints/range_exclusive.rs | 121 ++ crates/ide/src/lib.rs | 8 +- crates/ide/src/moniker.rs | 249 ++- crates/ide/src/navigation_target.rs | 32 +- crates/ide/src/rename.rs | 527 +++--- crates/ide/src/runnables.rs | 1516 ++--------------- crates/ide/src/static_index.rs | 13 +- .../ide/src/syntax_highlighting/highlight.rs | 12 +- crates/ide/src/syntax_highlighting/inject.rs | 2 +- .../test_data/highlight_macros.html | 2 +- crates/ide/src/syntax_highlighting/tests.rs | 2 +- crates/ide/src/view_memory_layout.rs | 4 +- .../proc-macro-srv/proc-macro-test/Cargo.toml | 2 +- crates/project-model/src/cargo_workspace.rs | 2 +- crates/project-model/src/sysroot.rs | 9 +- crates/project-model/src/workspace.rs | 2 +- .../rust-analyzer/src/cli/analysis_stats.rs | 1 + crates/rust-analyzer/src/cli/scip.rs | 104 +- crates/rust-analyzer/src/config.rs | 3 + crates/rust-analyzer/src/handlers/request.rs | 11 +- crates/span/Cargo.toml | 4 +- crates/stdx/src/lib.rs | 11 + crates/syntax/src/ast.rs | 10 + crates/syntax/src/ast/edit_in_place.rs | 3 +- crates/syntax/src/ast/expr_ext.rs | 24 +- crates/syntax/src/ast/make.rs | 3 - crates/syntax/src/ast/node_ext.rs | 34 +- crates/syntax/src/ast/prec.rs | 2 +- crates/syntax/src/validation.rs | 2 +- docs/dev/guide.md | 265 +-- docs/user/generated_config.adoc | 5 + docs/user/manual.adoc | 15 +- editors/code/package.json | 5 + editors/code/src/config.ts | 1 + editors/code/src/ctx.ts | 1 + editors/code/src/main.ts | 1 + editors/code/src/rust_project.ts | 6 +- editors/code/tsconfig.json | 2 +- lib/line-index/README.md | 30 + 115 files changed, 3106 insertions(+), 3623 deletions(-) create mode 100644 crates/ide/src/inlay_hints/range_exclusive.rs create mode 100644 lib/line-index/README.md diff --git a/Cargo.lock b/Cargo.lock index c7d110eafb66..6670e92f51bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,6 +569,7 @@ dependencies = [ "expect-test", "hir-def", "hir-expand", + "indexmap", "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 7054020086ea..4ee8064b5e34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = ["xtask/", "lib/*", "crates/*"] -exclude = ["crates/proc-macro-srv/proc-macro-test/"] +exclude = ["crates/proc-macro-srv/proc-macro-test/imp"] resolver = "2" [workspace.package] @@ -138,4 +138,4 @@ dashmap = { version = "=5.5.3", features = ["raw-api"] } collapsible_if = "allow" needless_pass_by_value = "allow" nonminimal_bool = "allow" -redundant_pattern_matching = "allow" \ No newline at end of file +redundant_pattern_matching = "allow" diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index a45ec844aba0..c728570d9866 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -17,7 +17,7 @@ use smallvec::SmallVec; use syntax::{ ast::{ self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasLoopBody, HasName, - SlicePatComponents, + RangeItem, SlicePatComponents, }, AstNode, AstPtr, SyntaxNodePtr, }; @@ -622,7 +622,8 @@ impl ExprCollector<'_> { ast::Expr::IndexExpr(e) => { let base = self.collect_expr_opt(e.base()); let index = self.collect_expr_opt(e.index()); - self.alloc_expr(Expr::Index { base, index }, syntax_ptr) + let is_assignee_expr = self.is_lowering_assignee_expr; + self.alloc_expr(Expr::Index { base, index, is_assignee_expr }, syntax_ptr) } ast::Expr::RangeExpr(e) => { let lhs = e.start().map(|lhs| self.collect_expr(lhs)); @@ -1609,7 +1610,7 @@ impl ExprCollector<'_> { |name| self.alloc_expr_desugared(Expr::Path(Path::from(name))), |name, span| { if let Some(span) = span { - mappings.push((span, name.clone())) + mappings.push((span, name)) } }, ), diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 6ecf1c20d6c1..02b19ade44ba 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -376,7 +376,7 @@ impl Printer<'_> { w!(self, ") "); } } - Expr::Index { base, index } => { + Expr::Index { base, index, is_assignee_expr: _ } => { self.print_expr(*base); w!(self, "["); self.print_expr(*index); diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index b163112db918..a95b78614e82 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -128,7 +128,7 @@ fn parse_repr_tt(tt: &Subtree) -> Option { } else { 0 }; - let pack = Align::from_bytes(pack).unwrap(); + let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); min_pack = Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); ReprFlags::empty() diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 591ee77c70a4..5890e818c46f 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -265,6 +265,7 @@ pub enum Expr { Index { base: ExprId, index: ExprId, + is_assignee_expr: bool, }, Closure { args: Box<[PatId]>, @@ -432,7 +433,7 @@ impl Expr { f(rhs); } } - Expr::Index { base, index } => { + Expr::Index { base, index, .. } => { f(*base); f(*index); } diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index aea7229bd648..989bbc7bfb2d 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -3,13 +3,13 @@ use std::{fmt, hash::BuildHasherDefault}; use base_db::CrateId; -use fst::{self, raw::IndexedValue, Streamer}; +use fst::{self, raw::IndexedValue, Automaton, Streamer}; use hir_expand::name::Name; use indexmap::IndexMap; use itertools::Itertools; use rustc_hash::{FxHashSet, FxHasher}; use smallvec::SmallVec; -use stdx::format_to; +use stdx::{format_to, TupleExt}; use triomphe::Arc; use crate::{ @@ -20,12 +20,10 @@ use crate::{ AssocItemId, ModuleDefId, ModuleId, TraitId, }; -type FxIndexMap = IndexMap>; - /// Item import details stored in the `ImportMap`. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct ImportInfo { - /// A name that can be used to import the item, relative to the crate's root. + /// A name that can be used to import the item, relative to the container. pub name: Name, /// The module containing this item. pub container: ModuleId, @@ -35,22 +33,22 @@ pub struct ImportInfo { pub is_unstable: bool, } -type ImportMapIndex = FxIndexMap, IsTraitAssocItem)>; - /// A map from publicly exported items to its name. /// -/// Reexports of items are taken into account, ie. if something is exported under multiple -/// names, the one with the shortest import path will be used. +/// Reexports of items are taken into account. #[derive(Default)] pub struct ImportMap { - map: ImportMapIndex, - /// List of keys stored in `map`, sorted lexicographically by their `ModPath`. Indexed by the - /// values returned by running `fst`. + /// Maps from `ItemInNs` to information of imports that bring the item into scope. + item_to_info_map: ImportMapIndex, + /// List of keys stored in [`Self::item_to_info_map`], sorted lexicographically by their + /// [`Name`]. Indexed by the values returned by running `fst`. /// - /// Since a name can refer to multiple items due to namespacing, we store all items with the - /// same name right after each other. This allows us to find all items after the FST gives us - /// the index of the first one. - importables: Vec, + /// Since a name can refer to multiple items due to namespacing and import aliases, we store all + /// items with the same name right after each other. This allows us to find all items after the + /// fst gives us the index of the first one. + /// + /// The [`u32`] is the index into the smallvec in the value of [`Self::item_to_info_map`]. + importables: Vec<(ItemInNs, u32)>, fst: fst::Map>, } @@ -60,10 +58,13 @@ enum IsTraitAssocItem { No, } +type FxIndexMap = IndexMap>; +type ImportMapIndex = FxIndexMap, IsTraitAssocItem)>; + impl ImportMap { pub fn dump(&self, db: &dyn DefDatabase) -> String { let mut out = String::new(); - for (k, v) in self.map.iter() { + for (k, v) in self.item_to_info_map.iter() { format_to!(out, "{:?} ({:?}) -> ", k, v.1); for v in &v.0 { format_to!(out, "{}:{:?}, ", v.name.display(db.upcast()), v.container); @@ -76,177 +77,191 @@ impl ImportMap { pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { let _p = profile::span("import_map_query"); - let map = collect_import_map(db, krate); + let map = Self::collect_import_map(db, krate); let mut importables: Vec<_> = map .iter() - // We've only collected items, whose name cannot be tuple field. - .flat_map(|(&item, (info, is_assoc))| { - info.iter().map(move |info| { - (item, *is_assoc, info.name.as_str().unwrap().to_ascii_lowercase()) - }) + // We've only collected items, whose name cannot be tuple field so unwrapping is fine. + .flat_map(|(&item, (info, _))| { + info.iter() + .enumerate() + .map(move |(idx, info)| (item, info.name.to_smol_str(), idx as u32)) }) .collect(); - importables.sort_by(|(_, l_is_assoc, lhs_name), (_, r_is_assoc, rhs_name)| { - lhs_name.cmp(rhs_name).then_with(|| l_is_assoc.cmp(r_is_assoc)) + importables.sort_by(|(_, l_info, _), (_, r_info, _)| { + let lhs_chars = l_info.chars().map(|c| c.to_ascii_lowercase()); + let rhs_chars = r_info.chars().map(|c| c.to_ascii_lowercase()); + lhs_chars.cmp(rhs_chars) }); importables.dedup(); // Build the FST, taking care not to insert duplicate values. let mut builder = fst::MapBuilder::memory(); - let iter = importables + let mut iter = importables .iter() .enumerate() - .dedup_by(|(_, (_, _, lhs)), (_, (_, _, rhs))| lhs == rhs); - for (start_idx, (_, _, name)) in iter { - let _ = builder.insert(name, start_idx as u64); + .dedup_by(|&(_, (_, lhs, _)), &(_, (_, rhs, _))| lhs.eq_ignore_ascii_case(rhs)); + + let mut insert = |name: &str, start, end| { + builder.insert(name.to_ascii_lowercase(), ((start as u64) << 32) | end as u64).unwrap() + }; + + if let Some((mut last, (_, name, _))) = iter.next() { + debug_assert_eq!(last, 0); + let mut last_name = name; + for (next, (_, next_name, _)) in iter { + insert(last_name, last, next); + last = next; + last_name = next_name; + } + insert(last_name, last, importables.len()); } - Arc::new(ImportMap { - map, - fst: builder.into_map(), - importables: importables.into_iter().map(|(item, _, _)| item).collect(), - }) + let importables = importables.into_iter().map(|(item, _, idx)| (item, idx)).collect(); + Arc::new(ImportMap { item_to_info_map: map, fst: builder.into_map(), importables }) } pub fn import_info_for(&self, item: ItemInNs) -> Option<&[ImportInfo]> { - self.map.get(&item).map(|(info, _)| &**info) + self.item_to_info_map.get(&item).map(|(info, _)| &**info) } -} -fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex { - let _p = profile::span("collect_import_map"); + fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex { + let _p = profile::span("collect_import_map"); - let def_map = db.crate_def_map(krate); - let mut map = FxIndexMap::default(); + let def_map = db.crate_def_map(krate); + let mut map = FxIndexMap::default(); - // We look only into modules that are public(ly reexported), starting with the crate root. - let root = def_map.module_id(DefMap::ROOT); - let mut worklist = vec![root]; - let mut visited = FxHashSet::default(); + // We look only into modules that are public(ly reexported), starting with the crate root. + let root = def_map.module_id(DefMap::ROOT); + let mut worklist = vec![root]; + let mut visited = FxHashSet::default(); - while let Some(module) = worklist.pop() { - if !visited.insert(module) { - continue; - } - let ext_def_map; - let mod_data = if module.krate == krate { - &def_map[module.local_id] - } else { - // The crate might reexport a module defined in another crate. - ext_def_map = module.def_map(db); - &ext_def_map[module.local_id] - }; - - let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { - let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); - if per_ns.is_none() { None } else { Some((name, per_ns)) } - }); - - for (name, per_ns) in visible_items { - for (item, import) in per_ns.iter_items() { - let attr_id = if let Some(import) = import { - match import { - ImportOrExternCrate::ExternCrate(id) => Some(id.into()), - ImportOrExternCrate::Import(id) => Some(id.import.into()), - } - } else { - match item { - ItemInNs::Types(id) | ItemInNs::Values(id) => id.try_into().ok(), - ItemInNs::Macros(id) => Some(id.into()), - } - }; - let (is_doc_hidden, is_unstable) = attr_id.map_or((false, false), |attr_id| { - let attrs = db.attrs(attr_id); - (attrs.has_doc_hidden(), attrs.is_unstable()) - }); - - let import_info = ImportInfo { - name: name.clone(), - container: module, - is_doc_hidden, - is_unstable, - }; - - if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { - collect_trait_assoc_items( - db, - &mut map, - tr, - matches!(item, ItemInNs::Types(_)), - &import_info, - ); - } - - let (infos, _) = - map.entry(item).or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::No)); - infos.reserve_exact(1); - infos.push(import_info); - - // If we've just added a module, descend into it. - if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { - worklist.push(mod_id); - } - } - } - } - map.shrink_to_fit(); - map -} - -fn collect_trait_assoc_items( - db: &dyn DefDatabase, - map: &mut ImportMapIndex, - tr: TraitId, - is_type_in_ns: bool, - trait_import_info: &ImportInfo, -) { - let _p = profile::span("collect_trait_assoc_items"); - for &(ref assoc_item_name, item) in &db.trait_data(tr).items { - let module_def_id = match item { - AssocItemId::FunctionId(f) => ModuleDefId::from(f), - AssocItemId::ConstId(c) => ModuleDefId::from(c), - // cannot use associated type aliases directly: need a `::TypeAlias` - // qualifier, ergo no need to store it for imports in import_map - AssocItemId::TypeAliasId(_) => { - cov_mark::hit!(type_aliases_ignored); + while let Some(module) = worklist.pop() { + if !visited.insert(module) { continue; } - }; - let assoc_item = if is_type_in_ns { - ItemInNs::Types(module_def_id) - } else { - ItemInNs::Values(module_def_id) - }; + let ext_def_map; + let mod_data = if module.krate == krate { + &def_map[module.local_id] + } else { + // The crate might reexport a module defined in another crate. + ext_def_map = module.def_map(db); + &ext_def_map[module.local_id] + }; - let attrs = &db.attrs(item.into()); - let assoc_item_info = ImportInfo { - container: trait_import_info.container, - name: assoc_item_name.clone(), - is_doc_hidden: attrs.has_doc_hidden(), - is_unstable: attrs.is_unstable(), - }; + let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { + let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); + if per_ns.is_none() { + None + } else { + Some((name, per_ns)) + } + }); - let (infos, _) = - map.entry(assoc_item).or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::Yes)); - infos.reserve_exact(1); - infos.push(assoc_item_info); + for (name, per_ns) in visible_items { + for (item, import) in per_ns.iter_items() { + let attr_id = if let Some(import) = import { + match import { + ImportOrExternCrate::ExternCrate(id) => Some(id.into()), + ImportOrExternCrate::Import(id) => Some(id.import.into()), + } + } else { + match item { + ItemInNs::Types(id) | ItemInNs::Values(id) => id.try_into().ok(), + ItemInNs::Macros(id) => Some(id.into()), + } + }; + let (is_doc_hidden, is_unstable) = attr_id.map_or((false, false), |attr_id| { + let attrs = db.attrs(attr_id); + (attrs.has_doc_hidden(), attrs.is_unstable()) + }); + + let import_info = ImportInfo { + name: name.clone(), + container: module, + is_doc_hidden, + is_unstable, + }; + + if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { + Self::collect_trait_assoc_items( + db, + &mut map, + tr, + matches!(item, ItemInNs::Types(_)), + &import_info, + ); + } + + let (infos, _) = + map.entry(item).or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::No)); + infos.reserve_exact(1); + infos.push(import_info); + + // If we've just added a module, descend into it. + if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { + worklist.push(mod_id); + } + } + } + } + map.shrink_to_fit(); + map } -} -impl PartialEq for ImportMap { - fn eq(&self, other: &Self) -> bool { - // `fst` and `importables` are built from `map`, so we don't need to compare them. - self.map == other.map + fn collect_trait_assoc_items( + db: &dyn DefDatabase, + map: &mut ImportMapIndex, + tr: TraitId, + is_type_in_ns: bool, + trait_import_info: &ImportInfo, + ) { + let _p = profile::span("collect_trait_assoc_items"); + for &(ref assoc_item_name, item) in &db.trait_data(tr).items { + let module_def_id = match item { + AssocItemId::FunctionId(f) => ModuleDefId::from(f), + AssocItemId::ConstId(c) => ModuleDefId::from(c), + // cannot use associated type aliases directly: need a `::TypeAlias` + // qualifier, ergo no need to store it for imports in import_map + AssocItemId::TypeAliasId(_) => { + cov_mark::hit!(type_aliases_ignored); + continue; + } + }; + let assoc_item = if is_type_in_ns { + ItemInNs::Types(module_def_id) + } else { + ItemInNs::Values(module_def_id) + }; + + let attrs = &db.attrs(item.into()); + let assoc_item_info = ImportInfo { + container: trait_import_info.container, + name: assoc_item_name.clone(), + is_doc_hidden: attrs.has_doc_hidden(), + is_unstable: attrs.is_unstable(), + }; + + let (infos, _) = + map.entry(assoc_item).or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::Yes)); + infos.reserve_exact(1); + infos.push(assoc_item_info); + } } } impl Eq for ImportMap {} +impl PartialEq for ImportMap { + fn eq(&self, other: &Self) -> bool { + // `fst` and `importables` are built from `map`, so we don't need to compare them. + self.item_to_info_map == other.item_to_info_map + } +} impl fmt::Debug for ImportMap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut importable_names: Vec<_> = self - .map + .item_to_info_map .iter() .map(|(item, (infos, _))| { let l = infos.len(); @@ -264,8 +279,8 @@ impl fmt::Debug for ImportMap { } /// A way to match import map contents against the search query. -#[derive(Copy, Clone, Debug)] -enum SearchMode { +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum SearchMode { /// Import map entry should strictly match the query string. Exact, /// Import map entry should contain all letters from the query string, @@ -275,6 +290,42 @@ enum SearchMode { Prefix, } +impl SearchMode { + pub fn check(self, query: &str, case_sensitive: bool, candidate: &str) -> bool { + match self { + SearchMode::Exact if case_sensitive => candidate == query, + SearchMode::Exact => candidate.eq_ignore_ascii_case(&query), + SearchMode::Prefix => { + query.len() <= candidate.len() && { + let prefix = &candidate[..query.len() as usize]; + if case_sensitive { + prefix == query + } else { + prefix.eq_ignore_ascii_case(&query) + } + } + } + SearchMode::Fuzzy => { + let mut name = candidate; + query.chars().all(|query_char| { + let m = if case_sensitive { + name.match_indices(query_char).next() + } else { + name.match_indices([query_char, query_char.to_ascii_uppercase()]).next() + }; + match m { + Some((index, _)) => { + name = &name[index + 1..]; + true + } + None => false, + } + }) + } + } + } +} + /// Three possible ways to search for the name in associated and/or other items. #[derive(Debug, Clone, Copy)] pub enum AssocSearchMode { @@ -293,7 +344,6 @@ pub struct Query { search_mode: SearchMode, assoc_mode: AssocSearchMode, case_sensitive: bool, - limit: usize, } impl Query { @@ -305,7 +355,6 @@ impl Query { search_mode: SearchMode::Exact, assoc_mode: AssocSearchMode::Include, case_sensitive: false, - limit: usize::MAX, } } @@ -327,11 +376,6 @@ impl Query { Self { assoc_mode, ..self } } - /// Limits the returned number of items to `limit`. - pub fn limit(self, limit: usize) -> Self { - Self { limit, ..self } - } - /// Respect casing of the query string when matching. pub fn case_sensitive(self) -> Self { Self { case_sensitive: true, ..self } @@ -344,39 +388,6 @@ impl Query { _ => true, } } - - /// Checks whether the import map entry matches the query. - fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { - let _p = profile::span("import_map::Query::import_matches"); - - // FIXME: Can we get rid of the alloc here? - let input = import.name.to_smol_str(); - let mut _s_slot; - let case_insensitive = enforce_lowercase || !self.case_sensitive; - let input = if case_insensitive { - _s_slot = String::from(input); - _s_slot.make_ascii_lowercase(); - &*_s_slot - } else { - &*input - }; - - let query_string = if case_insensitive { &self.lowercased } else { &self.query }; - - match self.search_mode { - SearchMode::Exact => input == *query_string, - SearchMode::Prefix => input.starts_with(query_string), - SearchMode::Fuzzy => { - let mut input_chars = input.chars(); - for query_char in query_string.chars() { - if !input_chars.any(|it| it == query_char) { - return false; - } - } - true - } - } - } } /// Searches dependencies of `krate` for an importable name matching `query`. @@ -394,73 +405,66 @@ pub fn search_dependencies( let import_maps: Vec<_> = graph[krate].dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect(); - let automaton = fst::automaton::Subsequence::new(&query.lowercased); - let mut op = fst::map::OpBuilder::new(); - for map in &import_maps { - op = op.add(map.fst.search(&automaton)); + + match query.search_mode { + SearchMode::Exact => { + let automaton = fst::automaton::Str::new(&query.lowercased); + + for map in &import_maps { + op = op.add(map.fst.search(&automaton)); + } + search_maps(&import_maps, op.union(), query) + } + SearchMode::Fuzzy => { + let automaton = fst::automaton::Subsequence::new(&query.lowercased); + + for map in &import_maps { + op = op.add(map.fst.search(&automaton)); + } + search_maps(&import_maps, op.union(), query) + } + SearchMode::Prefix => { + let automaton = fst::automaton::Str::new(&query.lowercased).starts_with(); + + for map in &import_maps { + op = op.add(map.fst.search(&automaton)); + } + search_maps(&import_maps, op.union(), query) + } } +} - let mut stream = op.union(); - +fn search_maps( + import_maps: &[Arc], + mut stream: fst::map::Union<'_>, + query: &Query, +) -> FxHashSet { let mut res = FxHashSet::default(); - let mut common_importable_data_scratch = vec![]; - // FIXME: Improve this, its rather unreadable and does duplicate amount of work while let Some((_, indexed_values)) = stream.next() { - for &IndexedValue { index, value } in indexed_values { - let import_map = &import_maps[index]; - let importables @ [importable, ..] = &import_map.importables[value as usize..] else { - continue; - }; - let &(ref importable_data, is_trait_assoc_item) = &import_map.map[importable]; - if !query.matches_assoc_mode(is_trait_assoc_item) { - continue; - } + for &IndexedValue { index: import_map_idx, value } in indexed_values { + let end = (value & 0xFFFF_FFFF) as usize; + let start = (value >> 32) as usize; + let ImportMap { item_to_info_map, importables, .. } = &*import_maps[import_map_idx]; + let importables = &importables[start as usize..end]; - // Fetch all the known names of this importable item (to handle import aliases/renames) - common_importable_data_scratch.extend( - importable_data - .iter() - .filter(|&info| query.import_matches(info, true)) - // Name shared by the importable items in this group. - .map(|info| info.name.to_smol_str()), - ); - if common_importable_data_scratch.is_empty() { - continue; - } - common_importable_data_scratch.sort(); - common_importable_data_scratch.dedup(); - - let iter = - common_importable_data_scratch.drain(..).flat_map(|common_importable_name| { - // Add the items from this name group. Those are all subsequent items in - // `importables` whose name match `common_importable_name`. - - importables - .iter() - .copied() - .take_while(move |item| { - let &(ref import_infos, assoc_mode) = &import_map.map[item]; - query.matches_assoc_mode(assoc_mode) - && import_infos.iter().any(|info| { - info.name - .to_smol_str() - .eq_ignore_ascii_case(&common_importable_name) - }) - }) - .filter(move |item| { - !query.case_sensitive || { - // we've already checked the common importables name case-insensitively - let &(ref import_infos, _) = &import_map.map[item]; - import_infos.iter().any(|info| query.import_matches(info, false)) - } - }) + let iter = importables + .iter() + .copied() + .filter_map(|(item, info_idx)| { + let (import_infos, assoc_mode) = &item_to_info_map[&item]; + query + .matches_assoc_mode(*assoc_mode) + .then(|| (item, &import_infos[info_idx as usize])) + }) + .filter(|&(_, info)| { + query.search_mode.check( + &query.query, + query.case_sensitive, + &info.name.to_smol_str(), + ) }); - res.extend(iter); - - if res.len() >= query.limit { - return res; - } + res.extend(iter.map(TupleExt::head)); } } @@ -480,7 +484,7 @@ mod tests { impl ImportMap { fn fmt_for_test(&self, db: &dyn DefDatabase) -> String { let mut importable_paths: Vec<_> = self - .map + .item_to_info_map .iter() .flat_map(|(item, (info, _))| info.iter().map(move |info| (item, info))) .map(|(item, info)| { @@ -907,28 +911,28 @@ mod tests { #[test] fn search_mode() { let ra_fixture = r#" - //- /main.rs crate:main deps:dep - //- /dep.rs crate:dep deps:tdep - use tdep::fmt as fmt_dep; - pub mod fmt { - pub trait Display { - fn fmt(); - } - } - #[macro_export] - macro_rules! Fmt { - () => {}; - } - pub struct Fmt; +//- /main.rs crate:main deps:dep +//- /dep.rs crate:dep deps:tdep +use tdep::fmt as fmt_dep; +pub mod fmt { + pub trait Display { + fn fmt(); + } +} +#[macro_export] +macro_rules! Fmt { + () => {}; +} +pub struct Fmt; - pub fn format() {} - pub fn no() {} +pub fn format() {} +pub fn no() {} - //- /tdep.rs crate:tdep - pub mod fmt { - pub struct NotImportableFromMain; - } - "#; +//- /tdep.rs crate:tdep +pub mod fmt { + pub struct NotImportableFromMain; +} +"#; check_search( ra_fixture, @@ -996,19 +1000,6 @@ mod tests { dep::fmt::Display::fmt (a) "#]], ); - - check_search( - ra_fixture, - "main", - Query::new("fmt".to_string()), - expect![[r#" - dep::Fmt (m) - dep::Fmt (t) - dep::Fmt (v) - dep::fmt (t) - dep::fmt::Display::fmt (a) - "#]], - ); } #[test] @@ -1043,32 +1034,4 @@ mod tests { "#]], ); } - - #[test] - fn search_limit() { - check_search( - r#" - //- /main.rs crate:main deps:dep - //- /dep.rs crate:dep - pub mod fmt { - pub trait Display { - fn fmt(); - } - } - #[macro_export] - macro_rules! Fmt { - () => {}; - } - pub struct Fmt; - - pub fn format() {} - pub fn no() {} - "#, - "main", - Query::new("".to_string()).fuzzy().limit(1), - expect![[r#" - dep::fmt::Display (t) - "#]], - ); - } } diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 22ba3aab4e9f..250d7b677b5d 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -307,6 +307,15 @@ pub struct FieldId { pub type LocalFieldId = Idx; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TupleId(pub u32); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TupleFieldId { + pub tuple: TupleId, + pub index: u32, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstId(salsa::InternId); type ConstLoc = AssocItemLoc; diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 3763bfcbcfaf..a18ac4b28c4e 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1397,7 +1397,7 @@ impl DefCollector<'_> { always!(krate == loc.def.krate); DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate) } - _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()), + _ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()), }; self.def_map.diagnostics.push(diag); diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index f7a26e436dee..ed04582cb0ab 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -390,7 +390,13 @@ fn parse_macro_expansion( let expand_to = loc.expand_to(); let mbe::ValueResult { value: tt, err } = macro_expand(db, macro_file.macro_call_id, loc); - let (parse, rev_token_map) = token_tree_to_syntax_node(&tt, expand_to); + let (parse, rev_token_map) = token_tree_to_syntax_node( + match &tt { + CowArc::Arc(it) => it, + CowArc::Owned(it) => it, + }, + expand_to, + ); ExpandResult { value: (parse, Arc::new(rev_token_map)), err } } @@ -669,15 +675,20 @@ fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { } } +enum CowArc { + Arc(Arc), + Owned(T), +} + fn macro_expand( db: &dyn ExpandDatabase, macro_call_id: MacroCallId, loc: MacroCallLoc, -) -> ExpandResult> { +) -> ExpandResult> { let _p = profile::span("macro_expand"); let ExpandResult { value: tt, mut err } = match loc.def.kind { - MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id), + MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc), MacroDefKind::BuiltInDerive(expander, ..) => { let (root, map) = parse_with_map(db, loc.kind.file_id()); let root = root.syntax_node(); @@ -692,7 +703,7 @@ fn macro_expand( let ValueResult { value, err } = db.macro_arg(macro_call_id); let Some((macro_arg, undo_info)) = value else { return ExpandResult { - value: Arc::new(tt::Subtree { + value: CowArc::Owned(tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(loc.call_site), token_trees: Vec::new(), }), @@ -718,7 +729,7 @@ fn macro_expand( // As such we just return the input subtree here. MacroDefKind::BuiltInEager(..) if loc.eager.is_none() => { return ExpandResult { - value: macro_arg.clone(), + value: CowArc::Arc(macro_arg.clone()), err: err.map(|err| { let mut buf = String::new(); for err in &**err { @@ -752,12 +763,17 @@ fn macro_expand( // Skip checking token tree limit for include! macro call if !loc.def.is_include() { // Set a hard limit for the expanded tt - if let Err(value) = check_tt_count(&tt, loc.call_site) { - return value; + if let Err(value) = check_tt_count(&tt) { + return value.map(|()| { + CowArc::Owned(tt::Subtree { + delimiter: tt::Delimiter::invisible_spanned(loc.call_site), + token_trees: vec![], + }) + }); } } - ExpandResult { value: Arc::new(tt), err } + ExpandResult { value: CowArc::Owned(tt), err } } fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult> { @@ -796,8 +812,13 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult Result<(), ExpandResult>> { +fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> { let count = tt.count(); if TOKEN_LIMIT.check(count).is_err() { Err(ExpandResult { - value: Arc::new(tt::Subtree { - delimiter: tt::Delimiter::invisible_spanned(call_site), - token_trees: vec![], - }), + value: (), err: Some(ExpandError::other(format!( "macro invocation exceeds token limit: produced {} tokens, limit is {}", count, diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index b5197d4c25d2..6a122e0859cc 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -220,6 +220,8 @@ pub enum MacroCallKind { }, Attr { ast_id: AstId, + // FIXME: This is being interned, subtrees can very quickly differ just slightly causing + // leakage problems here attr_args: Option>, /// Syntactical index of the invoking `#[attribute]`. /// diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index 1873e7bfe6a5..c7807bcf9aa1 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -32,6 +32,7 @@ once_cell = "1.17.0" triomphe.workspace = true nohash-hasher.workspace = true typed-arena = "2.0.1" +indexmap.workspace = true rustc-dependencies.workspace = true @@ -60,4 +61,4 @@ test-fixture.workspace = true in-rust-tree = ["rustc-dependencies/in-rust-tree"] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 9792d945eb8f..5528ad3ab4ab 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -142,15 +142,15 @@ pub fn intern_const_ref( LiteralConstRef::Int(i) => { // FIXME: We should handle failure of layout better. let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); - ConstScalar::Bytes(i.to_le_bytes()[0..size].to_vec(), MemoryMap::default()) + ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) } LiteralConstRef::UInt(i) => { let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); - ConstScalar::Bytes(i.to_le_bytes()[0..size].to_vec(), MemoryMap::default()) + ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) } - LiteralConstRef::Bool(b) => ConstScalar::Bytes(vec![*b as u8], MemoryMap::default()), + LiteralConstRef::Bool(b) => ConstScalar::Bytes(Box::new([*b as u8]), MemoryMap::default()), LiteralConstRef::Char(c) => { - ConstScalar::Bytes((*c as u32).to_le_bytes().to_vec(), MemoryMap::default()) + ConstScalar::Bytes((*c as u32).to_le_bytes().into(), MemoryMap::default()) } LiteralConstRef::Unknown => ConstScalar::Unknown, }; diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index d81926f7c976..23d951542214 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -515,7 +515,7 @@ fn render_const_scalar( TyKind::Dyn(_) => { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); - let Ok(t) = memory_map.vtable.ty(ty_id) else { + let Ok(t) = memory_map.vtable_ty(ty_id) else { return f.write_str(""); }; let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else { @@ -609,7 +609,7 @@ fn render_const_scalar( } hir_def::AdtId::EnumId(e) => { let Some((var_id, var_layout)) = - detect_variant_from_bytes(&layout, f.db, trait_env.clone(), b, e) + detect_variant_from_bytes(&layout, f.db, trait_env, b, e) else { return f.write_str(""); }; diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 8053300ad220..a78e3e7dc251 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -41,9 +41,10 @@ use hir_def::{ resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, type_ref::TypeRef, AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup, - TraitId, TypeAliasId, VariantId, + TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, }; use hir_expand::name::{name, Name}; +use indexmap::IndexSet; use la_arena::{ArenaMap, Entry}; use rustc_hash::{FxHashMap, FxHashSet}; use stdx::{always, never}; @@ -403,11 +404,15 @@ pub struct InferenceResult { /// For each method call expr, records the function it resolves to. method_resolutions: FxHashMap, /// For each field access expr, records the field it resolves to. - field_resolutions: FxHashMap, + field_resolutions: FxHashMap>, /// For each struct literal or pattern, records the variant it resolves to. variant_resolutions: FxHashMap, /// For each associated item record what it resolves to assoc_resolutions: FxHashMap, + /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in + /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of + /// that which allows us to resolve a [`TupleFieldId`]s type. + pub tuple_field_access_types: FxHashMap, pub diagnostics: Vec, pub type_of_expr: ArenaMap, /// For each pattern record the type it resolves to. @@ -447,7 +452,7 @@ impl InferenceResult { pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> { self.method_resolutions.get(&expr).cloned() } - pub fn field_resolution(&self, expr: ExprId) -> Option { + pub fn field_resolution(&self, expr: ExprId) -> Option> { self.field_resolutions.get(&expr).copied() } pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option { @@ -517,6 +522,8 @@ pub(crate) struct InferenceContext<'a> { /// The traits in scope, disregarding block modules. This is used for caching purposes. traits_in_scope: FxHashSet, pub(crate) result: InferenceResult, + tuple_field_accesses_rev: + IndexSet>, /// The return type of the function being inferred, the closure or async block if we're /// currently within one. /// @@ -598,6 +605,7 @@ impl<'a> InferenceContext<'a> { InferenceContext { result: InferenceResult::default(), table: unify::InferenceTable::new(db, trait_env), + tuple_field_accesses_rev: Default::default(), return_ty: TyKind::Error.intern(Interner), // set in collect_* calls resume_yield_tys: None, return_coercion: None, @@ -621,7 +629,13 @@ impl<'a> InferenceContext<'a> { // used this function for another workaround, mention it here. If you really need this function and believe that // there is no problem in it being `pub(crate)`, remove this comment. pub(crate) fn resolve_all(self) -> InferenceResult { - let InferenceContext { mut table, mut result, deferred_cast_checks, .. } = self; + let InferenceContext { + mut table, + mut result, + deferred_cast_checks, + tuple_field_accesses_rev, + .. + } = self; // Destructure every single field so whenever new fields are added to `InferenceResult` we // don't forget to handle them here. let InferenceResult { @@ -645,6 +659,7 @@ impl<'a> InferenceContext<'a> { // to resolve them here. closure_info: _, mutated_bindings_in_closure: _, + tuple_field_access_types: _, } = &mut result; table.fallback_if_possible(); @@ -720,6 +735,11 @@ impl<'a> InferenceContext<'a> { for adjustment in pat_adjustments.values_mut().flatten() { *adjustment = table.resolve_completely(adjustment.clone()); } + result.tuple_field_access_types = tuple_field_accesses_rev + .into_iter() + .enumerate() + .map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst))) + .collect(); result } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index af74df1032cb..118b9c0149f6 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -1,18 +1,19 @@ //! Inference of closure parameter types based on the closure's expected type. -use std::{cmp, collections::HashMap, convert::Infallible, mem}; +use std::{cmp, convert::Infallible, mem}; use chalk_ir::{ cast::Cast, fold::{FallibleTypeFolder, TypeFoldable}, AliasEq, AliasTy, BoundVar, DebruijnIndex, FnSubst, Mutability, TyKind, WhereClause, }; +use either::Either; use hir_def::{ data::adt::VariantData, hir::{Array, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat, PatId, Statement, UnaryOp}, lang_item::LangItem, resolver::{resolver_for_expr, ResolveValueResult, ValueNs}, - DefWithBodyId, FieldId, HasModule, VariantId, + DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, }; use hir_expand::name; use rustc_hash::FxHashMap; @@ -129,7 +130,7 @@ impl HirPlace { ctx.owner.module(ctx.db.upcast()).krate(), ); } - ty.clone() + ty } fn capture_kind_of_truncated_place( @@ -186,7 +187,7 @@ impl CapturedItem { result = format!("*{result}"); field_need_paren = true; } - ProjectionElem::Field(f) => { + ProjectionElem::Field(Either::Left(f)) => { if field_need_paren { result = format!("({result})"); } @@ -207,7 +208,15 @@ impl CapturedItem { result = format!("{result}.{field}"); field_need_paren = false; } - &ProjectionElem::TupleOrClosureField(field) => { + ProjectionElem::Field(Either::Right(f)) => { + let field = f.index; + if field_need_paren { + result = format!("({result})"); + } + result = format!("{result}.{field}"); + field_need_paren = false; + } + &ProjectionElem::ClosureField(field) => { if field_need_paren { result = format!("({result})"); } @@ -236,7 +245,7 @@ pub(crate) struct CapturedItemWithoutTy { impl CapturedItemWithoutTy { fn with_ty(self, ctx: &mut InferenceContext<'_>) -> CapturedItem { - let ty = self.place.ty(ctx).clone(); + let ty = self.place.ty(ctx); let ty = match &self.kind { CaptureKind::ByValue => ty, CaptureKind::ByRef(bk) => { @@ -329,15 +338,10 @@ impl InferenceContext<'_> { } } } - Expr::Field { expr, name } => { + Expr::Field { expr, name: _ } => { let mut place = self.place_of_expr(*expr)?; - if let TyKind::Tuple(..) = self.expr_ty(*expr).kind(Interner) { - let index = name.as_tuple_index()?; - place.projections.push(ProjectionElem::TupleOrClosureField(index)) - } else { - let field = self.result.field_resolution(tgt_expr)?; - place.projections.push(ProjectionElem::Field(field)); - } + let field = self.result.field_resolution(tgt_expr)?; + place.projections.push(ProjectionElem::Field(field)); return Some(place); } Expr::UnaryOp { expr, op: UnaryOp::Deref } => { @@ -392,7 +396,7 @@ impl InferenceContext<'_> { fn consume_place(&mut self, place: HirPlace, span: MirSpan) { if self.is_upvar(&place) { - let ty = place.ty(self).clone(); + let ty = place.ty(self); let kind = if self.is_ty_copy(ty) { CaptureKind::ByRef(BorrowKind::Shared) } else { @@ -598,7 +602,7 @@ impl InferenceContext<'_> { self.consume_expr(expr); } } - Expr::Index { base, index } => { + Expr::Index { base, index, is_assignee_expr: _ } => { self.select_from_expr(*base); self.consume_expr(*index); } @@ -774,7 +778,7 @@ impl InferenceContext<'_> { fn minimize_captures(&mut self) { self.current_captures.sort_by_key(|it| it.place.projections.len()); - let mut hash_map = HashMap::::new(); + let mut hash_map = FxHashMap::::default(); let result = mem::take(&mut self.current_captures); for item in result { let mut lookup_place = HirPlace { local: item.place.local, projections: vec![] }; @@ -825,7 +829,10 @@ impl InferenceContext<'_> { let it = al.iter().zip(fields.clone()).chain(ar.iter().rev().zip(fields.rev())); for (arg, i) in it { let mut p = place.clone(); - p.projections.push(ProjectionElem::TupleOrClosureField(i)); + p.projections.push(ProjectionElem::Field(Either::Right(TupleFieldId { + tuple: TupleId(!0), // dummy this, as its unused anyways + index: i as u32, + }))); self.consume_with_pat(p, *arg); } } @@ -850,10 +857,10 @@ impl InferenceContext<'_> { continue; }; let mut p = place.clone(); - p.projections.push(ProjectionElem::Field(FieldId { + p.projections.push(ProjectionElem::Field(Either::Left(FieldId { parent: variant.into(), local_id, - })); + }))); self.consume_with_pat(p, arg); } } @@ -894,10 +901,10 @@ impl InferenceContext<'_> { al.iter().zip(fields.clone()).chain(ar.iter().rev().zip(fields.rev())); for (arg, (i, _)) in it { let mut p = place.clone(); - p.projections.push(ProjectionElem::Field(FieldId { + p.projections.push(ProjectionElem::Field(Either::Left(FieldId { parent: variant.into(), local_id: i, - })); + }))); self.consume_with_pat(p, *arg); } } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 84954ca7e904..db631c8517c1 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -6,6 +6,7 @@ use std::{ }; use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind}; +use either::Either; use hir_def::{ generics::TypeOrConstParamData, hir::{ @@ -13,7 +14,7 @@ use hir_def::{ }, lang_item::{LangItem, LangItemTarget}, path::{GenericArg, GenericArgs}, - BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, + BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId, }; use hir_expand::name::{name, Name}; use stdx::always; @@ -744,7 +745,7 @@ impl InferenceContext<'_> { (RangeOp::Inclusive, _, None) => self.err_ty(), } } - Expr::Index { base, index } => { + Expr::Index { base, index, is_assignee_expr } => { let base_ty = self.infer_expr_inner(*base, &Expectation::none()); let index_ty = self.infer_expr(*index, &Expectation::none()); @@ -772,11 +773,24 @@ impl InferenceContext<'_> { .build(); self.write_method_resolution(tgt_expr, func, substs); } - self.resolve_associated_type_with_params( - self_ty, - self.resolve_ops_index_output(), - &[index_ty.cast(Interner)], - ) + let assoc = self.resolve_ops_index_output(); + let res = self.resolve_associated_type_with_params( + self_ty.clone(), + assoc, + &[index_ty.clone().cast(Interner)], + ); + + if *is_assignee_expr { + if let Some(index_trait) = self.resolve_lang_trait(LangItem::IndexMut) { + let trait_ref = TyBuilder::trait_ref(self.db, index_trait) + .push(self_ty) + .fill(|_| index_ty.clone().cast(Interner)) + .build(); + self.push_obligation(trait_ref.cast(Interner)); + } + } + + res } else { self.err_ty() } @@ -964,7 +978,7 @@ impl InferenceContext<'_> { .push(callee_ty.clone()) .push(TyBuilder::tuple_with(params.iter().cloned())) .build(); - self.write_method_resolution(tgt_expr, func, subst.clone()); + self.write_method_resolution(tgt_expr, func, subst); } } @@ -1393,7 +1407,7 @@ impl InferenceContext<'_> { &mut self, receiver_ty: &Ty, name: &Name, - ) -> Option<(Ty, Option, Vec, bool)> { + ) -> Option<(Ty, Either, Vec, bool)> { let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false); let mut private_field = None; let res = autoderef.by_ref().find_map(|(derefed_ty, _)| { @@ -1405,7 +1419,20 @@ impl InferenceContext<'_> { .get(idx) .map(|a| a.assert_ty_ref(Interner)) .cloned() - .map(|ty| (None, ty)) + .map(|ty| { + ( + Either::Right(TupleFieldId { + tuple: TupleId( + self.tuple_field_accesses_rev + .insert_full(substs.clone()) + .0 + as u32, + ), + index: idx as u32, + }), + ty, + ) + }) }); } TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { @@ -1431,7 +1458,7 @@ impl InferenceContext<'_> { let ty = self.db.field_types(field_id.parent)[field_id.local_id] .clone() .substitute(Interner, ¶meters); - Some((Some(field_id), ty)) + Some((Either::Left(field_id), ty)) }); Some(match res { @@ -1451,7 +1478,7 @@ impl InferenceContext<'_> { let ty = self.insert_type_vars(ty); let ty = self.normalize_associated_types_in(ty); - (ty, Some(field_id), adjustments, false) + (ty, Either::Left(field_id), adjustments, false) } }) } @@ -1474,11 +1501,9 @@ impl InferenceContext<'_> { match self.lookup_field(&receiver_ty, name) { Some((ty, field_id, adjustments, is_public)) => { self.write_expr_adj(receiver, adjustments); - if let Some(field_id) = field_id { - self.result.field_resolutions.insert(tgt_expr, field_id); - } + self.result.field_resolutions.insert(tgt_expr, field_id); if !is_public { - if let Some(field) = field_id { + if let Either::Left(field) = field_id { // FIXME: Merge this diagnostic into UnresolvedField? self.result .diagnostics @@ -1568,9 +1593,7 @@ impl InferenceContext<'_> { { Some((ty, field_id, adjustments, _public)) => { self.write_expr_adj(receiver, adjustments); - if let Some(field_id) = field_id { - self.result.field_resolutions.insert(tgt_expr, field_id); - } + self.result.field_resolutions.insert(tgt_expr, field_id); Some(ty) } None => None, diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs index b8a1af96fba6..663ea8532318 100644 --- a/crates/hir-ty/src/infer/mutability.rs +++ b/crates/hir-ty/src/infer/mutability.rs @@ -96,7 +96,7 @@ impl InferenceContext<'_> { Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => { self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread)) } - &Expr::Index { base, index } => { + &Expr::Index { base, index, is_assignee_expr: _ } => { if mutability == Mutability::Mut { if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) { if let Some(index_trait) = self diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index acdb540289d7..1bf8babe8365 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -233,7 +233,6 @@ impl InferenceContext<'_> { }; let mut expectations_iter = expectations .iter() - .cloned() .map(|a| a.assert_ty_ref(Interner).clone()) .chain(repeat_with(|| self.table.new_type_var())); @@ -336,7 +335,7 @@ impl InferenceContext<'_> { &Pat::Lit(expr) => { // Don't emit type mismatches again, the expression lowering already did that. let ty = self.infer_lit_pat(expr, &expected); - self.write_pat_ty(pat, ty.clone()); + self.write_pat_ty(pat, ty); return self.pat_ty_after_adjustment(pat); } Pat::Box { inner } => match self.resolve_boxed_box() { diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs index e4dd4b86cf99..eb6296f7a04a 100644 --- a/crates/hir-ty/src/interner.rs +++ b/crates/hir-ty/src/interner.rs @@ -1,9 +1,15 @@ //! Implementation of the Chalk `Interner` trait, which allows customizing the //! representation of the various objects Chalk deals with (types, goals etc.). -use crate::{chalk_db, tls, ConstScalar, GenericArg}; +use crate::{ + chalk_db, tls, AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, + ConstScalar, Constraint, Constraints, FnDefId, GenericArg, GenericArgData, Goal, GoalData, + Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause, + ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, + Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds, +}; use base_db::salsa::InternId; -use chalk_ir::{Goal, GoalData}; +use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance}; use hir_def::TypeAliasId; use intern::{impl_internable, Interned}; use smallvec::SmallVec; @@ -31,36 +37,37 @@ impl std::ops::Deref for InternedWrapper { } impl_internable!( - InternedWrapper>>, + InternedWrapper>, InternedWrapper>, - InternedWrapper>, - InternedWrapper>, - InternedWrapper>, + InternedWrapper, + InternedWrapper, + InternedWrapper, InternedWrapper, - InternedWrapper>>, - InternedWrapper>>, - InternedWrapper>>, - InternedWrapper>, + InternedWrapper>, + InternedWrapper>, + InternedWrapper>, + InternedWrapper>, ); impl chalk_ir::interner::Interner for Interner { - type InternedType = Interned>>; - type InternedLifetime = Interned>>; - type InternedConst = Interned>>; + type InternedType = Interned>; + type InternedLifetime = Interned>; + type InternedConst = Interned>; type InternedConcreteConst = ConstScalar; - type InternedGenericArg = chalk_ir::GenericArgData; - type InternedGoal = Arc>; - type InternedGoals = Vec>; + type InternedGenericArg = GenericArgData; + // We could do the following, but that saves "only" 20mb on self while increasing inferecene + // time by ~2.5% + // type InternedGoal = Interned>; + type InternedGoal = Arc; + type InternedGoals = Vec; type InternedSubstitution = Interned>>; - type InternedProgramClauses = Interned>>>; - type InternedProgramClause = chalk_ir::ProgramClauseData; - type InternedQuantifiedWhereClauses = - Interned>>>; - type InternedVariableKinds = Interned>>>; - type InternedCanonicalVarKinds = - Interned>>>; - type InternedConstraints = Vec>>; - type InternedVariances = Interned>>; + type InternedProgramClauses = Interned>>; + type InternedProgramClause = ProgramClauseData; + type InternedQuantifiedWhereClauses = Interned>>; + type InternedVariableKinds = Interned>>; + type InternedCanonicalVarKinds = Interned>>; + type InternedConstraints = Vec>; + type InternedVariances = SmallVec<[Variance; 16]>; type DefId = InternId; type InternedAdtId = hir_def::AdtId; type Identifier = TypeAliasId; @@ -88,68 +95,51 @@ impl chalk_ir::interner::Interner for Interner { } fn debug_opaque_ty_id( - opaque_ty_id: chalk_ir::OpaqueTyId, + opaque_ty_id: OpaqueTyId, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "OpaqueTy#{}", opaque_ty_id.0)) } - fn debug_fn_def_id( - fn_def_id: chalk_ir::FnDefId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { + fn debug_fn_def_id(fn_def_id: FnDefId, fmt: &mut fmt::Formatter<'_>) -> Option { tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) } fn debug_closure_id( - _fn_def_id: chalk_ir::ClosureId, + _fn_def_id: ClosureId, _fmt: &mut fmt::Formatter<'_>, ) -> Option { None } - fn debug_alias( - alias: &chalk_ir::AliasTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { + fn debug_alias(alias: &AliasTy, fmt: &mut fmt::Formatter<'_>) -> Option { use std::fmt::Debug; match alias { - chalk_ir::AliasTy::Projection(projection_ty) => { - Interner::debug_projection_ty(projection_ty, fmt) - } - chalk_ir::AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)), + AliasTy::Projection(projection_ty) => Interner::debug_projection_ty(projection_ty, fmt), + AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)), } } fn debug_projection_ty( - proj: &chalk_ir::ProjectionTy, + proj: &ProjectionTy, fmt: &mut fmt::Formatter<'_>, ) -> Option { tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) } - fn debug_opaque_ty( - opaque_ty: &chalk_ir::OpaqueTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { + fn debug_opaque_ty(opaque_ty: &OpaqueTy, fmt: &mut fmt::Formatter<'_>) -> Option { Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) } - fn debug_ty(ty: &chalk_ir::Ty, fmt: &mut fmt::Formatter<'_>) -> Option { + fn debug_ty(ty: &Ty, fmt: &mut fmt::Formatter<'_>) -> Option { Some(write!(fmt, "{:?}", ty.data(Interner))) } - fn debug_lifetime( - lifetime: &chalk_ir::Lifetime, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { + fn debug_lifetime(lifetime: &Lifetime, fmt: &mut fmt::Formatter<'_>) -> Option { Some(write!(fmt, "{:?}", lifetime.data(Interner))) } - fn debug_const( - constant: &chalk_ir::Const, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { + fn debug_const(constant: &Const, fmt: &mut fmt::Formatter<'_>) -> Option { Some(write!(fmt, "{:?}", constant.data(Interner))) } @@ -161,102 +151,99 @@ impl chalk_ir::interner::Interner for Interner { } fn debug_variable_kinds( - variable_kinds: &chalk_ir::VariableKinds, + variable_kinds: &VariableKinds, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", variable_kinds.as_slice(Interner))) } fn debug_variable_kinds_with_angles( - variable_kinds: &chalk_ir::VariableKinds, + variable_kinds: &VariableKinds, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", variable_kinds.inner_debug(Interner))) } fn debug_canonical_var_kinds( - canonical_var_kinds: &chalk_ir::CanonicalVarKinds, + canonical_var_kinds: &CanonicalVarKinds, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", canonical_var_kinds.as_slice(Interner))) } - fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { + fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { let goal_data = goal.data(Interner); Some(write!(fmt, "{goal_data:?}")) } - fn debug_goals( - goals: &chalk_ir::Goals, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { + fn debug_goals(goals: &Goals, fmt: &mut fmt::Formatter<'_>) -> Option { Some(write!(fmt, "{:?}", goals.debug(Interner))) } fn debug_program_clause_implication( - pci: &chalk_ir::ProgramClauseImplication, + pci: &ProgramClauseImplication, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", pci.debug(Interner))) } fn debug_program_clause( - clause: &chalk_ir::ProgramClause, + clause: &ProgramClause, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", clause.data(Interner))) } fn debug_program_clauses( - clauses: &chalk_ir::ProgramClauses, + clauses: &ProgramClauses, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", clauses.as_slice(Interner))) } fn debug_substitution( - substitution: &chalk_ir::Substitution, + substitution: &Substitution, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", substitution.debug(Interner))) } fn debug_separator_trait_ref( - separator_trait_ref: &chalk_ir::SeparatorTraitRef<'_, Interner>, + separator_trait_ref: &SeparatorTraitRef<'_, Interner>, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", separator_trait_ref.debug(Interner))) } fn debug_quantified_where_clauses( - clauses: &chalk_ir::QuantifiedWhereClauses, + clauses: &QuantifiedWhereClauses, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", clauses.as_slice(Interner))) } fn debug_constraints( - _clauses: &chalk_ir::Constraints, + _clauses: &Constraints, _fmt: &mut fmt::Formatter<'_>, ) -> Option { None } - fn intern_ty(self, kind: chalk_ir::TyKind) -> Self::InternedType { + fn intern_ty(self, kind: TyKind) -> Self::InternedType { let flags = kind.compute_flags(self); - Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags })) + Interned::new(InternedWrapper(TyData { kind, flags })) } - fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData { + fn ty_data(self, ty: &Self::InternedType) -> &TyData { &ty.0 } - fn intern_lifetime(self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { + fn intern_lifetime(self, lifetime: LifetimeData) -> Self::InternedLifetime { Interned::new(InternedWrapper(lifetime)) } - fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData { + fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &LifetimeData { &lifetime.0 } - fn intern_const(self, constant: chalk_ir::ConstData) -> Self::InternedConst { + fn intern_const(self, constant: ConstData) -> Self::InternedConst { Interned::new(InternedWrapper(constant)) } - fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData { + fn const_data(self, constant: &Self::InternedConst) -> &ConstData { &constant.0 } @@ -269,36 +256,33 @@ impl chalk_ir::interner::Interner for Interner { !matches!(c1, ConstScalar::Bytes(..)) || !matches!(c2, ConstScalar::Bytes(..)) || (c1 == c2) } - fn intern_generic_arg( - self, - parameter: chalk_ir::GenericArgData, - ) -> Self::InternedGenericArg { + fn intern_generic_arg(self, parameter: GenericArgData) -> Self::InternedGenericArg { parameter } - fn generic_arg_data( - self, - parameter: &Self::InternedGenericArg, - ) -> &chalk_ir::GenericArgData { + fn generic_arg_data(self, parameter: &Self::InternedGenericArg) -> &GenericArgData { parameter } - fn intern_goal(self, goal: GoalData) -> Self::InternedGoal { + fn intern_goal(self, goal: GoalData) -> Self::InternedGoal { Arc::new(goal) } - fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData { + fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData { goal } fn intern_goals( self, - data: impl IntoIterator, E>>, + data: impl IntoIterator>, ) -> Result { + // let hash = + // std::hash::BuildHasher::hash_one(&BuildHasherDefault::::default(), &goal); + // Interned::new(InternedWrapper(PreHashedWrapper(goal, hash))) data.into_iter().collect() } - fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal] { + fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal] { goals } @@ -313,37 +297,28 @@ impl chalk_ir::interner::Interner for Interner { &substitution.as_ref().0 } - fn intern_program_clause( - self, - data: chalk_ir::ProgramClauseData, - ) -> Self::InternedProgramClause { + fn intern_program_clause(self, data: ProgramClauseData) -> Self::InternedProgramClause { data } - fn program_clause_data( - self, - clause: &Self::InternedProgramClause, - ) -> &chalk_ir::ProgramClauseData { + fn program_clause_data(self, clause: &Self::InternedProgramClause) -> &ProgramClauseData { clause } fn intern_program_clauses( self, - data: impl IntoIterator, E>>, + data: impl IntoIterator>, ) -> Result { Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) } - fn program_clauses_data( - self, - clauses: &Self::InternedProgramClauses, - ) -> &[chalk_ir::ProgramClause] { + fn program_clauses_data(self, clauses: &Self::InternedProgramClauses) -> &[ProgramClause] { clauses } fn intern_quantified_where_clauses( self, - data: impl IntoIterator, E>>, + data: impl IntoIterator>, ) -> Result { Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) } @@ -351,27 +326,24 @@ impl chalk_ir::interner::Interner for Interner { fn quantified_where_clauses_data( self, clauses: &Self::InternedQuantifiedWhereClauses, - ) -> &[chalk_ir::QuantifiedWhereClause] { + ) -> &[QuantifiedWhereClause] { clauses } fn intern_generic_arg_kinds( self, - data: impl IntoIterator, E>>, + data: impl IntoIterator>, ) -> Result { Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) } - fn variable_kinds_data( - self, - parameter_kinds: &Self::InternedVariableKinds, - ) -> &[chalk_ir::VariableKind] { + fn variable_kinds_data(self, parameter_kinds: &Self::InternedVariableKinds) -> &[VariableKind] { ¶meter_kinds.as_ref().0 } fn intern_canonical_var_kinds( self, - data: impl IntoIterator, E>>, + data: impl IntoIterator>, ) -> Result { Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) } @@ -379,30 +351,30 @@ impl chalk_ir::interner::Interner for Interner { fn canonical_var_kinds_data( self, canonical_var_kinds: &Self::InternedCanonicalVarKinds, - ) -> &[chalk_ir::CanonicalVarKind] { + ) -> &[CanonicalVarKind] { canonical_var_kinds } fn intern_constraints( self, - data: impl IntoIterator>, E>>, + data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect() } fn constraints_data( self, constraints: &Self::InternedConstraints, - ) -> &[chalk_ir::InEnvironment>] { + ) -> &[InEnvironment] { constraints } fn intern_variances( self, - data: impl IntoIterator>, + data: impl IntoIterator>, ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) + data.into_iter().collect::>() } - fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] { + fn variances_data(self, variances: &Self::InternedVariances) -> &[Variance] { variances } } diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index bfc4f1383ec6..68619bb8b18c 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -164,7 +164,7 @@ fn layout_of_simd_ty( }; // Compute the ABI of the element type: - let e_ly = db.layout_of_ty(e_ty, env.clone())?; + let e_ly = db.layout_of_ty(e_ty, env)?; let Abi::Scalar(e_abi) = e_ly.abi else { return Err(LayoutError::Unknown); }; @@ -204,17 +204,17 @@ pub fn layout_of_ty_query( }; let cx = LayoutCx { target: &target }; let dl = &*cx.current_data_layout(); - let ty = normalize(db, trait_env.clone(), ty.clone()); + let ty = normalize(db, trait_env.clone(), ty); let result = match ty.kind(Interner) { TyKind::Adt(AdtId(def), subst) => { if let hir_def::AdtId::StructId(s) = def { let data = db.struct_data(*s); let repr = data.repr.unwrap_or_default(); if repr.simd() { - return layout_of_simd_ty(db, *s, subst, trait_env.clone(), &target); + return layout_of_simd_ty(db, *s, subst, trait_env, &target); } }; - return db.layout_of_adt(*def, subst.clone(), trait_env.clone()); + return db.layout_of_adt(*def, subst.clone(), trait_env); } TyKind::Scalar(s) => match s { chalk_ir::Scalar::Bool => Layout::scalar( @@ -280,7 +280,7 @@ pub fn layout_of_ty_query( } TyKind::Array(element, count) => { let count = try_const_usize(db, &count).ok_or(LayoutError::HasErrorConst)? as u64; - let element = db.layout_of_ty(element.clone(), trait_env.clone())?; + let element = db.layout_of_ty(element.clone(), trait_env)?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?; let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) { @@ -303,7 +303,7 @@ pub fn layout_of_ty_query( } } TyKind::Slice(element) => { - let element = db.layout_of_ty(element.clone(), trait_env.clone())?; + let element = db.layout_of_ty(element.clone(), trait_env)?; Layout { variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count: 0 }, @@ -345,7 +345,7 @@ pub fn layout_of_ty_query( })) .intern(Interner); } - unsized_part = normalize(db, trait_env.clone(), unsized_part); + unsized_part = normalize(db, trait_env, unsized_part); let metadata = match unsized_part.kind(Interner) { TyKind::Slice(_) | TyKind::Str => { scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) @@ -384,7 +384,7 @@ pub fn layout_of_ty_query( match impl_trait_id { crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { let infer = db.infer(func.into()); - return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env.clone()); + return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env); } crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => { return Err(LayoutError::NotImplemented) diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs index 9937113685ca..ef0be7ab2daf 100644 --- a/crates/hir-ty/src/layout/tests.rs +++ b/crates/hir-ty/src/layout/tests.rs @@ -220,6 +220,36 @@ fn recursive() { ); } +#[test] +fn repr_packed() { + size_and_align! { + #[repr(packed)] + struct Goal; + } + size_and_align! { + #[repr(packed(2))] + struct Goal; + } + size_and_align! { + #[repr(packed(4))] + struct Goal; + } + size_and_align! { + #[repr(packed)] + struct Goal(i32); + } + size_and_align! { + #[repr(packed(2))] + struct Goal(i32); + } + size_and_align! { + #[repr(packed(4))] + struct Goal(i32); + } + + check_size_and_align("#[repr(packed(5))] struct Goal(i32);", "", 4, 1); +} + #[test] fn generic() { size_and_align! { diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index cf174feed24b..793b52b49faa 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -37,22 +37,22 @@ mod tests; mod test_db; use std::{ - collections::{hash_map::Entry, HashMap}, - hash::Hash, + collections::hash_map::Entry, + hash::{BuildHasherDefault, Hash}, }; use chalk_ir::{ fold::{Shift, TypeFoldable}, interner::HasInterner, visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, - NoSolution, TyData, + NoSolution, }; use either::Either; use hir_def::{hir::ExprId, type_ref::Rawness, GeneralConstId, TypeOrConstParamId}; use hir_expand::name; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use syntax::ast::{make, ConstArg}; use traits::FnTrait; use triomphe::Arc; @@ -152,32 +152,64 @@ pub type DomainGoal = chalk_ir::DomainGoal; pub type Goal = chalk_ir::Goal; pub type AliasEq = chalk_ir::AliasEq; pub type Solution = chalk_solve::Solution; +pub type Constraint = chalk_ir::Constraint; +pub type Constraints = chalk_ir::Constraints; pub type ConstrainedSubst = chalk_ir::ConstrainedSubst; pub type Guidance = chalk_solve::Guidance; pub type WhereClause = chalk_ir::WhereClause; +pub type CanonicalVarKind = chalk_ir::CanonicalVarKind; +pub type GoalData = chalk_ir::GoalData; +pub type Goals = chalk_ir::Goals; +pub type ProgramClauseData = chalk_ir::ProgramClauseData; +pub type ProgramClause = chalk_ir::ProgramClause; +pub type ProgramClauses = chalk_ir::ProgramClauses; +pub type TyData = chalk_ir::TyData; +pub type Variances = chalk_ir::Variances; + /// A constant can have reference to other things. Memory map job is holding /// the necessary bits of memory of the const eval session to keep the constant /// meaningful. #[derive(Debug, Default, Clone, PartialEq, Eq)] -pub struct MemoryMap { - pub memory: HashMap>, - pub vtable: VTableMap, +pub enum MemoryMap { + #[default] + Empty, + Simple(Box<[u8]>), + Complex(Box), } -impl MemoryMap { - fn insert(&mut self, addr: usize, x: Vec) { +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct ComplexMemoryMap { + memory: FxHashMap>, + vtable: VTableMap, +} + +impl ComplexMemoryMap { + fn insert(&mut self, addr: usize, val: Box<[u8]>) { match self.memory.entry(addr) { Entry::Occupied(mut e) => { - if e.get().len() < x.len() { - e.insert(x); + if e.get().len() < val.len() { + e.insert(val); } } Entry::Vacant(e) => { - e.insert(x); + e.insert(val); } } } +} + +impl MemoryMap { + pub fn vtable_ty(&self, id: usize) -> Result<&Ty, MirEvalError> { + match self { + MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)), + MemoryMap::Complex(cm) => cm.vtable.ty(id), + } + } + + fn simple(v: Box<[u8]>) -> Self { + MemoryMap::Simple(v) + } /// This functions convert each address by a function `f` which gets the byte intervals and assign an address /// to them. It is useful when you want to load a constant with a memory map in a new memory. You can pass an @@ -185,22 +217,33 @@ impl MemoryMap { fn transform_addresses( &self, mut f: impl FnMut(&[u8], usize) -> Result, - ) -> Result, MirEvalError> { - self.memory - .iter() - .map(|x| { - let addr = *x.0; - let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) }; - Ok((addr, f(x.1, align)?)) - }) - .collect() + ) -> Result, MirEvalError> { + let mut transform = |(addr, val): (&usize, &Box<[u8]>)| { + let addr = *addr; + let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) }; + f(val, align).and_then(|it| Ok((addr, it))) + }; + match self { + MemoryMap::Empty => Ok(Default::default()), + MemoryMap::Simple(m) => transform((&0, m)).map(|(addr, val)| { + let mut map = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default()); + map.insert(addr, val); + map + }), + MemoryMap::Complex(cm) => cm.memory.iter().map(transform).collect(), + } } - fn get<'a>(&'a self, addr: usize, size: usize) -> Option<&'a [u8]> { + fn get(&self, addr: usize, size: usize) -> Option<&[u8]> { if size == 0 { Some(&[]) } else { - self.memory.get(&addr)?.get(0..size) + match self { + MemoryMap::Empty => Some(&[]), + MemoryMap::Simple(m) if addr == 0 => m.get(0..size), + MemoryMap::Simple(_) => None, + MemoryMap::Complex(cm) => cm.memory.get(&addr)?.get(0..size), + } } } } @@ -208,7 +251,7 @@ impl MemoryMap { /// A concrete constant value #[derive(Debug, Clone, PartialEq, Eq)] pub enum ConstScalar { - Bytes(Vec, MemoryMap), + Bytes(Box<[u8]>, MemoryMap), // FIXME: this is a hack to get around chalk not being able to represent unevaluatable // constants UnevaluatedConst(GeneralConstId, Substitution), diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 041d61c1b153..33619edfee93 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -1350,7 +1350,7 @@ pub(crate) fn resolve_indexing_op( ty: Canonical, index_trait: TraitId, ) -> Option { - let mut table = InferenceTable::new(db, env.clone()); + let mut table = InferenceTable::new(db, env); let ty = table.instantiate_canonical(ty); let deref_chain = autoderef_method_receiver(&mut table, ty); for (ty, adj) in deref_chain { diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index f1795e71d945..7bef6f0d0f71 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -14,9 +14,10 @@ use crate::{ }; use base_db::CrateId; use chalk_ir::Mutability; +use either::Either; use hir_def::{ hir::{BindingId, Expr, ExprId, Ordering, PatId}, - DefWithBodyId, FieldId, StaticId, UnionId, VariantId, + DefWithBodyId, FieldId, StaticId, TupleFieldId, UnionId, VariantId, }; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; @@ -97,16 +98,16 @@ pub enum Operand { } impl Operand { - fn from_concrete_const(data: Vec, memory_map: MemoryMap, ty: Ty) -> Self { + fn from_concrete_const(data: Box<[u8]>, memory_map: MemoryMap, ty: Ty) -> Self { Operand::Constant(intern_const_scalar(ConstScalar::Bytes(data, memory_map), ty)) } - fn from_bytes(data: Vec, ty: Ty) -> Self { + fn from_bytes(data: Box<[u8]>, ty: Ty) -> Self { Operand::from_concrete_const(data, MemoryMap::default(), ty) } fn const_zst(ty: Ty) -> Operand { - Self::from_bytes(vec![], ty) + Self::from_bytes(Box::default(), ty) } fn from_fn( @@ -117,16 +118,16 @@ impl Operand { let ty = chalk_ir::TyKind::FnDef(CallableDefId::FunctionId(func_id).to_chalk(db), generic_args) .intern(Interner); - Operand::from_bytes(vec![], ty) + Operand::from_bytes(Box::default(), ty) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ProjectionElem { Deref, - Field(FieldId), + Field(Either), // FIXME: get rid of this, and use FieldId for tuples and closures - TupleOrClosureField(usize), + ClosureField(usize), Index(V), ConstantIndex { offset: u64, from_end: bool }, Subslice { from: u64, to: u64 }, @@ -161,7 +162,7 @@ impl ProjectionElem { return TyKind::Error.intern(Interner); } }, - ProjectionElem::Field(f) => match &base.kind(Interner) { + ProjectionElem::Field(Either::Left(f)) => match &base.kind(Interner) { TyKind::Adt(_, subst) => { db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst) } @@ -170,19 +171,25 @@ impl ProjectionElem { return TyKind::Error.intern(Interner); } }, - ProjectionElem::TupleOrClosureField(f) => match &base.kind(Interner) { + ProjectionElem::Field(Either::Right(f)) => match &base.kind(Interner) { TyKind::Tuple(_, subst) => subst .as_slice(Interner) - .get(*f) + .get(f.index as usize) .map(|x| x.assert_ty_ref(Interner)) .cloned() .unwrap_or_else(|| { never!("Out of bound tuple field"); TyKind::Error.intern(Interner) }), + _ => { + never!("Only tuple has tuple field"); + return TyKind::Error.intern(Interner); + } + }, + ProjectionElem::ClosureField(f) => match &base.kind(Interner) { TyKind::Closure(id, subst) => closure_field(*id, subst, *f), _ => { - never!("Only tuple or closure has tuple or closure field"); + never!("Only closure has closure field"); return TyKind::Error.intern(Interner); } }, diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index 74c5efd6c3f4..e79c87a02f40 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -205,7 +205,7 @@ fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> Projectio | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Field(_) - | ProjectionElem::TupleOrClosureField(_) + | ProjectionElem::ClosureField(_) | ProjectionElem::Index(_) => { is_part_of = true; } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index fbfb6ff8cddd..16075d907343 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1,13 +1,6 @@ //! This module provides a MIR interpreter, which is used in const eval. -use std::{ - borrow::Cow, - cell::RefCell, - collections::{HashMap, HashSet}, - fmt::Write, - iter, mem, - ops::Range, -}; +use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range}; use base_db::{CrateId, FileId}; use chalk_ir::{cast::Cast, Mutability}; @@ -40,8 +33,8 @@ use crate::{ name, static_lifetime, traits::FnTrait, utils::{detect_variant_from_bytes, ClosureSubst}, - CallableDefId, ClosureId, Const, ConstScalar, FnDefId, Interner, MemoryMap, Substitution, - TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstScalar, FnDefId, Interner, MemoryMap, + Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, }; use super::{ @@ -98,6 +91,15 @@ impl VTableMap { let id = from_bytes!(usize, bytes); self.ty(id) } + + pub fn shrink_to_fit(&mut self) { + self.id_to_ty.shrink_to_fit(); + self.ty_to_id.shrink_to_fit(); + } + + fn is_empty(&self) -> bool { + self.id_to_ty.is_empty() && self.ty_to_id.is_empty() + } } #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -251,13 +253,6 @@ impl From for IntervalOrOwned { } impl IntervalOrOwned { - pub(crate) fn to_vec(self, memory: &Evaluator<'_>) -> Result> { - Ok(match self { - IntervalOrOwned::Owned(o) => o, - IntervalOrOwned::Borrowed(b) => b.get(memory)?.to_vec(), - }) - } - fn get<'a>(&'a self, memory: &'a Evaluator<'a>) -> Result<&'a [u8]> { Ok(match self { IntervalOrOwned::Owned(o) => o, @@ -291,8 +286,8 @@ impl Address { } } - fn to_bytes(&self) -> Vec { - usize::to_le_bytes(self.to_usize()).to_vec() + fn to_bytes(&self) -> [u8; mem::size_of::()] { + usize::to_le_bytes(self.to_usize()) } fn to_usize(&self) -> usize { @@ -391,7 +386,7 @@ impl MirEvalError { write!( f, "Layout for type `{}` is not available due {err:?}", - ty.display(db).with_closure_style(ClosureStyle::ClosureWithId).to_string() + ty.display(db).with_closure_style(ClosureStyle::ClosureWithId) )?; } MirEvalError::MirLowerError(func, err) => { @@ -510,6 +505,20 @@ struct Locals { drop_flags: DropFlags, } +pub struct MirOutput { + stdout: Vec, + stderr: Vec, +} + +impl MirOutput { + pub fn stdout(&self) -> Cow<'_, str> { + String::from_utf8_lossy(&self.stdout) + } + pub fn stderr(&self) -> Cow<'_, str> { + String::from_utf8_lossy(&self.stderr) + } +} + pub fn interpret_mir( db: &dyn HirDatabase, body: Arc, @@ -520,27 +529,31 @@ pub fn interpret_mir( // (and probably should) do better here, for example by excluding bindings outside of the target expression. assert_placeholder_ty_is_unused: bool, trait_env: Option>, -) -> (Result, String, String) { +) -> (Result, MirOutput) { let ty = body.locals[return_slot()].ty.clone(); let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env); let it: Result = (|| { if evaluator.ptr_size() != std::mem::size_of::() { not_supported!("targets with different pointer size from host"); } - let bytes = evaluator.interpret_mir(body.clone(), None.into_iter())?; + let interval = evaluator.interpret_mir(body.clone(), None.into_iter())?; + let bytes = interval.get(&evaluator)?; let mut memory_map = evaluator.create_memory_map( - &bytes, + bytes, &ty, &Locals { ptr: ArenaMap::new(), body, drop_flags: DropFlags::default() }, )?; - memory_map.vtable = evaluator.vtable_map.clone(); + let bytes = bytes.into(); + let memory_map = if memory_map.memory.is_empty() && evaluator.vtable_map.is_empty() { + MemoryMap::Empty + } else { + memory_map.vtable = mem::take(&mut evaluator.vtable_map); + memory_map.vtable.shrink_to_fit(); + MemoryMap::Complex(Box::new(memory_map)) + }; return Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty)); })(); - ( - it, - String::from_utf8_lossy(&evaluator.stdout).into_owned(), - String::from_utf8_lossy(&evaluator.stderr).into_owned(), - ) + (it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr }) } #[cfg(test)] @@ -562,7 +575,7 @@ impl Evaluator<'_> { code_stack: vec![], vtable_map: VTableMap::default(), thread_local_storage: TlsData::default(), - static_locations: HashMap::default(), + static_locations: Default::default(), db, random_state: oorandom::Rand64::new(0), trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)), @@ -573,11 +586,11 @@ impl Evaluator<'_> { stack_depth_limit: 100, execution_limit: EXECUTION_LIMIT, memory_limit: 1000_000_000, // 2GB, 1GB for stack and 1GB for heap - layout_cache: RefCell::new(HashMap::default()), - projected_ty_cache: RefCell::new(HashMap::default()), - not_special_fn_cache: RefCell::new(HashSet::default()), - mir_or_dyn_index_cache: RefCell::new(HashMap::default()), - unused_locals_store: RefCell::new(HashMap::default()), + layout_cache: RefCell::new(Default::default()), + projected_ty_cache: RefCell::new(Default::default()), + not_special_fn_cache: RefCell::new(Default::default()), + mir_or_dyn_index_cache: RefCell::new(Default::default()), + unused_locals_store: RefCell::new(Default::default()), cached_ptr_size: match db.target_data_layout(crate_id) { Some(it) => it.pointer_size.bytes_usize(), None => 8, @@ -720,13 +733,19 @@ impl Evaluator<'_> { self.size_of_sized(&inner_ty, locals, "array inner type should be sized")?; addr = addr.offset(ty_size * (from as usize)); } - &ProjectionElem::TupleOrClosureField(f) => { + &ProjectionElem::ClosureField(f) => { let layout = self.layout(&prev_ty)?; let offset = layout.fields.offset(f).bytes_usize(); addr = addr.offset(offset); - metadata = None; // tuple field is always sized + metadata = None; } - ProjectionElem::Field(f) => { + ProjectionElem::Field(Either::Right(f)) => { + let layout = self.layout(&prev_ty)?; + let offset = layout.fields.offset(f.index as usize).bytes_usize(); + addr = addr.offset(offset); + metadata = None; // tuple field is always sized FIXME: This is wrong, the tail can be unsized + } + ProjectionElem::Field(Either::Left(f)) => { let layout = self.layout(&prev_ty)?; let variant_layout = match &layout.variants { Variants::Single { .. } => &layout, @@ -797,11 +816,11 @@ impl Evaluator<'_> { }) } - fn interpret_mir( - &mut self, + fn interpret_mir<'slf>( + &'slf mut self, body: Arc, args: impl Iterator, - ) -> Result> { + ) -> Result { if let Some(it) = self.stack_depth_limit.checked_sub(1) { self.stack_depth_limit = it; } else { @@ -831,8 +850,8 @@ impl Evaluator<'_> { match &statement.kind { StatementKind::Assign(l, r) => { let addr = self.place_addr(l, &locals)?; - let result = self.eval_rvalue(r, &mut locals)?.to_vec(&self)?; - self.write_memory(addr, &result)?; + let result = self.eval_rvalue(r, &mut locals)?; + self.copy_from_interval_or_owned(addr, result)?; locals .drop_flags .add_place(l.clone(), &locals.body.projection_store); @@ -951,7 +970,7 @@ impl Evaluator<'_> { None => { self.code_stack = prev_code_stack; self.stack_depth_limit += 1; - return Ok(return_interval.get(self)?.to_vec()); + return Ok(return_interval); } Some(bb) => { // We don't support const promotion, so we can't truncate the stack yet. @@ -1044,7 +1063,7 @@ impl Evaluator<'_> { Rvalue::Use(it) => Borrowed(self.eval_operand(it, locals)?), Rvalue::Ref(_, p) => { let (addr, _, metadata) = self.place_addr_and_ty_and_metadata(p, locals)?; - let mut r = addr.to_bytes(); + let mut r = addr.to_bytes().to_vec(); if let Some(metadata) = metadata { r.extend(metadata.get(self)?); } @@ -1277,7 +1296,7 @@ impl Evaluator<'_> { not_supported!("unsized box initialization"); }; let addr = self.heap_allocate(size, align)?; - Owned(addr.to_bytes()) + Owned(addr.to_bytes().to_vec()) } Rvalue::CopyForDeref(_) => not_supported!("copy for deref"), Rvalue::Aggregate(kind, values) => { @@ -1514,7 +1533,7 @@ impl Evaluator<'_> { } }, TyKind::Dyn(_) => { - let vtable = self.vtable_map.id(current_ty.clone()); + let vtable = self.vtable_map.id(current_ty); let mut r = Vec::with_capacity(16); let addr = addr.get(self)?; r.extend(addr.iter().copied()); @@ -1709,7 +1728,18 @@ impl Evaluator<'_> { } let addr = self.heap_allocate(size, align)?; self.write_memory(addr, &v)?; - self.patch_addresses(&patch_map, &memory_map.vtable, addr, ty, locals)?; + self.patch_addresses( + &patch_map, + |bytes| match &memory_map { + MemoryMap::Empty | MemoryMap::Simple(_) => { + Err(MirEvalError::InvalidVTableId(from_bytes!(usize, bytes))) + } + MemoryMap::Complex(cm) => cm.vtable.ty_of_bytes(bytes), + }, + addr, + ty, + locals, + )?; Ok(Interval::new(addr, size)) } @@ -1761,6 +1791,13 @@ impl Evaluator<'_> { Ok(()) } + fn copy_from_interval_or_owned(&mut self, addr: Address, r: IntervalOrOwned) -> Result<()> { + match r { + IntervalOrOwned::Borrowed(r) => self.copy_from_interval(addr, r), + IntervalOrOwned::Owned(r) => self.write_memory(addr, &r), + } + } + fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<()> { if r.size == 0 { return Ok(()); @@ -1881,13 +1918,18 @@ impl Evaluator<'_> { } } - fn create_memory_map(&self, bytes: &[u8], ty: &Ty, locals: &Locals) -> Result { + fn create_memory_map( + &self, + bytes: &[u8], + ty: &Ty, + locals: &Locals, + ) -> Result { fn rec( this: &Evaluator<'_>, bytes: &[u8], ty: &Ty, locals: &Locals, - mm: &mut MemoryMap, + mm: &mut ComplexMemoryMap, ) -> Result<()> { match ty.kind(Interner) { TyKind::Ref(_, _, t) => { @@ -1897,7 +1939,7 @@ impl Evaluator<'_> { let addr_usize = from_bytes!(usize, bytes); mm.insert( addr_usize, - this.read_memory(Address::from_usize(addr_usize), size)?.to_vec(), + this.read_memory(Address::from_usize(addr_usize), size)?.into(), ) } None => { @@ -1923,7 +1965,7 @@ impl Evaluator<'_> { let size = element_size * count; let addr = Address::from_bytes(addr)?; let b = this.read_memory(addr, size)?; - mm.insert(addr.to_usize(), b.to_vec()); + mm.insert(addr.to_usize(), b.into()); if let Some(ty) = check_inner { for i in 0..count { let offset = element_size * i; @@ -1996,15 +2038,15 @@ impl Evaluator<'_> { } Ok(()) } - let mut mm = MemoryMap::default(); - rec(self, bytes, ty, locals, &mut mm)?; + let mut mm = ComplexMemoryMap::default(); + rec(&self, bytes, ty, locals, &mut mm)?; Ok(mm) } - fn patch_addresses( + fn patch_addresses<'vtable>( &mut self, - patch_map: &HashMap, - old_vtable: &VTableMap, + patch_map: &FxHashMap, + ty_of_bytes: impl Fn(&[u8]) -> Result<&'vtable Ty> + Copy, addr: Address, ty: &Ty, locals: &Locals, @@ -2031,7 +2073,7 @@ impl Evaluator<'_> { } } TyKind::Function(_) => { - let ty = old_vtable.ty_of_bytes(self.read_memory(addr, my_size)?)?.clone(); + let ty = ty_of_bytes(self.read_memory(addr, my_size)?)?.clone(); let new_id = self.vtable_map.id(ty); self.write_memory(addr, &new_id.to_le_bytes())?; } @@ -2042,7 +2084,7 @@ impl Evaluator<'_> { let ty = ty.clone().substitute(Interner, subst); self.patch_addresses( patch_map, - old_vtable, + ty_of_bytes, addr.offset(offset), &ty, locals, @@ -2064,7 +2106,7 @@ impl Evaluator<'_> { let ty = ty.clone().substitute(Interner, subst); self.patch_addresses( patch_map, - old_vtable, + ty_of_bytes, addr.offset(offset), &ty, locals, @@ -2077,7 +2119,7 @@ impl Evaluator<'_> { for (id, ty) in subst.iter(Interner).enumerate() { let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument let offset = layout.fields.offset(id).bytes_usize(); - self.patch_addresses(patch_map, old_vtable, addr.offset(offset), ty, locals)?; + self.patch_addresses(patch_map, ty_of_bytes, addr.offset(offset), ty, locals)?; } } TyKind::Array(inner, len) => { @@ -2089,7 +2131,7 @@ impl Evaluator<'_> { for i in 0..len { self.patch_addresses( patch_map, - old_vtable, + ty_of_bytes, addr.offset(i * size), inner, locals, @@ -2160,14 +2202,14 @@ impl Evaluator<'_> { .map_err(|it| MirEvalError::MirLowerErrorForClosure(closure, it))?; let closure_data = if mir_body.locals[mir_body.param_locals[0]].ty.as_reference().is_some() { - closure_data.addr.to_bytes() + closure_data.addr.to_bytes().to_vec() } else { closure_data.get(self)?.to_owned() }; let arg_bytes = iter::once(Ok(closure_data)) .chain(args.iter().map(|it| Ok(it.get(&self)?.to_owned()))) .collect::>>()?; - let bytes = self + let interval = self .interpret_mir(mir_body, arg_bytes.into_iter().map(IntervalOrOwned::Owned)) .map_err(|e| { MirEvalError::InFunction( @@ -2175,7 +2217,7 @@ impl Evaluator<'_> { vec![(Either::Right(closure), span, locals.body.owner)], ) })?; - destination.write_from_bytes(self, &bytes)?; + destination.write_from_interval(self, interval)?; Ok(None) } @@ -2368,7 +2410,7 @@ impl Evaluator<'_> { vec![(Either::Left(def), span, locals.body.owner)], ) })?; - destination.write_from_bytes(self, &result)?; + destination.write_from_interval(self, result)?; None }) } @@ -2546,7 +2588,7 @@ impl Evaluator<'_> { body, locals, drop_fn, - [IntervalOrOwned::Owned(addr.to_bytes())].into_iter(), + iter::once(IntervalOrOwned::Owned(addr.to_bytes().to_vec())), span, Interval { addr: Address::Invalid(0), size: 0 }, None, @@ -2674,11 +2716,12 @@ pub fn render_const_using_debug_impl( ) else { not_supported!("std::fmt::format not found"); }; - let message_string = evaluator.interpret_mir( + let interval = evaluator.interpret_mir( db.mir_body(format_fn.into()).map_err(|e| MirEvalError::MirLowerError(format_fn, e))?, [IntervalOrOwned::Borrowed(Interval { addr: a3, size: evaluator.ptr_size() * 6 })] .into_iter(), )?; + let message_string = interval.get(&evaluator)?; let addr = Address::from_bytes(&message_string[evaluator.ptr_size()..2 * evaluator.ptr_size()])?; let size = from_bytes!(usize, message_string[2 * evaluator.ptr_size()..]); diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 2de99e41659c..ff26a3d0be17 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -322,12 +322,13 @@ impl Evaluator<'_> { let hir_def::resolver::ValueNs::FunctionId(format_fn) = format_fn else { not_supported!("std::fmt::format is not a function") }; - let message_string = self.interpret_mir( + let interval = self.interpret_mir( self.db .mir_body(format_fn.into()) .map_err(|e| MirEvalError::MirLowerError(format_fn, e))?, args.map(|x| IntervalOrOwned::Owned(x.clone())), )?; + let message_string = interval.get(self)?; let addr = Address::from_bytes(&message_string[self.ptr_size()..2 * self.ptr_size()])?; let size = from_bytes!(usize, message_string[2 * self.ptr_size()..]); diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs index b0f929279a5c..6552bf493377 100644 --- a/crates/hir-ty/src/mir/eval/tests.rs +++ b/crates/hir-ty/src/mir/eval/tests.rs @@ -31,9 +31,9 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr db.trait_environment(func_id.into()), ) .map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?; - let (result, stdout, stderr) = interpret_mir(db, body, false, None); + let (result, output) = interpret_mir(db, body, false, None); result?; - Ok((stdout, stderr)) + Ok((output.stdout().into_owned(), output.stderr().into_owned())) } fn check_pass(ra_fixture: &str) { diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 639fabc198c1..c02c5ef8767f 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -15,7 +15,7 @@ use hir_def::{ path::Path, resolver::{resolver_for_expr, HasResolver, ResolveValueResult, ValueNs}, AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId, - Lookup, TraitId, TypeOrConstParamId, + Lookup, TraitId, TupleId, TypeOrConstParamId, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -177,7 +177,7 @@ impl MirLowerError { )?; writeln!(f, "Provided args: [")?; for g in subst.iter(Interner) { - write!(f, " {},", g.display(db).to_string())?; + write!(f, " {},", g.display(db))?; } writeln!(f, "]")?; } @@ -540,7 +540,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.write_bytes_to_place( then_target, place.clone(), - vec![1], + Box::new([1]), TyBuilder::bool(), MirSpan::Unknown, )?; @@ -548,7 +548,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.write_bytes_to_place( else_target, place, - vec![0], + Box::new([0]), TyBuilder::bool(), MirSpan::Unknown, )?; @@ -602,7 +602,7 @@ impl<'ctx> MirLowerCtx<'ctx> { generic_args, ) .intern(Interner); - let func = Operand::from_bytes(vec![], ty); + let func = Operand::from_bytes(Box::default(), ty); return self.lower_call_and_args( func, iter::once(*callee).chain(args.iter().copied()), @@ -615,7 +615,7 @@ impl<'ctx> MirLowerCtx<'ctx> { let callee_ty = self.expr_ty_after_adjustments(*callee); match &callee_ty.kind(Interner) { chalk_ir::TyKind::FnDef(..) => { - let func = Operand::from_bytes(vec![], callee_ty.clone()); + let func = Operand::from_bytes(Box::default(), callee_ty.clone()); self.lower_call_and_args( func, args.iter().copied(), @@ -828,12 +828,12 @@ impl<'ctx> MirLowerCtx<'ctx> { Some(it) => it, None => { let p = sp.project( - ProjectionElem::Field(FieldId { + ProjectionElem::Field(Either::Left(FieldId { parent: variant_id, local_id: LocalFieldId::from_raw(RawIdx::from( i as u32, )), - }), + })), &mut self.result.projection_store, ); Operand::Copy(p) @@ -855,7 +855,10 @@ impl<'ctx> MirLowerCtx<'ctx> { let local_id = variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?; let place = place.project( - PlaceElem::Field(FieldId { parent: union_id.into(), local_id }), + PlaceElem::Field(Either::Left(FieldId { + parent: union_id.into(), + local_id, + })), &mut self.result.projection_store, ); self.lower_expr_to_place(*expr, place, current) @@ -1110,7 +1113,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Some("start") => lp.take(), Some("end") => rp.take(), Some("exhausted") => { - Some(Operand::from_bytes(vec![0], TyBuilder::bool())) + Some(Operand::from_bytes(Box::new([0]), TyBuilder::bool())) } _ => None, }; @@ -1142,8 +1145,8 @@ impl<'ctx> MirLowerCtx<'ctx> { .map(|it| match it { ProjectionElem::Deref => ProjectionElem::Deref, ProjectionElem::Field(it) => ProjectionElem::Field(it), - ProjectionElem::TupleOrClosureField(it) => { - ProjectionElem::TupleOrClosureField(it) + ProjectionElem::ClosureField(it) => { + ProjectionElem::ClosureField(it) } ProjectionElem::ConstantIndex { offset, from_end } => { ProjectionElem::ConstantIndex { offset, from_end } @@ -1273,7 +1276,10 @@ impl<'ctx> MirLowerCtx<'ctx> { Expr::Tuple { exprs, is_assignee_expr: _ } => { for (i, expr) in exprs.iter().enumerate() { let rhs = rhs.project( - ProjectionElem::TupleOrClosureField(i), + ProjectionElem::Field(Either::Right(TupleFieldId { + tuple: TupleId(!0), // Dummy this as its unused + index: i as u32, + })), &mut self.result.projection_store, ); let Some(c) = self.lower_destructing_assignment(current, *expr, rhs, span)? @@ -1337,11 +1343,14 @@ impl<'ctx> MirLowerCtx<'ctx> { fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> { if let Expr::Field { expr, name } = &self.body[expr_id] { if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind(Interner) { - let index = name - .as_tuple_index() - .ok_or(MirLowerError::TypeError("named field on tuple"))?; + let index = + name.as_tuple_index().ok_or(MirLowerError::TypeError("named field on tuple"))? + as u32; *place = place.project( - ProjectionElem::TupleOrClosureField(index), + ProjectionElem::Field(Either::Right(TupleFieldId { + tuple: TupleId(!0), // dummy as its unused + index, + })), &mut self.result.projection_store, ) } else { @@ -1386,46 +1395,43 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result { - let size = self - .db - .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner))? - .size - .bytes_usize(); - let bytes = match l { + let size = || { + self.db + .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner)) + .map(|it| it.size.bytes_usize()) + }; + const USIZE_SIZE: usize = mem::size_of::(); + let bytes: Box<[_]> = match l { hir_def::hir::Literal::String(b) => { - let b = b.as_bytes(); - let mut data = Vec::with_capacity(mem::size_of::() * 2); - data.extend(0usize.to_le_bytes()); - data.extend(b.len().to_le_bytes()); - let mut mm = MemoryMap::default(); - mm.insert(0, b.to_vec()); - return Ok(Operand::from_concrete_const(data, mm, ty)); + let mut data = [0; { 2 * USIZE_SIZE }]; + data[..USIZE_SIZE].copy_from_slice(&0usize.to_le_bytes()); + data[USIZE_SIZE..].copy_from_slice(&b.len().to_le_bytes()); + let mm = MemoryMap::simple(b.as_bytes().into()); + return Ok(Operand::from_concrete_const(Box::new(data), mm, ty)); } hir_def::hir::Literal::CString(b) => { - let bytes = b.iter().copied().chain(iter::once(0)).collect::>(); + let bytes = b.iter().copied().chain(iter::once(0)).collect::>(); - let mut data = Vec::with_capacity(mem::size_of::() * 2); - data.extend(0usize.to_le_bytes()); - data.extend(bytes.len().to_le_bytes()); - let mut mm = MemoryMap::default(); - mm.insert(0, bytes); - return Ok(Operand::from_concrete_const(data, mm, ty)); + let mut data = [0; { 2 * USIZE_SIZE }]; + data[..USIZE_SIZE].copy_from_slice(&0usize.to_le_bytes()); + data[USIZE_SIZE..].copy_from_slice(&bytes.len().to_le_bytes()); + let mm = MemoryMap::simple(bytes); + return Ok(Operand::from_concrete_const(Box::new(data), mm, ty)); } hir_def::hir::Literal::ByteString(b) => { - let mut data = Vec::with_capacity(mem::size_of::() * 2); - data.extend(0usize.to_le_bytes()); - data.extend(b.len().to_le_bytes()); - let mut mm = MemoryMap::default(); - mm.insert(0, b.to_vec()); - return Ok(Operand::from_concrete_const(data, mm, ty)); + let mut data = [0; { 2 * USIZE_SIZE }]; + data[..USIZE_SIZE].copy_from_slice(&0usize.to_le_bytes()); + data[USIZE_SIZE..].copy_from_slice(&b.len().to_le_bytes()); + let mm = MemoryMap::simple(b.clone()); + return Ok(Operand::from_concrete_const(Box::new(data), mm, ty)); } - hir_def::hir::Literal::Char(c) => u32::from(*c).to_le_bytes().into(), - hir_def::hir::Literal::Bool(b) => vec![*b as u8], - hir_def::hir::Literal::Int(it, _) => it.to_le_bytes()[0..size].into(), - hir_def::hir::Literal::Uint(it, _) => it.to_le_bytes()[0..size].into(), - hir_def::hir::Literal::Float(f, _) => match size { - 8 => f.into_f64().to_le_bytes().into(), - 4 => f.into_f32().to_le_bytes().into(), + hir_def::hir::Literal::Char(c) => Box::new(u32::from(*c).to_le_bytes()), + hir_def::hir::Literal::Bool(b) => Box::new([*b as u8]), + hir_def::hir::Literal::Int(it, _) => Box::from(&it.to_le_bytes()[0..size()?]), + hir_def::hir::Literal::Uint(it, _) => Box::from(&it.to_le_bytes()[0..size()?]), + hir_def::hir::Literal::Float(f, _) => match size()? { + 8 => Box::new(f.into_f64().to_le_bytes()), + 4 => Box::new(f.into_f32().to_le_bytes()), _ => { return Err(MirLowerError::TypeError("float with size other than 4 or 8 bytes")) } @@ -1474,7 +1480,7 @@ impl<'ctx> MirLowerCtx<'ctx> { &mut self, prev_block: BasicBlockId, place: Place, - cv: Vec, + cv: Box<[u8]>, ty: Ty, span: MirSpan, ) -> Result<()> { @@ -2041,10 +2047,11 @@ pub fn mir_body_for_closure_query( match (it, y) { (ProjectionElem::Deref, ProjectionElem::Deref) => (), (ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (), - ( - ProjectionElem::TupleOrClosureField(it), - ProjectionElem::TupleOrClosureField(y), - ) if it == y => (), + (ProjectionElem::ClosureField(it), ProjectionElem::ClosureField(y)) + if it == y => + { + () + } _ => return false, } } @@ -2054,7 +2061,7 @@ pub fn mir_body_for_closure_query( Some(it) => { p.local = closure_local; let mut next_projs = closure_projection.clone(); - next_projs.push(PlaceElem::TupleOrClosureField(it.1)); + next_projs.push(PlaceElem::ClosureField(it.1)); let prev_projs = p.projection; if it.0.kind != CaptureKind::ByValue { next_projs.push(ProjectionElem::Deref); @@ -2063,8 +2070,8 @@ pub fn mir_body_for_closure_query( prev_projs .lookup(&store) .iter() - .cloned() - .skip(it.0.place.projections.len()), + .skip(it.0.place.projections.len()) + .cloned(), ); p.projection = store.intern(next_projs.into()); } diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs index 8c078eb4ad75..cb5588a5c13d 100644 --- a/crates/hir-ty/src/mir/lower/as_place.rs +++ b/crates/hir-ty/src/mir/lower/as_place.rs @@ -218,7 +218,7 @@ impl MirLowerCtx<'_> { self.push_field_projection(&mut r, expr_id)?; Ok(Some((r, current))) } - Expr::Index { base, index } => { + Expr::Index { base, index, is_assignee_expr: _ } => { let base_ty = self.expr_ty_after_adjustments(*base); let index_ty = self.expr_ty_after_adjustments(*index); if index_ty != TyBuilder::usize() diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 1120bb1c1123..98c2e7c63bc1 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -108,7 +108,12 @@ impl MirLowerCtx<'_> { current_else, args, *ellipsis, - (0..subst.len(Interner)).map(|i| PlaceElem::TupleOrClosureField(i)), + (0..subst.len(Interner)).map(|i| { + PlaceElem::Field(Either::Right(TupleFieldId { + tuple: TupleId(!0), // Dummy as it is unused + index: i as u32, + })) + }), &(&mut cond_place), mode, )? @@ -239,7 +244,7 @@ impl MirLowerCtx<'_> { ); } else { let c = Operand::from_concrete_const( - pattern_len.to_le_bytes().to_vec(), + pattern_len.to_le_bytes().into(), MemoryMap::default(), TyBuilder::usize(), ); @@ -566,7 +571,10 @@ impl MirLowerCtx<'_> { let field_id = variant_data.field(&x.name).ok_or(MirLowerError::UnresolvedField)?; Ok(( - PlaceElem::Field(FieldId { parent: v.into(), local_id: field_id }), + PlaceElem::Field(Either::Left(FieldId { + parent: v.into(), + local_id: field_id, + })), x.pat, )) }) @@ -574,10 +582,9 @@ impl MirLowerCtx<'_> { self.pattern_match_adt(current, current_else, it.into_iter(), cond_place, mode)? } AdtPatternShape::Tuple { args, ellipsis } => { - let fields = variant_data - .fields() - .iter() - .map(|(x, _)| PlaceElem::Field(FieldId { parent: v.into(), local_id: x })); + let fields = variant_data.fields().iter().map(|(x, _)| { + PlaceElem::Field(Either::Left(FieldId { parent: v.into(), local_id: x })) + }); self.pattern_match_tuple_like( current, current_else, diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs index a91f90bc249e..366c2f662b54 100644 --- a/crates/hir-ty/src/mir/pretty.rs +++ b/crates/hir-ty/src/mir/pretty.rs @@ -5,6 +5,7 @@ use std::{ mem, }; +use either::Either; use hir_def::{body::Body, hir::BindingId}; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -298,7 +299,7 @@ impl<'a> MirPrettyCtx<'a> { f(this, local, head); w!(this, ")"); } - ProjectionElem::Field(field) => { + ProjectionElem::Field(Either::Left(field)) => { let variant_data = field.parent.variant_data(this.db.upcast()); let name = &variant_data.fields()[field.local_id].name; match field.parent { @@ -320,7 +321,11 @@ impl<'a> MirPrettyCtx<'a> { } } } - ProjectionElem::TupleOrClosureField(it) => { + ProjectionElem::Field(Either::Right(field)) => { + f(this, local, head); + w!(this, ".{}", field.index); + } + ProjectionElem::ClosureField(it) => { f(this, local, head); w!(this, ".{}", it); } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 003ae60e8e51..d270328605a9 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -4506,3 +4506,50 @@ fn ttt() { "#, ); } + +#[test] +fn infer_borrow() { + check_types( + r#" +//- minicore: index +pub struct SomeMap; + +pub trait Borrow { + fn borrow(&self) -> &Borrowed; +} + +impl Borrow for T { + fn borrow(&self) -> &T { + self + } +} + +impl Borrow for &T { + fn borrow(&self) -> &T { + &**self + } +} + +impl> core::ops::Index for SomeMap { + type Output = (); + + fn index(&self, _: KB) -> &() { + &() + } +} + +impl core::ops::IndexMut for SomeMap { + fn index_mut(&mut self, _: K) -> &mut () { + &mut () + } +} + +fn foo() { + let mut map = SomeMap; + map["a"] = (); + map; + //^^^ SomeMap<&str> +} +"#, + ); +} diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index d60d20f5b7ee..60ddc4aa86fe 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -1,5 +1,7 @@ //! Attributes & documentation for hir types. +use std::ops::ControlFlow; + use base_db::FileId; use hir_def::{ attr::AttrsWithOwner, @@ -13,13 +15,13 @@ use hir_expand::{ name::Name, span_map::{RealSpanMap, SpanMapRef}, }; -use hir_ty::db::HirDatabase; +use hir_ty::{db::HirDatabase, method_resolution}; use syntax::{ast, AstNode}; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, - Field, Function, GenericParam, Impl, LifetimeParam, Macro, Module, ModuleDef, Static, Struct, - Trait, TraitAlias, TypeAlias, TypeParam, Union, Variant, VariantDef, + Field, Function, GenericParam, HasCrate, Impl, LifetimeParam, Macro, Module, ModuleDef, Static, + Struct, Trait, TraitAlias, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, }; pub trait HasAttrs { @@ -99,9 +101,6 @@ pub fn resolve_doc_path_on( link: &str, ns: Option, ) -> Option { - // AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()), - // AttrDefId::EnumVariantId(it) => it.parent.resolver(db.upcast()), - resolve_doc_path_on_(db, link, def.attr_id(), ns) } @@ -205,8 +204,14 @@ fn resolve_assoc_or_field( } }; - // FIXME: Resolve associated items here, e.g. `Option::map`. Note that associated items take - // precedence over fields. + // Resolve inherent items first, then trait items, then fields. + if let Some(assoc_item_def) = resolve_assoc_item(db, &ty, &name, ns) { + return Some(assoc_item_def); + } + + if let Some(impl_trait_item_def) = resolve_impl_trait_item(db, resolver, &ty, &name, ns) { + return Some(impl_trait_item_def); + } let variant_def = match ty.as_adt()? { Adt::Struct(it) => it.into(), @@ -216,6 +221,65 @@ fn resolve_assoc_or_field( resolve_field(db, variant_def, name, ns) } +fn resolve_assoc_item( + db: &dyn HirDatabase, + ty: &Type, + name: &Name, + ns: Option, +) -> Option { + ty.iterate_assoc_items(db, ty.krate(db), move |assoc_item| { + if assoc_item.name(db)? != *name { + return None; + } + as_module_def_if_namespace_matches(assoc_item, ns) + }) +} + +fn resolve_impl_trait_item( + db: &dyn HirDatabase, + resolver: Resolver, + ty: &Type, + name: &Name, + ns: Option, +) -> Option { + let canonical = ty.canonical(); + let krate = ty.krate(db); + let environment = resolver.generic_def().map_or_else( + || crate::TraitEnvironment::empty(krate.id).into(), + |d| db.trait_environment(d), + ); + let traits_in_scope = resolver.traits_in_scope(db.upcast()); + + let mut result = None; + + // `ty.iterate_path_candidates()` require a scope, which is not available when resolving + // attributes here. Use path resolution directly instead. + // + // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) + method_resolution::iterate_path_candidates( + &canonical, + db, + environment, + &traits_in_scope, + method_resolution::VisibleFromModule::None, + Some(name), + &mut |assoc_item_id| { + // If two traits in scope define the same item, Rustdoc links to no specific trait (for + // instance, given two methods `a`, Rustdoc simply links to `method.a` with no + // disambiguation) so we just pick the first one we find as well. + result = as_module_def_if_namespace_matches(assoc_item_id.into(), ns); + + if result.is_some() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }, + ); + + result +} + fn resolve_field( db: &dyn HirDatabase, def: VariantDef, @@ -228,6 +292,19 @@ fn resolve_field( def.fields(db).into_iter().find(|f| f.name(db) == name).map(DocLinkDef::Field) } +fn as_module_def_if_namespace_matches( + assoc_item: AssocItem, + ns: Option, +) -> Option { + let (def, expected_ns) = match assoc_item { + AssocItem::Function(it) => (ModuleDef::Function(it), Namespace::Values), + AssocItem::Const(it) => (ModuleDef::Const(it), Namespace::Values), + AssocItem::TypeAlias(it) => (ModuleDef::TypeAlias(it), Namespace::Types), + }; + + (ns.unwrap_or(expected_ns) == expected_ns).then(|| DocLinkDef::ModuleDef(def)) +} + fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option { // FIXME: this is not how we should get a mod path here. let try_get_modpath = |link: &str| { diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 5847c8a9fb52..9b99b141fc5e 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -19,8 +19,8 @@ use hir_ty::{ use crate::{ Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, - Static, Struct, Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, - Union, Variant, + Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, + TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -257,6 +257,13 @@ impl HirDisplay for Field { } } +impl HirDisplay for TupleField { + fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { + write!(f, "pub {}: ", self.name().display(f.db.upcast()))?; + self.ty(f.db).hir_fmt(f) + } +} + impl HirDisplay for Variant { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 09b56e138241..0266915c39b6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -55,7 +55,7 @@ use hir_def::{ AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, - Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, + Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind}; @@ -1038,6 +1038,29 @@ pub struct Field { pub(crate) id: LocalFieldId, } +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub struct TupleField { + pub owner: DefWithBodyId, + pub tuple: TupleId, + pub index: u32, +} + +impl TupleField { + pub fn name(&self) -> Name { + Name::new_tuple_field(self.index as usize) + } + + pub fn ty(&self, db: &dyn HirDatabase) -> Type { + let ty = db.infer(self.owner).tuple_field_access_types[&self.tuple] + .as_slice(Interner) + .get(self.index as usize) + .and_then(|arg| arg.ty(Interner)) + .cloned() + .unwrap_or_else(|| TyKind::Error.intern(Interner)); + Type { env: db.trait_environment_for_body(self.owner), ty } + } +} + #[derive(Debug, PartialEq, Eq)] pub enum FieldSource { Named(ast::RecordField), @@ -1070,7 +1093,7 @@ impl Field { pub fn layout(&self, db: &dyn HirDatabase) -> Result { db.layout_of_ty( - self.ty(db).ty.clone(), + self.ty(db).ty, db.trait_environment(match hir_def::VariantId::from(self.parent) { hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id), hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()), @@ -1831,7 +1854,7 @@ impl DefWithBody { let local = Local { parent: self.into(), binding_id }; match (need_mut, local.is_mut(db)) { (mir::MutabilityReason::Unused, _) => { - let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with("_")); + let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_')); if !should_ignore { acc.push(UnusedVariable { local }.into()) } @@ -1856,7 +1879,7 @@ impl DefWithBody { } (mir::MutabilityReason::Not, true) => { if !infer.mutated_bindings_in_closure.contains(&binding_id) { - let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with("_")); + let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_')); if !should_ignore { acc.push(UnusedMut { local }.into()) } @@ -2160,7 +2183,7 @@ impl Function { return r; } }; - let (result, stdout, stderr) = interpret_mir(db, body, false, None); + let (result, output) = interpret_mir(db, body, false, None); let mut text = match result { Ok(_) => "pass".to_string(), Err(e) => { @@ -2169,10 +2192,12 @@ impl Function { r } }; + let stdout = output.stdout().into_owned(); if !stdout.is_empty() { text += "\n--------- stdout ---------\n"; text += &stdout; } + let stderr = output.stdout().into_owned(); if !stderr.is_empty() { text += "\n--------- stderr ---------\n"; text += &stderr; @@ -3648,7 +3673,6 @@ impl Closure { let (captures, _) = infer.closure_info(&self.id); captures .iter() - .cloned() .map(|capture| Type { env: db.trait_environment_for_body(owner), ty: capture.ty(&self.subst), @@ -4121,6 +4145,10 @@ impl Type { } } + pub(crate) fn canonical(&self) -> Canonical { + hir_ty::replace_errors_with_variables(&self.ty) + } + /// Returns types that this type dereferences to (including this type itself). The returned /// iterator won't yield the same type more than once even if the deref chain contains a cycle. pub fn autoderef(&self, db: &dyn HirDatabase) -> impl Iterator + '_ { diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index fdc604a006fc..f51fe80931c6 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -40,7 +40,7 @@ use crate::{ Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate, DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Struct, ToolModule, Trait, - Type, TypeAlias, TypeParam, VariantDef, + TupleField, Type, TypeAlias, TypeParam, VariantDef, }; pub enum DescendPreference { @@ -428,7 +428,7 @@ impl<'db> SemanticsImpl<'db> { if let Some(original_string) = ast::String::cast(original_token.clone()) { if let Some(quote) = original_string.open_quote_text_range() { return self - .descend_into_macros(DescendPreference::SameText, original_token.clone()) + .descend_into_macros(DescendPreference::SameText, original_token) .into_iter() .find_map(|token| { self.resolve_offset_in_format_args( @@ -1085,14 +1085,14 @@ impl<'db> SemanticsImpl<'db> { self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call) } - pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option { + pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option> { self.analyze(field.syntax())?.resolve_field(self.db, field) } pub fn resolve_field_fallback( &self, field: &ast::FieldExpr, - ) -> Option> { + ) -> Option, Function>> { self.analyze(field.syntax())?.resolve_field_fallback(self.db, field) } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 54b4d81012f3..73f8db762ae8 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -50,7 +50,7 @@ use triomphe::Arc; use crate::{ db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, Function, Local, Macro, ModuleDef, Static, - Struct, ToolModule, Trait, TraitAlias, Type, TypeAlias, Variant, + Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, Variant, }; /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of @@ -297,7 +297,11 @@ impl SourceAnalyzer { Some((f_in_trait, substs)) => Some(Either::Left( self.resolve_impl_method_or_trait_def(db, f_in_trait, substs).into(), )), - None => inference_result.field_resolution(expr_id).map(Into::into).map(Either::Right), + None => inference_result + .field_resolution(expr_id) + .and_then(Either::left) + .map(Into::into) + .map(Either::Right), } } @@ -305,20 +309,28 @@ impl SourceAnalyzer { &self, db: &dyn HirDatabase, field: &ast::FieldExpr, - ) -> Option { + ) -> Option> { + let &(def, ..) = self.def.as_ref()?; let expr_id = self.expr_id(db, &field.clone().into())?; - self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into()) + self.infer.as_ref()?.field_resolution(expr_id).map(|it| { + it.map_either(Into::into, |f| TupleField { owner: def, tuple: f.tuple, index: f.index }) + }) } pub(crate) fn resolve_field_fallback( &self, db: &dyn HirDatabase, field: &ast::FieldExpr, - ) -> Option> { + ) -> Option, Function>> { + let &(def, ..) = self.def.as_ref()?; let expr_id = self.expr_id(db, &field.clone().into())?; let inference_result = self.infer.as_ref()?; match inference_result.field_resolution(expr_id) { - Some(field) => Some(Either::Left(field.into())), + Some(field) => Some(Either::Left(field.map_either(Into::into, |f| TupleField { + owner: def, + tuple: f.tuple, + index: f.index, + }))), None => inference_result.method_resolution(expr_id).map(|(f, substs)| { Either::Right(self.resolve_impl_method_or_trait_def(db, f, substs).into()) }), diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 4da0dfba6755..841ddfb9c437 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -18,11 +18,11 @@ use crate::{Module, ModuleDef, Semantics}; /// possible. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FileSymbol { - // even though name can be derived from the def, we store it for efficiency pub name: SmolStr, pub def: ModuleDef, pub loc: DeclarationLocation, pub container_name: Option, + /// Whether this symbol is a doc alias for the original symbol. pub is_alias: bool, pub is_assoc: bool, } @@ -163,11 +163,9 @@ impl<'a> SymbolCollector<'a> { } // Record renamed imports. - // In case it imports multiple items under different namespaces we just pick one arbitrarily + // FIXME: In case it imports multiple items under different namespaces we just pick one arbitrarily // for now. for id in scope.imports() { - let loc = id.import.lookup(self.db.upcast()); - loc.id.item_tree(self.db.upcast()); let source = id.import.child_source(self.db.upcast()); let Some(use_tree_src) = source.value.get(id.idx) else { continue }; let Some(rename) = use_tree_src.rename() else { continue }; diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs index 1f785b5d0a81..7b71d9b86968 100644 --- a/crates/ide-assists/src/handlers/auto_import.rs +++ b/crates/ide-assists/src/handlers/auto_import.rs @@ -89,12 +89,14 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; // ``` pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (import_assets, syntax_under_caret) = find_importable_node(ctx)?; - let mut proposed_imports = import_assets.search_for_imports( - &ctx.sema, - ctx.config.insert_use.prefix_kind, - ctx.config.prefer_no_std, - ctx.config.prefer_no_std, - ); + let mut proposed_imports: Vec<_> = import_assets + .search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ctx.config.prefer_no_std, + ) + .collect(); if proposed_imports.is_empty() { return None; } @@ -113,6 +115,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< )?; // we aren't interested in different namespaces + proposed_imports.sort_by(|a, b| a.import_path.cmp(&b.import_path)); proposed_imports.dedup_by(|a, b| a.import_path == b.import_path); let current_node = match ctx.covering_element() { diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index b7b00e7ed068..dc1952c3ff3c 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -301,7 +301,7 @@ fn replace_usages( // add imports across modules where needed if let Some((import_scope, path)) = import_data { - let scope = match import_scope.clone() { + let scope = match import_scope { ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), @@ -329,7 +329,7 @@ fn augment_references_with_imports( references .into_iter() .filter_map(|FileReference { range, name, .. }| { - let name = name.clone().into_name_like()?; + let name = name.into_name_like()?; ctx.sema.scope(name.syntax()).map(|scope| (range, name, scope.module())) }) .map(|(range, name, ref_module)| { diff --git a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs index 5f7056b9c1c4..79c34c14da72 100644 --- a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs +++ b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs @@ -1,5 +1,6 @@ use hir::Semantics; use ide_db::RootDatabase; +use syntax::ast::RangeItem; use syntax::ast::{edit::AstNodeEdit, AstNode, HasName, LetStmt, Name, Pat}; use syntax::T; diff --git a/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs b/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs index 399f87c8f509..c30f3e1c3b2b 100644 --- a/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs +++ b/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs @@ -49,8 +49,8 @@ pub(crate) fn convert_nested_function_to_closure( target, |edit| { let params = ¶m_list.syntax().text().to_string(); - let params = params.strip_prefix("(").unwrap_or(params); - let params = params.strip_suffix(")").unwrap_or(params); + let params = params.strip_prefix('(').unwrap_or(params); + let params = params.strip_suffix(')').unwrap_or(params); let mut body = body.to_string(); if !has_semicolon(&function) { diff --git a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs index 79b46d66121e..41366658a74b 100644 --- a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs +++ b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -190,7 +190,7 @@ fn augment_references_with_imports( ctx.sema.scope(name.syntax()).map(|scope| (name, scope.module())) }) .map(|(name, ref_module)| { - let new_name = edit.make_mut(name.clone()); + let new_name = edit.make_mut(name); // if the referenced module is not the same as the target one and has not been seen before, add an import let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module diff --git a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index 37db27a8fc02..65e2a0184779 100644 --- a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -6,6 +6,7 @@ use ide_db::{ defs::Definition, helpers::mod_path_to_ast, imports::insert_use::{insert_use, ImportScope, InsertUseConfig}, + path_transform::PathTransform, search::FileReference, FxHashSet, RootDatabase, }; @@ -105,6 +106,16 @@ pub(crate) fn extract_struct_from_enum_variant( .generic_param_list() .and_then(|known_generics| extract_generic_params(&known_generics, &field_list)); let generics = generic_params.as_ref().map(|generics| generics.clone_for_update()); + + // resolve GenericArg in field_list to actual type + let field_list = field_list.clone_for_update(); + if let Some((target_scope, source_scope)) = + ctx.sema.scope(enum_ast.syntax()).zip(ctx.sema.scope(field_list.syntax())) + { + PathTransform::generic_transformation(&target_scope, &source_scope) + .apply(field_list.syntax()); + } + let def = create_struct_def(variant_name.clone(), &variant, &field_list, generics, &enum_ast); @@ -244,8 +255,6 @@ fn create_struct_def( // for fields without any existing visibility, use visibility of enum let field_list: ast::FieldList = match field_list { Either::Left(field_list) => { - let field_list = field_list.clone_for_update(); - if let Some(vis) = &enum_vis { field_list .fields() @@ -254,11 +263,9 @@ fn create_struct_def( .for_each(|it| insert_vis(it.syntax(), vis.syntax())); } - field_list.into() + field_list.clone().into() } Either::Right(field_list) => { - let field_list = field_list.clone_for_update(); - if let Some(vis) = &enum_vis { field_list .fields() @@ -267,7 +274,7 @@ fn create_struct_def( .for_each(|it| insert_vis(it.syntax(), vis.syntax())); } - field_list.into() + field_list.clone().into() } }; field_list.reindent_to(IndentLevel::single()); @@ -425,6 +432,59 @@ mod tests { use super::*; + #[test] + fn issue_16197() { + check_assist( + extract_struct_from_enum_variant, + r#" +enum Foo { + Bar $0{ node: Box }, + Nil, +} +"#, + r#" +struct Bar{ node: Box } + +enum Foo { + Bar(Bar), + Nil, +} +"#, + ); + check_assist( + extract_struct_from_enum_variant, + r#" +enum Foo { + Bar $0{ node: Box, a: Arc> }, + Nil, +} +"#, + r#" +struct Bar{ node: Box, a: Arc> } + +enum Foo { + Bar(Bar), + Nil, +} +"#, + ); + check_assist( + extract_struct_from_enum_variant, + r#" +enum Foo { + Nil(Box$0, Arc>), +} +"#, + r#" +struct Nil(Box, Arc>); + +enum Foo { + Nil(Nil), +} +"#, + ); + } + #[test] fn test_extract_struct_several_fields_tuple() { check_assist( diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs index 874b81d3b637..0b3bd0bed6ed 100644 --- a/crates/ide-assists/src/handlers/extract_variable.rs +++ b/crates/ide-assists/src/handlers/extract_variable.rs @@ -112,7 +112,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let insert_place = edit.make_syntax_mut(place); // Adjust ws to insert depending on if this is all inline or on separate lines - let trailing_ws = if prev_ws.is_some_and(|it| it.text().starts_with("\n")) { + let trailing_ws = if prev_ws.is_some_and(|it| it.text().starts_with('\n')) { format!("\n{indent_to}") } else { format!(" ") diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index db1e0ceaec1e..dc02aaf9af68 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -147,7 +147,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' None => { let name = &strukt_name.to_string(); let params = strukt.generic_param_list(); - let ty_params = params.clone(); + let ty_params = params; let where_clause = strukt.where_clause(); let impl_def = make::impl_( diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 0d34502add94..339c3ac71ecd 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -17,7 +17,7 @@ use syntax::{ self, edit::{self, AstNodeEdit}, make, AssocItem, GenericArgList, GenericParamList, HasGenericParams, HasName, - HasTypeBounds, HasVisibility as astHasVisibility, Path, + HasTypeBounds, HasVisibility as astHasVisibility, Path, WherePred, }, ted::{self, Position}, AstNode, NodeOrToken, SmolStr, SyntaxKind, @@ -217,9 +217,9 @@ impl Struct { }; acc.add_group( - &GroupLabel(format!("Generate delegate impls for field `{}`", field.name)), + &GroupLabel(format!("Generate delegate trait impls for field `{}`", field.name)), AssistId("generate_delegate_trait", ide_db::assists::AssistKind::Generate), - format!("Generate delegate impl `{}` for `{}`", signature, field.name), + format!("Generate delegate trait impl `{}` for `{}`", signature, field.name), field.range, |builder| { builder.insert( @@ -243,12 +243,12 @@ fn generate_impl( let db = ctx.db(); let ast_strukt = &strukt.strukt; let strukt_ty = make::ty_path(make::ext::ident_path(&strukt.name.to_string())); + let strukt_params = ast_strukt.generic_param_list(); match delegee { Delegee::Bound(delegee) => { let bound_def = ctx.sema.source(delegee.to_owned())?.value; let bound_params = bound_def.generic_param_list(); - let strukt_params = ast_strukt.generic_param_list(); delegate = make::impl_trait( delegee.is_unsafe(db), @@ -266,11 +266,8 @@ fn generate_impl( .clone_for_update(); // Goto link : https://doc.rust-lang.org/reference/paths.html#qualified-paths - let qualified_path_type = make::path_from_text(&format!( - "<{} as {}>", - field_ty.to_string(), - delegate.trait_()?.to_string() - )); + let qualified_path_type = + make::path_from_text(&format!("<{} as {}>", field_ty, delegate.trait_()?)); let delegate_assoc_items = delegate.get_or_create_assoc_item_list(); match bound_def.assoc_item_list() { @@ -295,63 +292,73 @@ fn generate_impl( } Delegee::Impls(trait_, old_impl) => { let old_impl = ctx.sema.source(old_impl.to_owned())?.value; + let old_impl_params = old_impl.generic_param_list(); + + // 1) Resolve conflicts between generic parameters in old_impl and + // those in strukt. + // + // These generics parameters will also be used in `field_ty` and + // `where_clauses`, so we should substitude arguments in them as well. + let strukt_params = resolve_name_conflicts(strukt_params, &old_impl_params); + let (field_ty, ty_where_clause) = match &strukt_params { + Some(strukt_params) => { + let args = strukt_params.to_generic_args(); + let field_ty = rename_strukt_args(ctx, ast_strukt, field_ty, &args)?; + let where_clause = ast_strukt + .where_clause() + .and_then(|wc| Some(rename_strukt_args(ctx, ast_strukt, &wc, &args)?)); + (field_ty, where_clause) + } + None => (field_ty.clone_for_update(), None), + }; + + // 2) Handle instantiated generics in `field_ty`. + + // 2.1) Some generics used in `self_ty` may be instantiated, so they + // are no longer generics, we should remove and instantiate those + // generics in advance. // `old_trait_args` contains names of generic args for trait in `old_impl` - let old_trait_args = old_impl + let old_impl_trait_args = old_impl .trait_()? .generic_arg_list() .map(|l| l.generic_args().map(|arg| arg.to_string())) .map_or_else(|| FxHashSet::default(), |it| it.collect()); - let old_impl_params = old_impl.generic_param_list(); + let trait_gen_params = remove_instantiated_params( + &old_impl.self_ty()?, + old_impl_params.clone(), + &old_impl_trait_args, + ); - // Resolve conflicts with generic parameters in strukt. - // These generics parameters will also be used in `field_ty` and `where_clauses`, - // so we should substitude arguments in them as well. - let (renamed_strukt_params, field_ty, ty_where_clause) = if let Some(strukt_params) = - resolve_conflicts_for_strukt(ast_strukt, old_impl_params.as_ref()) - { - let strukt_args = strukt_params.to_generic_args(); - let field_ty = - subst_name_in_strukt(ctx, ast_strukt, field_ty, strukt_args.clone())?; - let wc = ast_strukt - .where_clause() - .and_then(|wc| Some(subst_name_in_strukt(ctx, ast_strukt, &wc, strukt_args)?)); - (Some(strukt_params), field_ty, wc) - } else { - (None, field_ty.clone_for_update(), None) - }; - - // Some generics used in `field_ty` may be instantiated, so they are no longer - // `generics`. We should remove them from generics params, and use the rest params. - let trait_gen_params = - remove_instantiated_params(&old_impl.self_ty()?, old_impl_params, &old_trait_args); - - // Generate generic args that applied to current impl, this step will also remove unused params - let args_for_impl = - get_args_for_impl(&old_impl, &field_ty, &trait_gen_params, &old_trait_args); + // 2.2) Generate generic args applied on impl. + let transform_args = generate_args_for_impl( + old_impl_params, + &old_impl.self_ty()?, + &field_ty, + &trait_gen_params, + &old_impl_trait_args, + ); + // 2.3) Instantiate generics with `transform_impl`, this step also + // remove unused params. let mut trait_gen_args = old_impl.trait_()?.generic_arg_list(); - if let Some(arg_list) = &mut trait_gen_args { - *arg_list = arg_list.clone_for_update(); - transform_impl(ctx, ast_strukt, &old_impl, &args_for_impl, &arg_list.syntax())?; + if let Some(trait_args) = &mut trait_gen_args { + *trait_args = trait_args.clone_for_update(); + transform_impl(ctx, ast_strukt, &old_impl, &transform_args, &trait_args.syntax())?; } - let mut type_gen_args = - renamed_strukt_params.clone().map(|params| params.to_generic_args()); - if let Some(type_args) = &mut type_gen_args { - *type_args = type_args.clone_for_update(); - transform_impl(ctx, ast_strukt, &old_impl, &args_for_impl, &type_args.syntax())?; - } + let type_gen_args = strukt_params.clone().map(|params| params.to_generic_args()); let path_type = make::ty(&trait_.name(db).to_smol_str()).clone_for_update(); - transform_impl(ctx, ast_strukt, &old_impl, &args_for_impl, &path_type.syntax())?; + transform_impl(ctx, ast_strukt, &old_impl, &transform_args, &path_type.syntax())?; + // 3) Generate delegate trait impl delegate = make::impl_trait( trait_.is_unsafe(db), trait_gen_params, trait_gen_args, - renamed_strukt_params, + strukt_params, type_gen_args, trait_.is_auto(db), path_type, @@ -363,30 +370,26 @@ fn generate_impl( .clone_for_update(); // Goto link : https://doc.rust-lang.org/reference/paths.html#qualified-paths - let qualified_path_type = make::path_from_text(&format!( - "<{} as {}>", - field_ty.to_string(), - delegate.trait_()?.to_string() - )); + let qualified_path_type = + make::path_from_text(&format!("<{} as {}>", field_ty, delegate.trait_()?)); + // 4) Transform associated items in delegte trait impl let delegate_assoc_items = delegate.get_or_create_assoc_item_list(); for item in old_impl .get_or_create_assoc_item_list() .assoc_items() .filter(|item| matches!(item, AssocItem::MacroCall(_)).not()) { - let assoc = process_assoc_item( - transform_assoc_item(ctx, ast_strukt, &old_impl, &args_for_impl, item)?, - qualified_path_type.clone(), - &field_name, - )?; + let item = item.clone_for_update(); + transform_impl(ctx, ast_strukt, &old_impl, &transform_args, item.syntax())?; + let assoc = process_assoc_item(item, qualified_path_type.clone(), &field_name)?; delegate_assoc_items.add_item(assoc); } - // Remove unused where clauses + // 5) Remove useless where clauses if let Some(wc) = delegate.where_clause() { - remove_useless_where_clauses(&delegate, wc)?; + remove_useless_where_clauses(&delegate.trait_()?, &delegate.self_ty()?, wc); } } } @@ -394,32 +397,6 @@ fn generate_impl( Some(delegate) } -fn transform_assoc_item( - ctx: &AssistContext<'_>, - strukt: &ast::Struct, - old_impl: &ast::Impl, - args: &Option, - item: AssocItem, -) -> Option { - let source_scope = ctx.sema.scope(&item.syntax()).unwrap(); - let target_scope = ctx.sema.scope(&strukt.syntax())?; - let hir_old_impl = ctx.sema.to_impl_def(old_impl)?; - let item = item.clone_for_update(); - let transform = args.as_ref().map_or_else( - || PathTransform::generic_transformation(&target_scope, &source_scope), - |args| { - PathTransform::impl_transformation( - &target_scope, - &source_scope, - hir_old_impl, - args.clone(), - ) - }, - ); - transform.apply(&item.syntax()); - Some(item) -} - fn transform_impl( ctx: &AssistContext<'_>, strukt: &ast::Struct, @@ -463,11 +440,11 @@ fn remove_instantiated_params( .segments() .filter_map(|seg| seg.generic_arg_list()) .flat_map(|it| it.generic_args()) - // However, if the param is also used in the trait arguments, it shouldn't be removed. + // However, if the param is also used in the trait arguments, + // it shouldn't be removed now, which will be instantiated in + // later `path_transform` .filter(|arg| !old_trait_args.contains(&arg.to_string())) - .for_each(|arg| { - new_gpl.remove_generic_arg(&arg); - }); + .for_each(|arg| new_gpl.remove_generic_arg(&arg)); (new_gpl.generic_params().count() > 0).then_some(new_gpl) }) } @@ -475,49 +452,37 @@ fn remove_instantiated_params( } } -fn remove_useless_where_clauses(delegate: &ast::Impl, wc: ast::WhereClause) -> Option<()> { - let trait_args = - delegate.trait_()?.generic_arg_list().map(|trait_args| trait_args.generic_args()); - let strukt_args = - delegate.self_ty()?.generic_arg_list().map(|strukt_args| strukt_args.generic_args()); - let used_generic_names = match (trait_args, strukt_args) { - (None, None) => None, - (None, Some(y)) => Some(y.map(|arg| arg.to_string()).collect::>()), - (Some(x), None) => Some(x.map(|arg| arg.to_string()).collect::>()), - (Some(x), Some(y)) => Some(x.chain(y).map(|arg| arg.to_string()).collect::>()), - }; +fn remove_useless_where_clauses(trait_ty: &ast::Type, self_ty: &ast::Type, wc: ast::WhereClause) { + let live_generics = [trait_ty, self_ty] + .into_iter() + .flat_map(|ty| ty.generic_arg_list()) + .flat_map(|gal| gal.generic_args()) + .map(|x| x.to_string()) + .collect::>(); - // Keep clauses that have generic clauses after substitution, and remove the rest - if let Some(used_generic_names) = used_generic_names { - wc.predicates() - .filter(|pred| { - pred.syntax() - .descendants_with_tokens() - .filter_map(|e| e.into_token()) - .find(|e| { - e.kind() == SyntaxKind::IDENT && used_generic_names.contains(&e.to_string()) - }) - .is_none() - }) - .for_each(|pred| { - wc.remove_predicate(pred); - }); - } else { - wc.predicates().for_each(|pred| wc.remove_predicate(pred)); - } + // Keep where-clauses that have generics after substitution, and remove the + // rest. + let has_live_generics = |pred: &WherePred| { + pred.syntax() + .descendants_with_tokens() + .filter_map(|e| e.into_token()) + .any(|e| e.kind() == SyntaxKind::IDENT && live_generics.contains(&e.to_string())) + .not() + }; + wc.predicates().filter(has_live_generics).for_each(|pred| wc.remove_predicate(pred)); if wc.predicates().count() == 0 { // Remove useless whitespaces - wc.syntax() - .siblings_with_tokens(syntax::Direction::Prev) - .skip(1) - .take_while(|node_or_tok| node_or_tok.kind() == SyntaxKind::WHITESPACE) - .for_each(|ws| ted::remove(ws)); - wc.syntax() - .siblings_with_tokens(syntax::Direction::Next) - .skip(1) - .take_while(|node_or_tok| node_or_tok.kind() == SyntaxKind::WHITESPACE) + [syntax::Direction::Prev, syntax::Direction::Next] + .into_iter() + .flat_map(|dir| { + wc.syntax() + .siblings_with_tokens(dir) + .skip(1) + .take_while(|node_or_tok| node_or_tok.kind() == SyntaxKind::WHITESPACE) + }) .for_each(|ws| ted::remove(ws)); + ted::insert( ted::Position::after(wc.syntax()), NodeOrToken::Token(make::token(SyntaxKind::WHITESPACE)), @@ -525,84 +490,63 @@ fn remove_useless_where_clauses(delegate: &ast::Impl, wc: ast::WhereClause) -> O // Remove where clause ted::remove(wc.syntax()); } - - Some(()) } -fn get_args_for_impl( - old_impl: &ast::Impl, +// Generate generic args that should be apply to current impl. +// +// For exmaple, say we have implementation `impl Trait for B`, +// and `b: B` in struct `S`. Then the `A` should be instantiated to `T`. +// While the last two generic args `B` and `C` doesn't change, it remains +// ``. So we apply `` as generic arguments to impl. +fn generate_args_for_impl( + old_impl_gpl: Option, + self_ty: &ast::Type, field_ty: &ast::Type, trait_params: &Option, old_trait_args: &FxHashSet, ) -> Option { - // Generate generic args that should be apply to current impl - // - // For exmaple, if we have `impl Trait for B`, and `b: B` in `S`, - // then the generic `A` should be renamed to `T`. While the last two generic args - // doesn't change, it renames . So we apply `` as generic arguments - // to impl. - let old_impl_params = old_impl.generic_param_list(); - let self_ty = old_impl.self_ty(); + let Some(old_impl_args) = old_impl_gpl.map(|gpl| gpl.to_generic_args().generic_args()) else { + return None; + }; + // Create pairs of the args of `self_ty` and corresponding `field_ty` to + // form the substitution list + let mut arg_substs = FxHashMap::default(); - if let (Some(old_impl_gpl), Some(self_ty)) = (old_impl_params, self_ty) { - // Make pair of the arguments of `field_ty` and `old_strukt_args` to - // get the list for substitution - let mut arg_substs = FxHashMap::default(); - - match field_ty { - field_ty @ ast::Type::PathType(_) => { - let field_args = field_ty.generic_arg_list(); - if let (Some(field_args), Some(old_impl_args)) = - (field_args, self_ty.generic_arg_list()) - { - field_args.generic_args().zip(old_impl_args.generic_args()).for_each( - |(field_arg, impl_arg)| { - arg_substs.entry(impl_arg.to_string()).or_insert(field_arg); - }, - ) - } + match field_ty { + field_ty @ ast::Type::PathType(_) => { + let field_args = field_ty.generic_arg_list().map(|gal| gal.generic_args()); + let self_ty_args = self_ty.generic_arg_list().map(|gal| gal.generic_args()); + if let (Some(field_args), Some(self_ty_args)) = (field_args, self_ty_args) { + self_ty_args.zip(field_args).for_each(|(self_ty_arg, field_arg)| { + arg_substs.entry(self_ty_arg.to_string()).or_insert(field_arg); + }) } - _ => {} } - - let args = old_impl_gpl - .to_generic_args() - .generic_args() - .map(|old_arg| { - arg_substs.get(&old_arg.to_string()).map_or_else( - || old_arg.clone(), - |replace_with| { - // The old_arg will be replaced, so it becomes redundant - let old_arg_name = old_arg.to_string(); - if old_trait_args.contains(&old_arg_name) { - // However, we should check type bounds and where clauses on old_arg, - // if it has type bound, we should keep the type bound. - // match trait_params.and_then(|params| params.remove_generic_arg(&old_arg)) { - // Some(ast::GenericParam::TypeParam(ty)) => { - // ty.type_bound_list().and_then(|bounds| ) - // } - // _ => {} - // } - if let Some(params) = trait_params { - params.remove_generic_arg(&old_arg); - } - } - replace_with.clone() - }, - ) - }) - .collect_vec(); - args.is_empty().not().then(|| make::generic_arg_list(args.into_iter())) - } else { - None + _ => {} } + + let args = old_impl_args + .map(|old_arg| { + arg_substs.get(&old_arg.to_string()).map_or_else( + || old_arg.clone(), + |replace_with| { + // The old_arg will be replaced, so it becomes redundant + if trait_params.is_some() && old_trait_args.contains(&old_arg.to_string()) { + trait_params.as_ref().unwrap().remove_generic_arg(&old_arg) + } + replace_with.clone() + }, + ) + }) + .collect_vec(); + args.is_empty().not().then(|| make::generic_arg_list(args.into_iter())) } -fn subst_name_in_strukt( +fn rename_strukt_args( ctx: &AssistContext<'_>, strukt: &ast::Struct, item: &N, - args: GenericArgList, + args: &GenericArgList, ) -> Option where N: ast::AstNode, @@ -611,9 +555,11 @@ where let hir_adt = hir::Adt::from(hir_strukt); let item = item.clone_for_update(); - let item_scope = ctx.sema.scope(item.syntax())?; - let transform = PathTransform::adt_transformation(&item_scope, &item_scope, hir_adt, args); + let scope = ctx.sema.scope(item.syntax())?; + + let transform = PathTransform::adt_transformation(&scope, &scope, hir_adt, args.clone()); transform.apply(&item.syntax()); + Some(item) } @@ -627,16 +573,16 @@ fn has_self_type(trait_: hir::Trait, ctx: &AssistContext<'_>) -> Option<()> { .map(|_| ()) } -fn resolve_conflicts_for_strukt( - strukt: &ast::Struct, - old_impl_params: Option<&ast::GenericParamList>, +fn resolve_name_conflicts( + strukt_params: Option, + old_impl_params: &Option, ) -> Option { - match (strukt.generic_param_list(), old_impl_params) { + match (strukt_params, old_impl_params) { (Some(old_strukt_params), Some(old_impl_params)) => { let params = make::generic_param_list(std::iter::empty()).clone_for_update(); for old_strukt_param in old_strukt_params.generic_params() { - // Get old name from `strukt`` + // Get old name from `strukt` let mut name = SmolStr::from(match &old_strukt_param { ast::GenericParam::ConstParam(c) => c.name()?.to_string(), ast::GenericParam::LifetimeParam(l) => { @@ -807,7 +753,7 @@ fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> Option ast::Path { - make::path_from_text(&format!("{}::{}", qual_path_ty.to_string(), path_expr_seg.to_string())) + make::path_from_text(&format!("{}::{}", qual_path_ty, path_expr_seg)) } #[cfg(test)] diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 5bb200e84a49..50528e1caaac 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -432,7 +432,7 @@ fn get_fn_target( } None => next_space_for_fn_after_call_site(ast::CallableExpr::Call(call))?, }; - Some((target.clone(), file)) + Some((target, file)) } fn get_method_target( diff --git a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index cb8ef395650b..d90d366ffe4c 100644 --- a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -47,7 +47,7 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_> let impl_def = ctx.find_node_at_offset::()?.clone_for_update(); let trait_ = impl_def.trait_()?; - if let ast::Type::PathType(trait_path) = trait_.clone() { + if let ast::Type::PathType(trait_path) = trait_ { let trait_type = ctx.sema.resolve_trait(&trait_path.path()?)?; let scope = ctx.sema.scope(trait_path.syntax())?; if trait_type != FamousDefs(&ctx.sema, scope.krate()).core_convert_Index()? { @@ -105,7 +105,7 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_> "Generate `IndexMut` impl from this `Index` trait", target, |edit| { - edit.insert(target.start(), format!("$0{}\n\n", impl_def.to_string())); + edit.insert(target.start(), format!("$0{}\n\n", impl_def)); }, ) } diff --git a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index 0f67380d12b6..315b6487b514 100644 --- a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -128,7 +128,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ builder.replace_snippet( snippet_cap, impl_name.syntax().text_range(), - format!("${{0:TraitName}}{} for {}", arg_list, impl_name.to_string()), + format!("${{0:TraitName}}{} for {}", arg_list, impl_name), ); // Insert trait before TraitImpl @@ -144,17 +144,13 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ } else { builder.replace( impl_name.syntax().text_range(), - format!("NewTrait{} for {}", arg_list, impl_name.to_string()), + format!("NewTrait{} for {}", arg_list, impl_name), ); // Insert trait before TraitImpl builder.insert( impl_ast.syntax().text_range().start(), - format!( - "{}\n\n{}", - trait_ast.to_string(), - IndentLevel::from_node(impl_ast.syntax()) - ), + format!("{}\n\n{}", trait_ast, IndentLevel::from_node(impl_ast.syntax())), ); } diff --git a/crates/ide-assists/src/handlers/qualify_path.rs b/crates/ide-assists/src/handlers/qualify_path.rs index fde46db3058e..086487184909 100644 --- a/crates/ide-assists/src/handlers/qualify_path.rs +++ b/crates/ide-assists/src/handlers/qualify_path.rs @@ -37,11 +37,9 @@ use crate::{ // ``` pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (import_assets, syntax_under_caret) = find_importable_node(ctx)?; - let mut proposed_imports = import_assets.search_for_relative_paths( - &ctx.sema, - ctx.config.prefer_no_std, - ctx.config.prefer_prelude, - ); + let mut proposed_imports: Vec<_> = import_assets + .search_for_relative_paths(&ctx.sema, ctx.config.prefer_no_std, ctx.config.prefer_prelude) + .collect(); if proposed_imports.is_empty() { return None; } @@ -82,6 +80,7 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option }; // we aren't interested in different namespaces + proposed_imports.sort_by(|a, b| a.import_path.cmp(&b.import_path)); proposed_imports.dedup_by(|a, b| a.import_path == b.import_path); let group_label = group_label(candidate); diff --git a/crates/ide-assists/src/handlers/remove_parentheses.rs b/crates/ide-assists/src/handlers/remove_parentheses.rs index 0281b29cd427..99c55e9ff7c0 100644 --- a/crates/ide-assists/src/handlers/remove_parentheses.rs +++ b/crates/ide-assists/src/handlers/remove_parentheses.rs @@ -43,7 +43,7 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) -> let prev_token = parens.syntax().first_token().and_then(|it| it.prev_token()); let need_to_add_ws = match prev_token { Some(it) => { - let tokens = vec![T![&], T![!], T!['('], T!['['], T!['{']]; + let tokens = [T![&], T![!], T!['('], T!['['], T!['{']]; it.kind() != SyntaxKind::WHITESPACE && !tokens.contains(&it.kind()) } None => false, diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index b54e4204e3f3..788cc846c2a5 100644 --- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -74,7 +74,6 @@ pub(crate) fn replace_derive_with_manual_impl( current_crate, NameToImport::exact_case_sensitive(path.segments().last()?.to_string()), items_locator::AssocSearchMode::Exclude, - Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT.inner()), ) .filter_map(|item| match item.as_module_def()? { ModuleDef::Trait(trait_) => Some(trait_), diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index d74d3b264ae5..446f0be83481 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -263,7 +263,6 @@ fn import_on_the_fly( ctx.config.prefer_no_std, ctx.config.prefer_prelude, ) - .into_iter() .filter(ns_filter) .filter(|import| { let original_item = &import.original_item; @@ -271,8 +270,14 @@ fn import_on_the_fly( && !ctx.is_item_hidden(original_item) && ctx.check_stability(original_item.attrs(ctx.db).as_deref()) }) - .sorted_by_key(|located_import| { - compute_fuzzy_completion_order_key(&located_import.import_path, &user_input_lowercased) + .sorted_by(|a, b| { + let key = |import_path| { + ( + compute_fuzzy_completion_order_key(import_path, &user_input_lowercased), + import_path, + ) + }; + key(&a.import_path).cmp(&key(&b.import_path)) }) .filter_map(|import| { render_resolution_with_import(RenderContext::new(ctx), path_ctx, import) @@ -310,7 +315,6 @@ fn import_on_the_fly_pat_( ctx.config.prefer_no_std, ctx.config.prefer_prelude, ) - .into_iter() .filter(ns_filter) .filter(|import| { let original_item = &import.original_item; @@ -318,8 +322,14 @@ fn import_on_the_fly_pat_( && !ctx.is_item_hidden(original_item) && ctx.check_stability(original_item.attrs(ctx.db).as_deref()) }) - .sorted_by_key(|located_import| { - compute_fuzzy_completion_order_key(&located_import.import_path, &user_input_lowercased) + .sorted_by(|a, b| { + let key = |import_path| { + ( + compute_fuzzy_completion_order_key(import_path, &user_input_lowercased), + import_path, + ) + }; + key(&a.import_path).cmp(&key(&b.import_path)) }) .filter_map(|import| { render_resolution_with_import_pat(RenderContext::new(ctx), pattern_ctx, import) @@ -352,13 +362,18 @@ fn import_on_the_fly_method( ctx.config.prefer_no_std, ctx.config.prefer_prelude, ) - .into_iter() .filter(|import| { !ctx.is_item_hidden(&import.item_to_import) && !ctx.is_item_hidden(&import.original_item) }) - .sorted_by_key(|located_import| { - compute_fuzzy_completion_order_key(&located_import.import_path, &user_input_lowercased) + .sorted_by(|a, b| { + let key = |import_path| { + ( + compute_fuzzy_completion_order_key(import_path, &user_input_lowercased), + import_path, + ) + }; + key(&a.import_path).cmp(&key(&b.import_path)) }) .for_each(|import| match import.original_item { ItemInNs::Values(hir::ModuleDef::Function(f)) => { @@ -407,7 +422,8 @@ fn compute_fuzzy_completion_order_key( ) -> usize { cov_mark::hit!(certain_fuzzy_order_test); let import_name = match proposed_mod_path.segments().last() { - Some(name) => name.to_smol_str().to_lowercase(), + // FIXME: nasty alloc, this is a hot path! + Some(name) => name.to_smol_str().to_ascii_lowercase(), None => return usize::MAX, }; match import_name.match_indices(user_input_lowercased).next() { diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index ff324e7a56d6..6a98e109f6df 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -256,7 +256,6 @@ pub fn resolve_completion_edits( current_crate, NameToImport::exact_case_sensitive(imported_name), items_locator::AssocSearchMode::Include, - Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT.inner()), ); let import = items_with_name .filter_map(|candidate| { diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index c58374f2e833..1af16ef857d0 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -599,6 +599,7 @@ fn main() { expect![[r#" fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED + me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED "#]], ); } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index ded5d4e3db53..8f55f30a2dd4 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -6,18 +6,22 @@ // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). use arrayvec::ArrayVec; +use either::Either; use hir::{ - Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, DocLinkDef, - ExternCrateDecl, Field, Function, GenericParam, HasVisibility, Impl, Label, Local, Macro, - Module, ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, - TypeAlias, Variant, Visibility, + Adt, AsAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType, Const, Crate, + DefWithBody, DeriveHelper, DocLinkDef, ExternCrateDecl, Field, Function, GenericParam, + HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module, ModuleDef, Name, PathResolution, + Semantics, Static, ToolModule, Trait, TraitAlias, TupleField, TypeAlias, Variant, VariantDef, + Visibility, }; -use stdx::impl_from; +use stdx::{format_to, impl_from}; use syntax::{ ast::{self, AstNode}, match_ast, SyntaxKind, SyntaxNode, SyntaxToken, }; +use crate::documentation::{Documentation, HasDocs}; +use crate::famous_defs::FamousDefs; use crate::RootDatabase; // FIXME: a more precise name would probably be `Symbol`? @@ -25,6 +29,7 @@ use crate::RootDatabase; pub enum Definition { Macro(Macro), Field(Field), + TupleField(TupleField), Module(Module), Function(Function), Adt(Adt), @@ -76,13 +81,21 @@ impl Definition { Definition::Label(it) => it.module(db), Definition::ExternCrateDecl(it) => it.module(db), Definition::DeriveHelper(it) => it.derive().module(db), - Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::ToolModule(_) => { - return None - } + Definition::BuiltinAttr(_) + | Definition::BuiltinType(_) + | Definition::TupleField(_) + | Definition::ToolModule(_) => return None, }; Some(module) } + pub fn enclosing_definition(&self, db: &RootDatabase) -> Option { + match self { + Definition::Local(it) => it.parent(db).try_into().ok(), + _ => None, + } + } + pub fn visibility(&self, db: &RootDatabase) -> Option { let vis = match self { Definition::Field(sf) => sf.visibility(db), @@ -96,7 +109,7 @@ impl Definition { Definition::TypeAlias(it) => it.visibility(db), Definition::Variant(it) => it.visibility(db), Definition::ExternCrateDecl(it) => it.visibility(db), - Definition::BuiltinType(_) => Visibility::Public, + Definition::BuiltinType(_) | Definition::TupleField(_) => Visibility::Public, Definition::Macro(_) => return None, Definition::BuiltinAttr(_) | Definition::ToolModule(_) @@ -123,6 +136,7 @@ impl Definition { Definition::TraitAlias(it) => it.name(db), Definition::TypeAlias(it) => it.name(db), Definition::BuiltinType(it) => it.name(), + Definition::TupleField(it) => it.name(), Definition::SelfType(_) => return None, Definition::Local(it) => it.name(db), Definition::GenericParam(it) => it.name(db), @@ -134,6 +148,127 @@ impl Definition { }; Some(name) } + + pub fn docs( + &self, + db: &RootDatabase, + famous_defs: Option<&FamousDefs<'_, '_>>, + ) -> Option { + let docs = match self { + Definition::Macro(it) => it.docs(db), + Definition::Field(it) => it.docs(db), + Definition::Module(it) => it.docs(db), + Definition::Function(it) => it.docs(db), + Definition::Adt(it) => it.docs(db), + Definition::Variant(it) => it.docs(db), + Definition::Const(it) => it.docs(db), + Definition::Static(it) => it.docs(db), + Definition::Trait(it) => it.docs(db), + Definition::TraitAlias(it) => it.docs(db), + Definition::TypeAlias(it) => it.docs(db), + Definition::BuiltinType(it) => { + famous_defs.and_then(|fd| { + // std exposes prim_{} modules with docstrings on the root to document the builtins + let primitive_mod = format!("prim_{}", it.name().display(fd.0.db)); + let doc_owner = find_std_module(fd, &primitive_mod)?; + doc_owner.docs(fd.0.db) + }) + } + Definition::Local(_) => None, + Definition::SelfType(impl_def) => { + impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))? + } + Definition::GenericParam(_) => None, + Definition::Label(_) => None, + Definition::ExternCrateDecl(it) => it.docs(db), + + Definition::BuiltinAttr(it) => { + let name = it.name(db); + let AttributeTemplate { word, list, name_value_str } = it.template(db)?; + let mut docs = "Valid forms are:".to_owned(); + if word { + format_to!(docs, "\n - #\\[{}]", name); + } + if let Some(list) = list { + format_to!(docs, "\n - #\\[{}({})]", name, list); + } + if let Some(name_value_str) = name_value_str { + format_to!(docs, "\n - #\\[{} = {}]", name, name_value_str); + } + Some(Documentation::new(docs.replace('*', "\\*"))) + } + Definition::ToolModule(_) => None, + Definition::DeriveHelper(_) => None, + Definition::TupleField(_) => None, + }; + + docs.or_else(|| { + // docs are missing, for assoc items of trait impls try to fall back to the docs of the + // original item of the trait + let assoc = self.as_assoc_item(db)?; + let trait_ = assoc.containing_trait_impl(db)?; + let name = Some(assoc.name(db)?); + let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?; + item.docs(db) + }) + } + + pub fn label(&self, db: &RootDatabase) -> Option { + let label = match *self { + Definition::Macro(it) => it.display(db).to_string(), + Definition::Field(it) => it.display(db).to_string(), + Definition::TupleField(it) => it.display(db).to_string(), + Definition::Module(it) => it.display(db).to_string(), + Definition::Function(it) => it.display(db).to_string(), + Definition::Adt(it) => it.display(db).to_string(), + Definition::Variant(it) => it.display(db).to_string(), + Definition::Const(it) => it.display(db).to_string(), + Definition::Static(it) => it.display(db).to_string(), + Definition::Trait(it) => it.display(db).to_string(), + Definition::TraitAlias(it) => it.display(db).to_string(), + Definition::TypeAlias(it) => it.display(db).to_string(), + Definition::BuiltinType(it) => it.name().display(db).to_string(), + Definition::Local(it) => { + let ty = it.ty(db); + let ty = ty.display_truncated(db, None); + let is_mut = if it.is_mut(db) { "mut " } else { "" }; + let desc = match it.primary_source(db).into_ident_pat() { + Some(ident) => { + let name = it.name(db); + let let_kw = if ident.syntax().parent().map_or(false, |p| { + p.kind() == SyntaxKind::LET_STMT || p.kind() == SyntaxKind::LET_EXPR + }) { + "let " + } else { + "" + }; + format!("{let_kw}{is_mut}{}: {ty}", name.display(db)) + } + None => format!("{is_mut}self: {ty}"), + }; + desc + } + Definition::SelfType(impl_def) => { + impl_def.self_ty(db).as_adt().and_then(|adt| Definition::Adt(adt).label(db))? + } + Definition::GenericParam(it) => it.display(db).to_string(), + Definition::Label(it) => it.name(db).display(db).to_string(), + Definition::ExternCrateDecl(it) => it.display(db).to_string(), + Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db)), + Definition::ToolModule(it) => it.name(db).to_string(), + Definition::DeriveHelper(it) => format!("derive_helper {}", it.name(db).display(db)), + }; + Some(label) + } +} + +fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option { + let db = famous_defs.0.db; + let std_crate = famous_defs.std()?; + let std_root_module = std_crate.root_module(); + std_root_module.children(db).find(|module| { + module.name(db).map_or(false, |module| module.display(db).to_string() == name) + }) } // FIXME: IdentClass as a name no longer fits @@ -502,9 +637,11 @@ impl NameRefClass { ast::FieldExpr(field_expr) => { sema.resolve_field_fallback(&field_expr) .map(|it| { - it.map_left(Definition::Field) - .map_right(Definition::Function) - .either(NameRefClass::Definition, NameRefClass::Definition) + NameRefClass::Definition(match it { + Either::Left(Either::Left(field)) => Definition::Field(field), + Either::Left(Either::Right(field)) => Definition::TupleField(field), + Either::Right(fun) => Definition::Function(fun), + }) }) }, ast::RecordPatField(record_pat_field) => { @@ -662,3 +799,22 @@ impl From for Definition { } } } + +impl From for Definition { + fn from(def: VariantDef) -> Self { + ModuleDef::from(def).into() + } +} + +impl TryFrom for Definition { + type Error = (); + fn try_from(def: DefWithBody) -> Result { + match def { + DefWithBody::Function(it) => Ok(it.into()), + DefWithBody::Static(it) => Ok(it.into()), + DefWithBody::Const(it) => Ok(it.into()), + DefWithBody::Variant(it) => Ok(it.into()), + DefWithBody::InTypeConst(_) => Err(()), + } + } +} diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index a4f0a6df7813..652968d808fa 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -207,7 +207,7 @@ impl ImportAssets { prefix_kind: PrefixKind, prefer_no_std: bool, prefer_prelude: bool, - ) -> Vec { + ) -> impl Iterator { let _p = profile::span("import_assets::search_for_imports"); self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude) } @@ -218,7 +218,7 @@ impl ImportAssets { sema: &Semantics<'_, RootDatabase>, prefer_no_std: bool, prefer_prelude: bool, - ) -> Vec { + ) -> impl Iterator { let _p = profile::span("import_assets::search_for_relative_paths"); self.search_for(sema, None, prefer_no_std, prefer_prelude) } @@ -259,9 +259,15 @@ impl ImportAssets { prefixed: Option, prefer_no_std: bool, prefer_prelude: bool, - ) -> Vec { + ) -> impl Iterator { let _p = profile::span("import_assets::search_for"); + let scope = match sema.scope(&self.candidate_node) { + Some(it) => it, + None => return >::default().into_iter(), + }; + + let krate = self.module_with_candidate.krate(); let scope_definitions = self.scope_definitions(sema); let mod_path = |item| { get_mod_path( @@ -272,30 +278,30 @@ impl ImportAssets { prefer_no_std, prefer_prelude, ) - }; - - let krate = self.module_with_candidate.krate(); - let scope = match sema.scope(&self.candidate_node) { - Some(it) => it, - None => return Vec::new(), + .filter(|path| path.len() > 1) }; match &self.import_candidate { ImportCandidate::Path(path_candidate) => { - path_applicable_imports(sema, krate, path_candidate, mod_path) - } - ImportCandidate::TraitAssocItem(trait_candidate) => { - trait_applicable_items(sema, krate, &scope, trait_candidate, true, mod_path) - } - ImportCandidate::TraitMethod(trait_candidate) => { - trait_applicable_items(sema, krate, &scope, trait_candidate, false, mod_path) + path_applicable_imports(sema, krate, path_candidate, mod_path, |item_to_import| { + !scope_definitions.contains(&ScopeDef::from(item_to_import)) + }) } + ImportCandidate::TraitAssocItem(trait_candidate) + | ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( + sema, + krate, + &scope, + trait_candidate, + matches!(self.import_candidate, ImportCandidate::TraitAssocItem(_)), + mod_path, + |trait_to_import| { + !scope_definitions + .contains(&ScopeDef::ModuleDef(ModuleDef::Trait(trait_to_import))) + }, + ), } .into_iter() - .filter(|import| import.import_path.len() > 1) - .filter(|import| !scope_definitions.contains(&ScopeDef::from(import.item_to_import))) - .sorted_by(|a, b| a.import_path.cmp(&b.import_path)) - .collect() } fn scope_definitions(&self, sema: &Semantics<'_, RootDatabase>) -> FxHashSet { @@ -315,6 +321,7 @@ fn path_applicable_imports( current_crate: Crate, path_candidate: &PathImportCandidate, mod_path: impl Fn(ItemInNs) -> Option + Copy, + scope_filter: impl Fn(ItemInNs) -> bool + Copy, ) -> FxHashSet { let _p = profile::span("import_assets::path_applicable_imports"); @@ -333,12 +340,15 @@ fn path_applicable_imports( // // see also an ignored test under FIXME comment in the qualify_path.rs module AssocSearchMode::Exclude, - Some(DEFAULT_QUERY_SEARCH_LIMIT.inner()), ) .filter_map(|item| { + if !scope_filter(item) { + return None; + } let mod_path = mod_path(item)?; Some(LocatedImport::new(mod_path, item, item)) }) + .take(DEFAULT_QUERY_SEARCH_LIMIT.inner()) .collect() } Some(qualifier) => items_locator::items_with_name( @@ -346,9 +356,9 @@ fn path_applicable_imports( current_crate, path_candidate.name.clone(), AssocSearchMode::Include, - Some(DEFAULT_QUERY_SEARCH_LIMIT.inner()), ) - .filter_map(|item| import_for_item(sema.db, mod_path, &qualifier, item)) + .filter_map(|item| import_for_item(sema.db, mod_path, &qualifier, item, scope_filter)) + .take(DEFAULT_QUERY_SEARCH_LIMIT.inner()) .collect(), } } @@ -358,6 +368,7 @@ fn import_for_item( mod_path: impl Fn(ItemInNs) -> Option, unresolved_qualifier: &[SmolStr], original_item: ItemInNs, + scope_filter: impl Fn(ItemInNs) -> bool, ) -> Option { let _p = profile::span("import_assets::import_for_item"); let [first_segment, ..] = unresolved_qualifier else { return None }; @@ -413,15 +424,16 @@ fn import_for_item( // especially in case of lazy completion edit resolutions. return None; } - (false, Some(trait_to_import)) => { + (false, Some(trait_to_import)) if scope_filter(trait_to_import) => { LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, original_item) } - (true, None) => { + (true, None) if scope_filter(original_item_candidate) => { LocatedImport::new(import_path_candidate, original_item_candidate, original_item) } - (false, None) => { + (false, None) if scope_filter(segment_import) => { LocatedImport::new(mod_path(segment_import)?, segment_import, original_item) } + _ => return None, }) } @@ -490,6 +502,7 @@ fn trait_applicable_items( trait_candidate: &TraitImportCandidate, trait_assoc_item: bool, mod_path: impl Fn(ItemInNs) -> Option, + scope_filter: impl Fn(hir::Trait) -> bool, ) -> FxHashSet { let _p = profile::span("import_assets::trait_applicable_items"); @@ -500,22 +513,24 @@ fn trait_applicable_items( let related_traits = inherent_traits.chain(env_traits).collect::>(); let mut required_assoc_items = FxHashSet::default(); - let trait_candidates = items_locator::items_with_name( + let trait_candidates: FxHashSet<_> = items_locator::items_with_name( sema, current_crate, trait_candidate.assoc_item_name.clone(), AssocSearchMode::AssocItemsOnly, - Some(DEFAULT_QUERY_SEARCH_LIMIT.inner()), ) .filter_map(|input| item_as_assoc(db, input)) .filter_map(|assoc| { + if !trait_assoc_item && matches!(assoc, AssocItem::Const(_) | AssocItem::TypeAlias(_)) { + return None; + } + let assoc_item_trait = assoc.containing_trait(db)?; if related_traits.contains(&assoc_item_trait) { - None - } else { - required_assoc_items.insert(assoc); - Some(assoc_item_trait.into()) + return None; } + required_assoc_items.insert(assoc); + Some(assoc_item_trait.into()) }) .collect(); @@ -531,12 +546,8 @@ fn trait_applicable_items( None, |assoc| { if required_assoc_items.contains(&assoc) { - if let AssocItem::Function(f) = assoc { - if f.self_param(db).is_some() { - return None; - } - } - let located_trait = assoc.containing_trait(db)?; + let located_trait = + assoc.containing_trait(db).filter(|&it| scope_filter(it))?; let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let import_path = trait_import_paths .entry(trait_item) @@ -561,7 +572,8 @@ fn trait_applicable_items( |function| { let assoc = function.as_assoc_item(db)?; if required_assoc_items.contains(&assoc) { - let located_trait = assoc.containing_trait(db)?; + let located_trait = + assoc.containing_trait(db).filter(|&it| scope_filter(it))?; let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let import_path = trait_import_paths .entry(trait_item) diff --git a/crates/ide-db/src/items_locator.rs b/crates/ide-db/src/items_locator.rs index 4a5d234f73d2..432f1d745d20 100644 --- a/crates/ide-db/src/items_locator.rs +++ b/crates/ide-db/src/items_locator.rs @@ -19,26 +19,24 @@ pub fn items_with_name<'a>( krate: Crate, name: NameToImport, assoc_item_search: AssocSearchMode, - limit: Option, ) -> impl Iterator + 'a { let _p = profile::span("items_with_name").detail(|| { format!( - "Name: {}, crate: {:?}, assoc items: {:?}, limit: {:?}", + "Name: {}, crate: {:?}, assoc items: {:?}", name.text(), assoc_item_search, krate.display_name(sema.db).map(|name| name.to_string()), - limit, ) }); let prefix = matches!(name, NameToImport::Prefix(..)); - let (mut local_query, mut external_query) = match name { + let (local_query, external_query) = match name { NameToImport::Prefix(exact_name, case_sensitive) | NameToImport::Exact(exact_name, case_sensitive) => { let mut local_query = symbol_index::Query::new(exact_name.clone()); + local_query.assoc_search_mode(assoc_item_search); let mut external_query = - // import_map::Query::new(exact_name).assoc_search_mode(assoc_item_search); - import_map::Query::new(exact_name); + import_map::Query::new(exact_name).assoc_search_mode(assoc_item_search); if prefix { local_query.prefix(); external_query = external_query.prefix(); @@ -55,8 +53,9 @@ pub fn items_with_name<'a>( NameToImport::Fuzzy(fuzzy_search_string, case_sensitive) => { let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone()); local_query.fuzzy(); + local_query.assoc_search_mode(assoc_item_search); - let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) + let mut external_query = import_map::Query::new(fuzzy_search_string) .fuzzy() .assoc_search_mode(assoc_item_search); @@ -69,18 +68,12 @@ pub fn items_with_name<'a>( } }; - if let Some(limit) = limit { - external_query = external_query.limit(limit); - local_query.limit(limit); - } - - find_items(sema, krate, assoc_item_search, local_query, external_query) + find_items(sema, krate, local_query, external_query) } fn find_items<'a>( sema: &'a Semantics<'_, RootDatabase>, krate: Crate, - assoc_item_search: AssocSearchMode, local_query: symbol_index::Query, external_query: import_map::Query, ) -> impl Iterator + 'a { @@ -98,18 +91,12 @@ fn find_items<'a>( }); // Query the local crate using the symbol index. - let local_results = local_query - .search(&symbol_index::crate_symbols(db, krate)) - .into_iter() - .filter(move |candidate| match assoc_item_search { - AssocSearchMode::Include => true, - AssocSearchMode::Exclude => !candidate.is_assoc, - AssocSearchMode::AssocItemsOnly => candidate.is_assoc, - }) - .map(|local_candidate| match local_candidate.def { + let mut local_results = Vec::new(); + local_query.search(&symbol_index::crate_symbols(db, krate), |local_candidate| { + local_results.push(match local_candidate.def { hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def), def => ItemInNs::from(def), - }); - - external_importables.chain(local_results) + }) + }); + local_results.into_iter().chain(external_importables) } diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 8c1a6e6e40b8..edfeddc1bc9c 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -159,7 +159,7 @@ impl<'a> PathTransform<'a> { .for_each(|(k, v)| match (k.split(db), v) { (Either::Right(k), Some(TypeOrConst::Either(v))) => { if let Some(ty) = v.ty() { - type_substs.insert(k, ty.clone()); + type_substs.insert(k, ty); } } (Either::Right(k), None) => { diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs index 7f28965885ad..f694f7160dea 100644 --- a/crates/ide-db/src/rename.rs +++ b/crates/ide-db/src/rename.rs @@ -198,6 +198,7 @@ impl Definition { Definition::SelfType(_) => return None, Definition::BuiltinAttr(_) => return None, Definition::ToolModule(_) => return None, + Definition::TupleField(_) => return None, // FIXME: This should be doable in theory Definition::DeriveHelper(_) => return None, }; diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index dbef36026822..a40dd2692cfd 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -539,7 +539,7 @@ impl<'a> FindUsages<'a> { tree.token_at_offset(offset).into_iter().for_each(|token| { let Some(str_token) = ast::String::cast(token.clone()) else { return }; if let Some((range, nameres)) = - sema.check_for_format_args_template(token.clone(), offset) + sema.check_for_format_args_template(token, offset) { if self.found_format_args_ref(file_id, range, str_token, nameres, sink) { return; diff --git a/crates/ide-db/src/source_change.rs b/crates/ide-db/src/source_change.rs index c7188f1f7943..73be6a4071e4 100644 --- a/crates/ide-db/src/source_change.rs +++ b/crates/ide-db/src/source_change.rs @@ -341,13 +341,13 @@ impl SourceChangeBuilder { /// Adds a tabstop snippet to place the cursor before `token` pub fn add_tabstop_before_token(&mut self, _cap: SnippetCap, token: SyntaxToken) { assert!(token.parent().is_some()); - self.add_snippet(PlaceSnippet::Before(token.clone().into())); + self.add_snippet(PlaceSnippet::Before(token.into())); } /// Adds a tabstop snippet to place the cursor after `token` pub fn add_tabstop_after_token(&mut self, _cap: SnippetCap, token: SyntaxToken) { assert!(token.parent().is_some()); - self.add_snippet(PlaceSnippet::After(token.clone().into())); + self.add_snippet(PlaceSnippet::After(token.into())); } /// Adds a snippet to move the cursor selected over `node` diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index f5f0f0576f22..c2e95ca860ca 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -31,9 +31,10 @@ use base_db::{ salsa::{self, ParallelDatabase}, SourceDatabaseExt, SourceRootId, Upcast, }; -use fst::{self, Streamer}; +use fst::{self, raw::IndexedValue, Automaton, Streamer}; use hir::{ db::HirDatabase, + import_map::{AssocSearchMode, SearchMode}, symbols::{FileSymbol, SymbolCollector}, Crate, Module, }; @@ -43,22 +44,15 @@ use triomphe::Arc; use crate::RootDatabase; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum SearchMode { - Fuzzy, - Exact, - Prefix, -} - #[derive(Debug, Clone)] pub struct Query { query: String, lowercased: String, + mode: SearchMode, + assoc_mode: AssocSearchMode, + case_sensitive: bool, only_types: bool, libs: bool, - mode: SearchMode, - case_sensitive: bool, - limit: usize, } impl Query { @@ -70,8 +64,8 @@ impl Query { only_types: false, libs: false, mode: SearchMode::Fuzzy, + assoc_mode: AssocSearchMode::Include, case_sensitive: false, - limit: usize::max_value(), } } @@ -95,12 +89,13 @@ impl Query { self.mode = SearchMode::Prefix; } - pub fn case_sensitive(&mut self) { - self.case_sensitive = true; + /// Specifies whether we want to include associated items in the result. + pub fn assoc_search_mode(&mut self, assoc_mode: AssocSearchMode) { + self.assoc_mode = assoc_mode; } - pub fn limit(&mut self, limit: usize) { - self.limit = limit + pub fn case_sensitive(&mut self) { + self.case_sensitive = true; } } @@ -225,7 +220,9 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { indices.iter().flat_map(|indices| indices.iter().cloned()).collect() }; - query.search(&indices) + let mut res = vec![]; + query.search(&indices, |f| res.push(f.clone())); + res } #[derive(Default)] @@ -285,6 +282,7 @@ impl SymbolIndex { builder.insert(key, value).unwrap(); } + // FIXME: fst::Map should ideally have a way to shrink the backing buffer without the unwrap dance let map = fst::Map::new({ let mut buf = builder.into_inner().unwrap(); buf.shrink_to_fit(); @@ -317,22 +315,54 @@ impl SymbolIndex { } impl Query { - pub(crate) fn search(self, indices: &[Arc]) -> Vec { + pub(crate) fn search<'sym>( + self, + indices: &'sym [Arc], + cb: impl FnMut(&'sym FileSymbol), + ) { let _p = profile::span("symbol_index::Query::search"); let mut op = fst::map::OpBuilder::new(); - for file_symbols in indices.iter() { - let automaton = fst::automaton::Subsequence::new(&self.lowercased); - op = op.add(file_symbols.map.search(automaton)) + match self.mode { + SearchMode::Exact => { + let automaton = fst::automaton::Str::new(&self.lowercased); + + for index in indices.iter() { + op = op.add(index.map.search(&automaton)); + } + self.search_maps(&indices, op.union(), cb) + } + SearchMode::Fuzzy => { + let automaton = fst::automaton::Subsequence::new(&self.lowercased); + + for index in indices.iter() { + op = op.add(index.map.search(&automaton)); + } + self.search_maps(&indices, op.union(), cb) + } + SearchMode::Prefix => { + let automaton = fst::automaton::Str::new(&self.lowercased).starts_with(); + + for index in indices.iter() { + op = op.add(index.map.search(&automaton)); + } + self.search_maps(&indices, op.union(), cb) + } } - let mut stream = op.union(); - let mut res = Vec::new(); + } + + fn search_maps<'sym>( + &self, + indices: &'sym [Arc], + mut stream: fst::map::Union<'_>, + mut cb: impl FnMut(&'sym FileSymbol), + ) { while let Some((_, indexed_values)) = stream.next() { - for indexed_value in indexed_values { - let symbol_index = &indices[indexed_value.index]; - let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); + for &IndexedValue { index, value } in indexed_values { + let symbol_index = &indices[index]; + let (start, end) = SymbolIndex::map_value_to_range(value); for symbol in &symbol_index.symbols[start..end] { - if self.only_types + let non_type_for_type_only_query = self.only_types && !matches!( symbol.def, hir::ModuleDef::Adt(..) @@ -340,38 +370,23 @@ impl Query { | hir::ModuleDef::BuiltinType(..) | hir::ModuleDef::TraitAlias(..) | hir::ModuleDef::Trait(..) - ) - { + ); + if non_type_for_type_only_query || !self.matches_assoc_mode(symbol.is_assoc) { continue; } - let skip = match self.mode { - SearchMode::Fuzzy => { - self.case_sensitive - && self.query.chars().any(|c| !symbol.name.contains(c)) - } - SearchMode::Exact => symbol.name != self.query, - SearchMode::Prefix if self.case_sensitive => { - !symbol.name.starts_with(&self.query) - } - SearchMode::Prefix => symbol - .name - .chars() - .zip(self.lowercased.chars()) - .all(|(n, q)| n.to_lowercase().next() == Some(q)), - }; - - if skip { - continue; - } - - res.push(symbol.clone()); - if res.len() >= self.limit { - return res; + if self.mode.check(&self.query, self.case_sensitive, &symbol.name) { + cb(symbol); } } } } - res + } + + fn matches_assoc_mode(&self, is_trait_assoc_item: bool) -> bool { + match (is_trait_assoc_item, self.assoc_mode) { + (true, AssocSearchMode::Exclude) | (false, AssocSearchMode::AssocItemsOnly) => false, + _ => true, + } } } diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs index c202264bb566..6ecfd55ea024 100644 --- a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs +++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs @@ -1,5 +1,10 @@ -use hir::{Const, Function, HasSource, TypeAlias}; -use ide_db::base_db::FileRange; +use hir::{db::ExpandDatabase, Const, Function, HasSource, HirDisplay, TypeAlias}; +use ide_db::{ + assists::{Assist, AssistId, AssistKind}, + label::Label, + source_change::SourceChangeBuilder, +}; +use text_edit::TextRange; use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; @@ -10,47 +15,195 @@ pub(crate) fn trait_impl_redundant_assoc_item( ctx: &DiagnosticsContext<'_>, d: &hir::TraitImplRedundantAssocItems, ) -> Diagnostic { - let name = d.assoc_item.0.clone(); - let assoc_item = d.assoc_item.1; let db = ctx.sema.db; + let name = d.assoc_item.0.clone(); + let redundant_assoc_item_name = name.display(db); + let assoc_item = d.assoc_item.1; let default_range = d.impl_.syntax_node_ptr().text_range(); let trait_name = d.trait_.name(db).to_smol_str(); - let (redundant_item_name, diagnostic_range) = match assoc_item { - hir::AssocItem::Function(id) => ( - format!("`fn {}`", name.display(db)), - Function::from(id) - .source(db) - .map(|it| it.syntax().value.text_range()) - .unwrap_or(default_range), - ), - hir::AssocItem::Const(id) => ( - format!("`const {}`", name.display(db)), - Const::from(id) - .source(db) - .map(|it| it.syntax().value.text_range()) - .unwrap_or(default_range), - ), - hir::AssocItem::TypeAlias(id) => ( - format!("`type {}`", name.display(db)), - TypeAlias::from(id) - .source(db) - .map(|it| it.syntax().value.text_range()) - .unwrap_or(default_range), - ), + let (redundant_item_name, diagnostic_range, redundant_item_def) = match assoc_item { + hir::AssocItem::Function(id) => { + let function = Function::from(id); + ( + format!("`fn {}`", redundant_assoc_item_name), + function + .source(db) + .map(|it| it.syntax().value.text_range()) + .unwrap_or(default_range), + format!("\n {};", function.display(db)), + ) + } + hir::AssocItem::Const(id) => { + let constant = Const::from(id); + ( + format!("`const {}`", redundant_assoc_item_name), + constant + .source(db) + .map(|it| it.syntax().value.text_range()) + .unwrap_or(default_range), + format!("\n {};", constant.display(db)), + ) + } + hir::AssocItem::TypeAlias(id) => { + let type_alias = TypeAlias::from(id); + ( + format!("`type {}`", redundant_assoc_item_name), + type_alias + .source(db) + .map(|it| it.syntax().value.text_range()) + .unwrap_or(default_range), + format!("\n type {};", type_alias.name(ctx.sema.db).to_smol_str()), + ) + } }; Diagnostic::new( DiagnosticCode::RustcHardError("E0407"), format!("{redundant_item_name} is not a member of trait `{trait_name}`"), - FileRange { file_id: d.file_id.file_id().unwrap(), range: diagnostic_range }, + hir::InFile::new(d.file_id, diagnostic_range).original_node_file_range_rooted(db), ) + .with_fixes(quickfix_for_redundant_assoc_item( + ctx, + d, + redundant_item_def, + diagnostic_range, + )) +} + +/// add assoc item into the trait def body +fn quickfix_for_redundant_assoc_item( + ctx: &DiagnosticsContext<'_>, + d: &hir::TraitImplRedundantAssocItems, + redundant_item_def: String, + range: TextRange, +) -> Option> { + let add_assoc_item_def = |builder: &mut SourceChangeBuilder| -> Option<()> { + let db = ctx.sema.db; + let root = db.parse_or_expand(d.file_id); + // don't modify trait def in outer crate + let current_crate = ctx.sema.scope(&d.impl_.syntax_node_ptr().to_node(&root))?.krate(); + let trait_def_crate = d.trait_.module(db).krate(); + if trait_def_crate != current_crate { + return None; + } + + let trait_def = d.trait_.source(db)?.value; + let l_curly = trait_def.assoc_item_list()?.l_curly_token()?.text_range(); + let where_to_insert = + hir::InFile::new(d.file_id, l_curly).original_node_file_range_rooted(db).range; + + Some(builder.insert(where_to_insert.end(), redundant_item_def)) + }; + let file_id = d.file_id.file_id()?; + let mut source_change_builder = SourceChangeBuilder::new(file_id); + add_assoc_item_def(&mut source_change_builder)?; + + Some(vec![Assist { + id: AssistId("add assoc item def into trait def", AssistKind::QuickFix), + label: Label::new("Add assoc item def into trait def".to_string()), + group: None, + target: range, + source_change: Some(source_change_builder.finish()), + trigger_signature_help: false, + }]) } #[cfg(test)] mod tests { - use crate::tests::check_diagnostics; + use crate::tests::{check_diagnostics, check_fix, check_no_fix}; + + #[test] + fn quickfix_for_assoc_func() { + check_fix( + r#" +trait Marker { + fn boo(); +} +struct Foo; +impl Marker for Foo { + fn$0 bar(_a: i32, _b: String) -> String {} + fn boo() {} +} + "#, + r#" +trait Marker { + fn bar(_a: i32, _b: String) -> String; + fn boo(); +} +struct Foo; +impl Marker for Foo { + fn bar(_a: i32, _b: String) -> String {} + fn boo() {} +} + "#, + ) + } + + #[test] + fn quickfix_for_assoc_const() { + check_fix( + r#" +trait Marker { + fn foo () {} +} +struct Foo; +impl Marker for Foo { + const FLAG: bool$0 = false; +} + "#, + r#" +trait Marker { + const FLAG: bool; + fn foo () {} +} +struct Foo; +impl Marker for Foo { + const FLAG: bool = false; +} + "#, + ) + } + + #[test] + fn quickfix_for_assoc_type() { + check_fix( + r#" +trait Marker { +} +struct Foo; +impl Marker for Foo { + type T = i32;$0 +} + "#, + r#" +trait Marker { + type T; +} +struct Foo; +impl Marker for Foo { + type T = i32; +} + "#, + ) + } + + #[test] + fn quickfix_dont_work() { + check_no_fix( + r#" + //- /dep.rs crate:dep + trait Marker { + } + //- /main.rs crate:main deps:dep + struct Foo; + impl dep::Marker for Foo { + type T = i32;$0 + } + "#, + ) + } #[test] fn trait_with_default_value() { @@ -64,12 +217,12 @@ trait Marker { struct Foo; impl Marker for Foo { type T = i32; - //^^^^^^^^^^^^^ error: `type T` is not a member of trait `Marker` + //^^^^^^^^^^^^^ 💡 error: `type T` is not a member of trait `Marker` const FLAG: bool = true; fn bar() {} - //^^^^^^^^^^^ error: `fn bar` is not a member of trait `Marker` + //^^^^^^^^^^^ 💡 error: `fn bar` is not a member of trait `Marker` fn boo() {} } diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 60a45a05a4a1..41fb67290852 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -160,7 +160,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) - // if receiver should be pass as first arg in the assoc func, // we could omit generic parameters cause compiler can deduce it automatically if !need_to_take_receiver_as_first_arg && !generic_parameters.is_empty() { - let generic_parameters = generic_parameters.join(", ").to_string(); + let generic_parameters = generic_parameters.join(", "); receiver_type_adt_name = format!("{}::<{}>", receiver_type_adt_name, generic_parameters); } diff --git a/crates/ide-diagnostics/src/handlers/unresolved_module.rs b/crates/ide-diagnostics/src/handlers/unresolved_module.rs index e90d385bab8c..4d7d425bab34 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_module.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_module.rs @@ -58,9 +58,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedModule) -> Option Option { let mod_path = definition_mod_path(db, &def); - let (label, docs) = match def { - Definition::Macro(it) => label_and_docs(db, it), - Definition::Field(it) => label_and_layout_info_and_docs( - db, - it, - config, - |&it| it.layout(db), - |_| { - let var_def = it.parent_def(db); - match var_def { - hir::VariantDef::Struct(s) => { - Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(it)) + let label = def.label(db)?; + let docs = def.docs(db, famous_defs); + + let value = match def { + Definition::Variant(it) => { + if !it.parent_enum(db).is_data_carrying(db) { + match it.eval(db) { + Ok(it) => { + Some(if it >= 10 { format!("{it} ({it:#X})") } else { format!("{it}") }) } - _ => None, + Err(_) => it.value(db).map(|it| format!("{it:?}")), } - }, - ), - Definition::Module(it) => label_and_docs(db, it), - Definition::Function(it) => label_and_docs(db, it), - Definition::Adt(it) => { - label_and_layout_info_and_docs(db, it, config, |&it| it.layout(db), |_| None) + } else { + None + } } - Definition::Variant(it) => label_value_and_layout_info_and_docs( - db, - it, - config, - |&it| { - if !it.parent_enum(db).is_data_carrying(db) { - match it.eval(db) { - Ok(it) => { - Some(if it >= 10 { format!("{it} ({it:#X})") } else { format!("{it}") }) - } - Err(_) => it.value(db).map(|it| format!("{it:?}")), - } - } else { - None - } - }, - |it| it.layout(db), - |layout| layout.enum_tag_size(), - ), - Definition::Const(it) => label_value_and_docs(db, it, |it| { + Definition::Const(it) => { let body = it.render_eval(db); match body { Ok(it) => Some(it), @@ -447,53 +417,59 @@ pub(super) fn definition( Some(body.to_string()) } } - }), - Definition::Static(it) => label_value_and_docs(db, it, |it| { + } + Definition::Static(it) => { let source = it.source(db)?; let mut body = source.value.body()?.syntax().clone(); if source.file_id.is_macro() { body = insert_whitespace_into_node::insert_ws_into(body); } Some(body.to_string()) - }), - Definition::Trait(it) => label_and_docs(db, it), - Definition::TraitAlias(it) => label_and_docs(db, it), - Definition::TypeAlias(it) => { - label_and_layout_info_and_docs(db, it, config, |&it| it.ty(db).layout(db), |_| None) - } - Definition::BuiltinType(it) => { - return famous_defs - .and_then(|fd| builtin(fd, it)) - .or_else(|| Some(Markup::fenced_block(&it.name().display(db)))) - } - Definition::Local(it) => return local(db, it, config), - Definition::SelfType(impl_def) => { - impl_def.self_ty(db).as_adt().map(|adt| label_and_docs(db, adt))? - } - Definition::GenericParam(it) => (it.display(db).to_string(), None), - Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db).display(db))), - Definition::ExternCrateDecl(it) => label_and_docs(db, it), - // FIXME: We should be able to show more info about these - Definition::BuiltinAttr(it) => return render_builtin_attr(db, it), - Definition::ToolModule(it) => return Some(Markup::fenced_block(&it.name(db))), - Definition::DeriveHelper(it) => { - (format!("derive_helper {}", it.name(db).display(db)), None) } + _ => None, }; - let docs = docs - .filter(|_| config.documentation) - .or_else(|| { - // docs are missing, for assoc items of trait impls try to fall back to the docs of the - // original item of the trait - let assoc = def.as_assoc_item(db)?; - let trait_ = assoc.containing_trait_impl(db)?; - let name = Some(assoc.name(db)?); - let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?; - item.docs(db) - }) - .map(Into::into); - markup(docs, label, mod_path) + let layout_info = match def { + Definition::Field(it) => render_memory_layout( + config.memory_layout, + || it.layout(db), + |_| { + let var_def = it.parent_def(db); + match var_def { + hir::VariantDef::Struct(s) => { + Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(it)) + } + _ => None, + } + }, + |_| None, + ), + Definition::Adt(it) => { + render_memory_layout(config.memory_layout, || it.layout(db), |_| None, |_| None) + } + Definition::Variant(it) => render_memory_layout( + config.memory_layout, + || it.layout(db), + |_| None, + |layout| layout.enum_tag_size(), + ), + Definition::TypeAlias(it) => { + render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None) + } + Definition::Local(it) => { + render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None) + } + _ => None, + }; + + let label = match (value, layout_info) { + (Some(value), Some(layout_info)) => format!("{label} = {value}{layout_info}"), + (Some(value), None) => format!("{label} = {value}"), + (None, Some(layout_info)) => format!("{label}{layout_info}"), + (None, None) => label, + }; + + markup(docs.map(Into::into), label, mod_path) } fn type_info( @@ -595,114 +571,16 @@ fn closure_ty( Some(res) } -fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option { - let name = attr.name(db); - let desc = format!("#[{name}]"); - - let AttributeTemplate { word, list, name_value_str } = match attr.template(db) { - Some(template) => template, - None => return Some(Markup::fenced_block(&attr.name(db))), - }; - let mut docs = "Valid forms are:".to_owned(); - if word { - format_to!(docs, "\n - #\\[{}]", name); - } - if let Some(list) = list { - format_to!(docs, "\n - #\\[{}({})]", name, list); - } - if let Some(name_value_str) = name_value_str { - format_to!(docs, "\n - #\\[{} = {}]", name, name_value_str); - } - markup(Some(docs.replace('*', "\\*")), desc, None) -} - -fn label_and_docs(db: &RootDatabase, def: D) -> (String, Option) -where - D: HasDocs + HirDisplay, -{ - let label = def.display(db).to_string(); - let docs = def.docs(db); - (label, docs) -} - -fn label_and_layout_info_and_docs( - db: &RootDatabase, - def: D, - config: &HoverConfig, - layout_extractor: E, - layout_offset_extractor: E2, -) -> (String, Option) -where - D: HasDocs + HirDisplay, - E: Fn(&D) -> Result, - E2: Fn(&Layout) -> Option, -{ - let mut label = def.display(db).to_string(); - if let Some(layout) = render_memory_layout( - config.memory_layout, - || layout_extractor(&def), - layout_offset_extractor, - |_| None, - ) { - format_to!(label, "{layout}"); - } - let docs = def.docs(db); - (label, docs) -} - -fn label_value_and_layout_info_and_docs( - db: &RootDatabase, - def: D, - config: &HoverConfig, - value_extractor: E, - layout_extractor: E2, - layout_tag_extractor: E3, -) -> (String, Option) -where - D: HasDocs + HirDisplay, - E: Fn(&D) -> Option, - E2: Fn(&D) -> Result, - E3: Fn(&Layout) -> Option, - V: Display, -{ - let value = value_extractor(&def); - let mut label = match value { - Some(value) => format!("{} = {value}", def.display(db)), - None => def.display(db).to_string(), - }; - if let Some(layout) = render_memory_layout( - config.memory_layout, - || layout_extractor(&def), - |_| None, - layout_tag_extractor, - ) { - format_to!(label, "{layout}"); - } - let docs = def.docs(db); - (label, docs) -} - -fn label_value_and_docs( - db: &RootDatabase, - def: D, - value_extractor: E, -) -> (String, Option) -where - D: HasDocs + HirDisplay, - E: Fn(&D) -> Option, - V: Display, -{ - let label = if let Some(value) = value_extractor(&def) { - format!("{} = {value}", def.display(db)) - } else { - def.display(db).to_string() - }; - let docs = def.docs(db); - (label, docs) -} - fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option { - if let Definition::GenericParam(_) = def { + if matches!( + def, + Definition::GenericParam(_) + | Definition::BuiltinType(_) + | Definition::Local(_) + | Definition::Label(_) + | Definition::BuiltinAttr(_) + | Definition::ToolModule(_) + ) { return None; } def.module(db).map(|module| path(db, module, definition_owner_name(db, def))) @@ -724,14 +602,6 @@ fn markup(docs: Option, desc: String, mod_path: Option) -> Optio Some(buf.into()) } -fn builtin(famous_defs: &FamousDefs<'_, '_>, builtin: hir::BuiltinType) -> Option { - // std exposes prim_{} modules with docstrings on the root to document the builtins - let primitive_mod = format!("prim_{}", builtin.name().display(famous_defs.0.db)); - let doc_owner = find_std_module(famous_defs, &primitive_mod)?; - let docs = doc_owner.docs(famous_defs.0.db)?; - markup(Some(docs.into()), builtin.name().display(famous_defs.0.db).to_string(), None) -} - fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option { let db = famous_defs.0.db; let std_crate = famous_defs.std()?; @@ -741,34 +611,6 @@ fn find_std_module(famous_defs: &FamousDefs<'_, '_>, name: &str) -> Option Option { - let ty = it.ty(db); - let ty = ty.display_truncated(db, None); - let is_mut = if it.is_mut(db) { "mut " } else { "" }; - let mut desc = match it.primary_source(db).into_ident_pat() { - Some(ident) => { - let name = it.name(db); - let let_kw = if ident - .syntax() - .parent() - .map_or(false, |p| p.kind() == LET_STMT || p.kind() == LET_EXPR) - { - "let " - } else { - "" - }; - format!("{let_kw}{is_mut}{}: {ty}", name.display(db)) - } - None => format!("{is_mut}self: {ty}"), - }; - if let Some(layout) = - render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None) - { - format_to!(desc, "{layout}"); - } - markup(None, desc, None) -} - fn render_memory_layout( config: Option, layout: impl FnOnce() -> Result, diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index e82d730e4a36..f466b8e938f9 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -32,6 +32,7 @@ mod fn_lifetime_fn; mod implicit_static; mod param_name; mod implicit_drop; +mod range_exclusive; #[derive(Clone, Debug, PartialEq, Eq)] pub struct InlayHintsConfig { @@ -51,6 +52,7 @@ pub struct InlayHintsConfig { pub param_names_for_lifetime_elision_hints: bool, pub hide_named_constructor_hints: bool, pub hide_closure_initialization_hints: bool, + pub range_exclusive_hints: bool, pub closure_style: ClosureStyle, pub max_length: Option, pub closing_brace_hints_min_lines: Option, @@ -127,6 +129,7 @@ pub enum InlayKind { Parameter, Type, Drop, + RangeExclusive, } #[derive(Debug)] @@ -517,13 +520,20 @@ fn hints( closure_captures::hints(hints, famous_defs, config, file_id, it.clone()); closure_ret::hints(hints, famous_defs, config, file_id, it) }, + ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, config, it), _ => None, } }, ast::Pat(it) => { binding_mode::hints(hints, sema, config, &it); - if let ast::Pat::IdentPat(it) = it { - bind_pat::hints(hints, famous_defs, config, file_id, &it); + match it { + ast::Pat::IdentPat(it) => { + bind_pat::hints(hints, famous_defs, config, file_id, &it); + } + ast::Pat::RangePat(it) => { + range_exclusive::hints(hints, config, it); + } + _ => {} } Some(()) }, @@ -593,7 +603,6 @@ mod tests { use hir::ClosureStyle; use itertools::Itertools; use test_utils::extract_annotations; - use text_edit::{TextRange, TextSize}; use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode}; use crate::DiscriminantHints; @@ -622,6 +631,7 @@ mod tests { closing_brace_hints_min_lines: None, fields_to_resolve: InlayFieldsToResolve::empty(), implicit_drop_hints: false, + range_exclusive_hints: false, }; pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig { type_hints: true, @@ -654,29 +664,6 @@ mod tests { assert_eq!(expected, actual, "\nExpected:\n{expected:#?}\n\nActual:\n{actual:#?}"); } - #[track_caller] - pub(super) fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { - let (analysis, file_id) = fixture::file(ra_fixture); - let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); - expect.assert_debug_eq(&inlay_hints) - } - - #[track_caller] - pub(super) fn check_expect_clear_loc( - config: InlayHintsConfig, - ra_fixture: &str, - expect: Expect, - ) { - let (analysis, file_id) = fixture::file(ra_fixture); - let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); - inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| { - if let Some(loc) = &mut hint.linked_location { - loc.range = TextRange::empty(TextSize::from(0)); - } - }); - expect.assert_debug_eq(&inlay_hints) - } - /// Computes inlay hints for the fixture, applies all the provided text edits and then runs /// expect test. #[track_caller] diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs index c9e9a2237867..b6063978e923 100644 --- a/crates/ide/src/inlay_hints/chaining.rs +++ b/crates/ide/src/inlay_hints/chaining.rs @@ -75,12 +75,12 @@ pub(super) fn hints( #[cfg(test)] mod tests { - use expect_test::expect; + use expect_test::{expect, Expect}; + use text_edit::{TextRange, TextSize}; use crate::{ - inlay_hints::tests::{ - check_expect, check_expect_clear_loc, check_with_config, DISABLED_CONFIG, TEST_CONFIG, - }, + fixture, + inlay_hints::tests::{check_with_config, DISABLED_CONFIG, TEST_CONFIG}, InlayHintsConfig, }; @@ -89,6 +89,33 @@ mod tests { check_with_config(InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG }, ra_fixture); } + #[track_caller] + pub(super) fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { + let (analysis, file_id) = fixture::file(ra_fixture); + let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); + let filtered = + inlay_hints.into_iter().map(|hint| (hint.range, hint.label)).collect::>(); + expect.assert_debug_eq(&filtered) + } + + #[track_caller] + pub(super) fn check_expect_clear_loc( + config: InlayHintsConfig, + ra_fixture: &str, + expect: Expect, + ) { + let (analysis, file_id) = fixture::file(ra_fixture); + let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); + inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| { + if let Some(loc) = &mut hint.linked_location { + loc.range = TextRange::empty(TextSize::from(0)); + } + }); + let filtered = + inlay_hints.into_iter().map(|hint| (hint.range, hint.label)).collect::>(); + expect.assert_debug_eq(&filtered) + } + #[test] fn chaining_hints_ignore_comments() { check_expect( @@ -109,13 +136,9 @@ fn main() { "#, expect![[r#" [ - InlayHint { - range: 147..172, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ( + 147..172, + [ "", InlayHintLabelPart { text: "B", @@ -131,16 +154,10 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 147..154, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 147..154, + [ "", InlayHintLabelPart { text: "A", @@ -156,9 +173,7 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, + ), ] "#]], ); @@ -204,13 +219,9 @@ fn main() { }"#, expect![[r#" [ - InlayHint { - range: 143..190, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ( + 143..190, + [ "", InlayHintLabelPart { text: "C", @@ -226,16 +237,10 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 143..179, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 143..179, + [ "", InlayHintLabelPart { text: "B", @@ -251,9 +256,7 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, + ), ] "#]], ); @@ -283,13 +286,9 @@ fn main() { }"#, expect![[r#" [ - InlayHint { - range: 143..190, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ( + 143..190, + [ "", InlayHintLabelPart { text: "C", @@ -305,16 +304,10 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 143..179, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 143..179, + [ "", InlayHintLabelPart { text: "B", @@ -330,9 +323,7 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, + ), ] "#]], ); @@ -363,13 +354,9 @@ fn main() { "#, expect![[r#" [ - InlayHint { - range: 246..283, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ( + 246..283, + [ "", InlayHintLabelPart { text: "B", @@ -398,16 +385,10 @@ fn main() { }, ">", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 246..265, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 246..265, + [ "", InlayHintLabelPart { text: "A", @@ -436,9 +417,7 @@ fn main() { }, ">", ], - text_edit: None, - needs_resolve: true, - }, + ), ] "#]], ); @@ -471,13 +450,9 @@ fn main() { "#, expect![[r#" [ - InlayHint { - range: 174..241, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ( + 174..241, + [ "impl ", InlayHintLabelPart { text: "Iterator", @@ -506,16 +481,10 @@ fn main() { }, " = ()>", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 174..224, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 174..224, + [ "impl ", InlayHintLabelPart { text: "Iterator", @@ -544,16 +513,10 @@ fn main() { }, " = ()>", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 174..206, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 174..206, + [ "impl ", InlayHintLabelPart { text: "Iterator", @@ -582,16 +545,10 @@ fn main() { }, " = ()>", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 174..189, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 174..189, + [ "&mut ", InlayHintLabelPart { text: "MyIter", @@ -607,9 +564,7 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, + ), ] "#]], ); @@ -639,13 +594,9 @@ fn main() { "#, expect![[r#" [ - InlayHint { - range: 124..130, - position: After, - pad_left: true, - pad_right: false, - kind: Type, - label: [ + ( + 124..130, + [ "", InlayHintLabelPart { text: "Struct", @@ -661,25 +612,10 @@ fn main() { }, "", ], - text_edit: Some( - TextEdit { - indels: [ - Indel { - insert: ": Struct", - delete: 130..130, - }, - ], - }, - ), - needs_resolve: true, - }, - InlayHint { - range: 145..185, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 145..185, + [ "", InlayHintLabelPart { text: "Struct", @@ -695,16 +631,10 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 145..168, - position: After, - pad_left: true, - pad_right: false, - kind: Chaining, - label: [ + ), + ( + 145..168, + [ "", InlayHintLabelPart { text: "Struct", @@ -720,16 +650,10 @@ fn main() { }, "", ], - text_edit: None, - needs_resolve: true, - }, - InlayHint { - range: 222..228, - position: Before, - pad_left: false, - pad_right: true, - kind: Parameter, - label: [ + ), + ( + 222..228, + [ InlayHintLabelPart { text: "self", linked_location: Some( @@ -743,9 +667,7 @@ fn main() { tooltip: "", }, ], - text_edit: None, - needs_resolve: true, - }, + ), ] "#]], ); diff --git a/crates/ide/src/inlay_hints/range_exclusive.rs b/crates/ide/src/inlay_hints/range_exclusive.rs new file mode 100644 index 000000000000..50ab15c504f6 --- /dev/null +++ b/crates/ide/src/inlay_hints/range_exclusive.rs @@ -0,0 +1,121 @@ +//! Implementation of "range exclusive" inlay hints: +//! ```no_run +//! for i in 0../* < */10 {} +//! if let ../* < */100 = 50 {} +//! ``` +use syntax::{ast, SyntaxToken, T}; + +use crate::{InlayHint, InlayHintsConfig}; + +pub(super) fn hints( + acc: &mut Vec, + config: &InlayHintsConfig, + range: impl ast::RangeItem, +) -> Option<()> { + (config.range_exclusive_hints && range.end().is_some()) + .then(|| { + range.op_token().filter(|token| token.kind() == T![..]).map(|token| { + acc.push(inlay_hint(token)); + }) + }) + .flatten() +} + +fn inlay_hint(token: SyntaxToken) -> InlayHint { + InlayHint { + range: token.text_range(), + position: crate::InlayHintPosition::After, + pad_left: false, + pad_right: false, + kind: crate::InlayKind::RangeExclusive, + label: crate::InlayHintLabel::from("<"), + text_edit: None, + needs_resolve: false, + } +} + +#[cfg(test)] +mod tests { + use crate::{ + inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, + InlayHintsConfig, + }; + + #[test] + fn range_exclusive_expression_bounded_above_hints() { + check_with_config( + InlayHintsConfig { range_exclusive_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + let a = 0..10; + //^^< + let b = ..100; + //^^< + let c = (2 - 1)..(7 * 8) + //^^< +}"#, + ); + } + + #[test] + fn range_exclusive_expression_unbounded_above_no_hints() { + check_with_config( + InlayHintsConfig { range_exclusive_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + let a = 0..; + let b = ..; +}"#, + ); + } + + #[test] + fn range_inclusive_expression_no_hints() { + check_with_config( + InlayHintsConfig { range_exclusive_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + let a = 0..=10; + let b = ..=100; +}"#, + ); + } + + #[test] + fn range_exclusive_pattern_bounded_above_hints() { + check_with_config( + InlayHintsConfig { range_exclusive_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + if let 0..10 = 0 {} + //^^< + if let ..100 = 0 {} + //^^< +}"#, + ); + } + + #[test] + fn range_exclusive_pattern_unbounded_above_no_hints() { + check_with_config( + InlayHintsConfig { range_exclusive_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + if let 0.. = 0 {} + if let .. = 0 {} +}"#, + ); + } + + #[test] + fn range_inclusive_pattern_no_hints() { + check_with_config( + InlayHintsConfig { range_exclusive_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + if let 0..=10 = 0 {} + if let ..=100 = 0 {} +}"#, + ); + } +} diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 6ff16b9e2f71..c98e9fba120a 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -99,7 +99,10 @@ pub use crate::{ }, join_lines::JoinLinesConfig, markup::Markup, - moniker::{MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation}, + moniker::{ + MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation, + SymbolInformationKind, + }, move_item::Direction, navigation_target::{NavigationTarget, UpmappingResult}, prime_caches::ParallelPrimeCachesProgress, @@ -411,11 +414,12 @@ impl Analysis { } /// Fuzzy searches for a symbol. - pub fn symbol_search(&self, query: Query) -> Cancellable> { + pub fn symbol_search(&self, query: Query, limit: usize) -> Cancellable> { self.with_db(|db| { symbol_index::world_symbols(db, query) .into_iter() // xx: should we make this a par iter? .filter_map(|s| s.try_to_nav(db)) + .take(limit) .map(UpmappingResult::call_site) .collect::>() }) diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs index 8e8bb5e0139e..486329dadeda 100644 --- a/crates/ide/src/moniker.rs +++ b/crates/ide/src/moniker.rs @@ -1,7 +1,7 @@ //! This module generates [moniker](https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/#exportsImports) //! for LSIF and LSP. -use hir::{AsAssocItem, AssocItemContainer, Crate, DescendPreference, Semantics}; +use hir::{Adt, AsAssocItem, AssocItemContainer, Crate, DescendPreference, MacroKind, Semantics}; use ide_db::{ base_db::{CrateOrigin, FilePosition, LangCrateOrigin}, defs::{Definition, IdentClass}, @@ -25,6 +25,62 @@ pub enum MonikerDescriptorKind { Meta, } +// Subset of scip_types::SymbolInformation::Kind +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum SymbolInformationKind { + AssociatedType, + Attribute, + Constant, + Enum, + EnumMember, + Field, + Function, + Macro, + Method, + Module, + Parameter, + SelfParameter, + StaticMethod, + StaticVariable, + Struct, + Trait, + TraitMethod, + Type, + TypeAlias, + TypeParameter, + Union, + Variable, +} + +impl From for MonikerDescriptorKind { + fn from(value: SymbolInformationKind) -> Self { + match value { + SymbolInformationKind::AssociatedType => Self::TypeParameter, + SymbolInformationKind::Attribute => Self::Macro, + SymbolInformationKind::Constant => Self::Term, + SymbolInformationKind::Enum => Self::Type, + SymbolInformationKind::EnumMember => Self::Type, + SymbolInformationKind::Field => Self::Term, + SymbolInformationKind::Function => Self::Method, + SymbolInformationKind::Macro => Self::Macro, + SymbolInformationKind::Method => Self::Method, + SymbolInformationKind::Module => Self::Namespace, + SymbolInformationKind::Parameter => Self::Parameter, + SymbolInformationKind::SelfParameter => Self::Parameter, + SymbolInformationKind::StaticMethod => Self::Method, + SymbolInformationKind::StaticVariable => Self::Meta, + SymbolInformationKind::Struct => Self::Type, + SymbolInformationKind::Trait => Self::Type, + SymbolInformationKind::TraitMethod => Self::Method, + SymbolInformationKind::Type => Self::Type, + SymbolInformationKind::TypeAlias => Self::Type, + SymbolInformationKind::TypeParameter => Self::TypeParameter, + SymbolInformationKind::Union => Self::Type, + SymbolInformationKind::Variable => Self::Term, + } + } +} + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct MonikerDescriptor { pub name: String, @@ -112,6 +168,69 @@ pub(crate) fn moniker( Some(RangeInfo::new(original_token.text_range(), navs)) } +pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformationKind { + use SymbolInformationKind::*; + + match def { + Definition::Macro(it) => match it.kind(db) { + MacroKind::Declarative => Macro, + MacroKind::Derive => Attribute, + MacroKind::BuiltIn => Macro, + MacroKind::Attr => Attribute, + MacroKind::ProcMacro => Macro, + }, + Definition::Field(..) | Definition::TupleField(..) => Field, + Definition::Module(..) => Module, + Definition::Function(it) => { + if it.as_assoc_item(db).is_some() { + if it.has_self_param(db) { + if it.has_body(db) { + Method + } else { + TraitMethod + } + } else { + StaticMethod + } + } else { + Function + } + } + Definition::Adt(Adt::Struct(..)) => Struct, + Definition::Adt(Adt::Union(..)) => Union, + Definition::Adt(Adt::Enum(..)) => Enum, + Definition::Variant(..) => EnumMember, + Definition::Const(..) => Constant, + Definition::Static(..) => StaticVariable, + Definition::Trait(..) => Trait, + Definition::TraitAlias(..) => Trait, + Definition::TypeAlias(it) => { + if it.as_assoc_item(db).is_some() { + AssociatedType + } else { + TypeAlias + } + } + Definition::BuiltinType(..) => Type, + Definition::SelfType(..) => TypeAlias, + Definition::GenericParam(..) => TypeParameter, + Definition::Local(it) => { + if it.is_self(db) { + SelfParameter + } else if it.is_param(db) { + Parameter + } else { + Variable + } + } + Definition::Label(..) => Variable, // For lack of a better variant + Definition::DeriveHelper(..) => Attribute, + Definition::BuiltinAttr(..) => Attribute, + Definition::ToolModule(..) => Module, + Definition::ExternCrateDecl(..) => Module, + } +} + pub(crate) fn def_to_moniker( db: &RootDatabase, def: Definition, @@ -134,7 +253,7 @@ pub(crate) fn def_to_moniker( description.extend(module.path_to_root(db).into_iter().filter_map(|x| { Some(MonikerDescriptor { name: x.name(db)?.display(db).to_string(), - desc: MonikerDescriptorKind::Namespace, + desc: def_to_kind(db, x.into()).into(), }) })); @@ -147,7 +266,7 @@ pub(crate) fn def_to_moniker( // we have to include the trait name as part of the moniker for uniqueness. description.push(MonikerDescriptor { name: trait_.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, + desc: def_to_kind(db, trait_.into()).into(), }); } AssocItemContainer::Impl(impl_) => { @@ -156,14 +275,14 @@ pub(crate) fn def_to_moniker( if let Some(adt) = impl_.self_ty(db).as_adt() { description.push(MonikerDescriptor { name: adt.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, + desc: def_to_kind(db, adt.into()).into(), }); } if let Some(trait_) = impl_.trait_(db) { description.push(MonikerDescriptor { name: trait_.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, + desc: def_to_kind(db, trait_.into()).into(), }); } } @@ -173,21 +292,26 @@ pub(crate) fn def_to_moniker( if let Definition::Field(it) = def { description.push(MonikerDescriptor { name: it.parent_def(db).name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, + desc: def_to_kind(db, it.parent_def(db).into()).into(), }); } // Qualify locals/parameters by their parent definition name. if let Definition::Local(it) = def { - let parent_name = it.parent(db).name(db); - if let Some(name) = parent_name { - description.push(MonikerDescriptor { - name: name.display(db).to_string(), - desc: MonikerDescriptorKind::Method, - }); + let parent = Definition::try_from(it.parent(db)).ok(); + if let Some(parent) = parent { + let parent_name = parent.name(db); + if let Some(name) = parent_name { + description.push(MonikerDescriptor { + name: name.display(db).to_string(), + desc: def_to_kind(db, parent).into(), + }); + } } } + let desc = def_to_kind(db, def).into(); + let name_desc = match def { // These are handled by top-level guard (for performance). Definition::GenericParam(_) @@ -201,67 +325,54 @@ pub(crate) fn def_to_moniker( return None; } - MonikerDescriptor { - name: local.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Parameter, - } + MonikerDescriptor { name: local.name(db).display(db).to_string(), desc } + } + Definition::Macro(m) => { + MonikerDescriptor { name: m.name(db).display(db).to_string(), desc } + } + Definition::Function(f) => { + MonikerDescriptor { name: f.name(db).display(db).to_string(), desc } + } + Definition::Variant(v) => { + MonikerDescriptor { name: v.name(db).display(db).to_string(), desc } + } + Definition::Const(c) => { + MonikerDescriptor { name: c.name(db)?.display(db).to_string(), desc } + } + Definition::Trait(trait_) => { + MonikerDescriptor { name: trait_.name(db).display(db).to_string(), desc } + } + Definition::TraitAlias(ta) => { + MonikerDescriptor { name: ta.name(db).display(db).to_string(), desc } + } + Definition::TypeAlias(ta) => { + MonikerDescriptor { name: ta.name(db).display(db).to_string(), desc } + } + Definition::Module(m) => { + MonikerDescriptor { name: m.name(db)?.display(db).to_string(), desc } + } + Definition::BuiltinType(b) => { + MonikerDescriptor { name: b.name().display(db).to_string(), desc } } - Definition::Macro(m) => MonikerDescriptor { - name: m.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Macro, - }, - Definition::Function(f) => MonikerDescriptor { - name: f.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Method, - }, - Definition::Variant(v) => MonikerDescriptor { - name: v.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, - }, - Definition::Const(c) => MonikerDescriptor { - name: c.name(db)?.display(db).to_string(), - desc: MonikerDescriptorKind::Term, - }, - Definition::Trait(trait_) => MonikerDescriptor { - name: trait_.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, - }, - Definition::TraitAlias(ta) => MonikerDescriptor { - name: ta.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, - }, - Definition::TypeAlias(ta) => MonikerDescriptor { - name: ta.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::TypeParameter, - }, - Definition::Module(m) => MonikerDescriptor { - name: m.name(db)?.display(db).to_string(), - desc: MonikerDescriptorKind::Namespace, - }, - Definition::BuiltinType(b) => MonikerDescriptor { - name: b.name().display(db).to_string(), - desc: MonikerDescriptorKind::Type, - }, Definition::SelfType(imp) => MonikerDescriptor { name: imp.self_ty(db).as_adt()?.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, - }, - Definition::Field(it) => MonikerDescriptor { - name: it.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Term, - }, - Definition::Adt(adt) => MonikerDescriptor { - name: adt.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Type, - }, - Definition::Static(s) => MonikerDescriptor { - name: s.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Meta, - }, - Definition::ExternCrateDecl(m) => MonikerDescriptor { - name: m.name(db).display(db).to_string(), - desc: MonikerDescriptorKind::Namespace, + desc, }, + Definition::Field(it) => { + MonikerDescriptor { name: it.name(db).display(db).to_string(), desc } + } + Definition::TupleField(it) => { + MonikerDescriptor { name: it.name().display(db).to_string(), desc } + } + Definition::Adt(adt) => { + MonikerDescriptor { name: adt.name(db).display(db).to_string(), desc } + } + Definition::Static(s) => { + MonikerDescriptor { name: s.name(db).display(db).to_string(), desc } + } + Definition::ExternCrateDecl(m) => { + MonikerDescriptor { name: m.name(db).display(db).to_string(), desc } + } }; description.push(name_desc); diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 6cb7d7724d5f..bc0574ca86ed 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -237,7 +237,7 @@ impl TryToNav for Definition { Definition::TraitAlias(it) => it.try_to_nav(db), Definition::TypeAlias(it) => it.try_to_nav(db), Definition::ExternCrateDecl(it) => Some(it.try_to_nav(db)?), - Definition::BuiltinType(_) => None, + Definition::BuiltinType(_) | Definition::TupleField(_) => None, Definition::ToolModule(_) => None, Definition::BuiltinAttr(_) => None, // FIXME: The focus range should be set to the helper declaration @@ -724,11 +724,8 @@ fn orig_range_with_focus( ) -> UpmappingResult<(FileRange, Option)> { let Some(name) = name else { return orig_range(db, hir_file, value) }; - let call_range = || { - db.lookup_intern_macro_call(hir_file.macro_file().unwrap().macro_call_id) - .kind - .original_call_range(db) - }; + let call_kind = + || db.lookup_intern_macro_call(hir_file.macro_file().unwrap().macro_call_id).kind; let def_range = || { db.lookup_intern_macro_call(hir_file.macro_file().unwrap().macro_call_id) @@ -755,7 +752,22 @@ fn orig_range_with_focus( } // name lies outside the node, so instead point to the macro call which // *should* contain the name - _ => call_range(), + _ => { + let kind = call_kind(); + let range = kind.clone().original_call_range_with_body(db); + //If the focus range is in the attribute/derive body, we + // need to point the call site to the entire body, if not, fall back + // to the name range of the attribute/derive call + // FIXME: Do this differently, this is very inflexible the caller + // should choose this behavior + if range.file_id == focus_range.file_id + && range.range.contains_range(focus_range.range) + { + range + } else { + kind.original_call_range(db) + } + } }, Some(focus_range), ), @@ -784,7 +796,7 @@ fn orig_range_with_focus( // node is in macro def, just show the focus _ => ( // show the macro call - (call_range(), None), + (call_kind().original_call_range(db), None), Some((focus_range, Some(focus_range))), ), } @@ -848,7 +860,7 @@ fn foo() { enum FooInner { } } "#, ); - let navs = analysis.symbol_search(Query::new("FooInner".to_string())).unwrap(); + let navs = analysis.symbol_search(Query::new("FooInner".to_string()), !0).unwrap(); expect![[r#" [ NavigationTarget { @@ -886,7 +898,7 @@ struct Foo; "#, ); - let navs = analysis.symbol_search(Query::new("foo".to_string())).unwrap(); + let navs = analysis.symbol_search(Query::new("foo".to_string()), !0).unwrap(); assert_eq!(navs.len(), 2) } } diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index 1febfabfcb7f..3bf41defe343 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs @@ -366,6 +366,7 @@ fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Opt #[cfg(test)] mod tests { use expect_test::{expect, Expect}; + use ide_db::source_change::SourceChange; use stdx::trim_indent; use test_utils::assert_eq_text; use text_edit::TextEdit; @@ -418,7 +419,7 @@ mod tests { let (analysis, position) = fixture::position(ra_fixture); let source_change = analysis.rename(position, new_name).unwrap().expect("Expect returned a RenameError"); - expect.assert_debug_eq(&source_change) + expect.assert_eq(&filter_expect(source_change)) } fn check_expect_will_rename_file(new_name: &str, ra_fixture: &str, expect: Expect) { @@ -427,7 +428,7 @@ mod tests { .will_rename_file(position.file_id, new_name) .unwrap() .expect("Expect returned a RenameError"); - expect.assert_debug_eq(&source_change) + expect.assert_eq(&filter_expect(source_change)) } fn check_prepare(ra_fixture: &str, expect: Expect) { @@ -444,6 +445,19 @@ mod tests { }; } + fn filter_expect(source_change: SourceChange) -> String { + let source_file_edits = source_change + .source_file_edits + .into_iter() + .map(|(id, (text_edit, _))| (id, text_edit.into_iter().collect::>())) + .collect::>(); + + format!( + "source_file_edits: {:#?}\nfile_system_edits: {:#?}\n", + source_file_edits, source_change.file_system_edits + ) + } + #[test] fn test_prepare_rename_namelikes() { check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); @@ -916,37 +930,32 @@ mod foo$0; // empty "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 1, - ): ( - TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, - None, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + [ + Indel { + insert: "foo2", + delete: 4..7, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 2, + ), + dst: AnchoredPathBuf { + anchor: FileId( 2, ), - dst: AnchoredPathBuf { - anchor: FileId( - 2, - ), - path: "foo2.rs", - }, + path: "foo2.rs", }, - ], - is_snippet: false, - } + }, + ] "#]], ); } @@ -968,50 +977,43 @@ pub struct FooContent; use crate::foo$0::FooContent; "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "quux", - delete: 8..11, - }, - ], - }, - None, ), + [ + Indel { + insert: "quux", + delete: 8..11, + }, + ], + ), + ( FileId( 2, - ): ( - TextEdit { - indels: [ - Indel { - insert: "quux", - delete: 11..14, - }, - ], - }, - None, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + [ + Indel { + insert: "quux", + delete: 11..14, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "quux.rs", - }, + path: "quux.rs", }, - ], - is_snippet: false, - } + }, + ] "#]], ); } @@ -1027,43 +1029,38 @@ mod fo$0o; // empty "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, - None, ), - }, - file_system_edits: [ - MoveDir { - src: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "../foo", + [ + Indel { + insert: "foo2", + delete: 4..7, }, - src_id: FileId( + ], + ), + ] + file_system_edits: [ + MoveDir { + src: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "../foo2", - }, + path: "../foo", }, - ], - is_snippet: false, - } + src_id: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( + 1, + ), + path: "../foo2", + }, + }, + ] "#]], ); } @@ -1080,37 +1077,32 @@ mod outer { mod fo$0o; } // empty "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "bar", - delete: 16..19, - }, - ], - }, - None, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + [ + Indel { + insert: "bar", + delete: 16..19, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "bar.rs", - }, + path: "bar.rs", }, - ], - is_snippet: false, - } + }, + ] "#]], ); } @@ -1156,50 +1148,43 @@ pub mod foo$0; // pub fn fun() {} "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 27..30, - }, - ], - }, - None, ), + [ + Indel { + insert: "foo2", + delete: 27..30, + }, + ], + ), + ( FileId( 1, - ): ( - TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 8..11, - }, - ], - }, - None, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + [ + Indel { + insert: "foo2", + delete: 8..11, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 2, + ), + dst: AnchoredPathBuf { + anchor: FileId( 2, ), - dst: AnchoredPathBuf { - anchor: FileId( - 2, - ), - path: "foo2.rs", - }, + path: "foo2.rs", }, - ], - is_snippet: false, - } + }, + ] "#]], ); } @@ -1229,54 +1214,49 @@ mod quux; // empty "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, - None, ), + [ + Indel { + insert: "foo2", + delete: 4..7, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( + 1, + ), + path: "foo2.rs", + }, }, - file_system_edits: [ - MoveFile { - src: FileId( + MoveDir { + src: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "foo2.rs", - }, + path: "foo", }, - MoveDir { - src: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "foo", - }, - src_id: FileId( + src_id: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "foo2", - }, + path: "foo2", }, - ], - is_snippet: false, - } + }, + ] "#]], ) } @@ -1344,12 +1324,9 @@ fn foo() {} mod bar$0; "#, expect![[r#" - SourceChange { - source_file_edits: {}, - file_system_edits: [], - is_snippet: false, - } - "#]], + source_file_edits: [] + file_system_edits: [] + "#]], ) } @@ -1370,58 +1347,53 @@ pub mod bar; pub fn baz() {} "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "r#fn", - delete: 4..7, - }, - Indel { - insert: "r#fn", - delete: 22..25, - }, - ], - }, - None, ), + [ + Indel { + insert: "r#fn", + delete: 4..7, + }, + Indel { + insert: "r#fn", + delete: 22..25, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( + 1, + ), + path: "fn.rs", + }, }, - file_system_edits: [ - MoveFile { - src: FileId( + MoveDir { + src: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "fn.rs", - }, + path: "foo", }, - MoveDir { - src: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "foo", - }, - src_id: FileId( + src_id: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "fn", - }, + path: "fn", }, - ], - is_snippet: false, - } + }, + ] "#]], ); } @@ -1443,58 +1415,53 @@ pub mod bar; pub fn baz() {} "#, expect![[r#" - SourceChange { - source_file_edits: { + source_file_edits: [ + ( FileId( 0, - ): ( - TextEdit { - indels: [ - Indel { - insert: "foo", - delete: 4..8, - }, - Indel { - insert: "foo", - delete: 23..27, - }, - ], - }, - None, ), + [ + Indel { + insert: "foo", + delete: 4..8, + }, + Indel { + insert: "foo", + delete: 23..27, + }, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( + 1, + ), + path: "foo.rs", + }, }, - file_system_edits: [ - MoveFile { - src: FileId( + MoveDir { + src: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "foo.rs", - }, + path: "fn", }, - MoveDir { - src: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "fn", - }, - src_id: FileId( + src_id: FileId( + 1, + ), + dst: AnchoredPathBuf { + anchor: FileId( 1, ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "foo", - }, + path: "foo", }, - ], - is_snippet: false, - } + }, + ] "#]], ); } diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index d334e66d3dd6..352ce89820de 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -555,28 +555,33 @@ mod tests { use crate::fixture; - use super::{RunnableTestKind::*, *}; - - fn check( - ra_fixture: &str, - // FIXME: fold this into `expect` as well - actions: &[RunnableTestKind], - expect: Expect, - ) { + fn check(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let mut runnables = analysis.runnables(position.file_id).unwrap(); runnables.sort_by_key(|it| (it.nav.full_range.start(), it.nav.name.clone())); - expect.assert_debug_eq(&runnables); - assert_eq!( - actions, - runnables.into_iter().map(|it| it.test_kind()).collect::>().as_slice() - ); + + let result = runnables + .into_iter() + .map(|runnable| { + let mut a = format!("({:?}, {:?}", runnable.test_kind(), runnable.nav); + if runnable.use_name_in_title { + a.push_str(", true"); + } + if let Some(cfg) = runnable.cfg { + a.push_str(&format!(", {cfg:?}")); + } + a.push_str(")"); + a + }) + .collect::>(); + expect.assert_debug_eq(&result); } fn check_tests(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let tests = analysis.related_tests(position, None).unwrap(); - expect.assert_debug_eq(&tests); + let navigation_targets = tests.into_iter().map(|runnable| runnable.nav).collect::>(); + expect.assert_debug_eq(&navigation_targets); } #[test] @@ -607,133 +612,15 @@ mod not_a_root { fn main() {} } "#, - &[TestMod, Bin, Bin, Test, Test, Test, Bench], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..253, - name: "", - kind: Module, - }, - kind: TestMod { - path: "", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 15..76, - focus_range: 42..71, - name: "__cortex_m_rt_main_trampoline", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 78..102, - focus_range: 89..97, - name: "test_foo", - kind: Function, - }, - kind: Test { - test_id: Path( - "test_foo", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 104..155, - focus_range: 136..150, - name: "test_full_path", - kind: Function, - }, - kind: Test { - test_id: Path( - "test_full_path", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 157..191, - focus_range: 178..186, - name: "test_foo", - kind: Function, - }, - kind: Test { - test_id: Path( - "test_foo", - ), - attr: TestAttr { - ignore: true, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 193..215, - focus_range: 205..210, - name: "bench", - kind: Function, - }, - kind: Bench { - test_id: Path( - "bench", - ), - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..253, name: \"\", kind: Module })", + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 15..76, focus_range: 42..71, name: \"__cortex_m_rt_main_trampoline\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 78..102, focus_range: 89..97, name: \"test_foo\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 104..155, focus_range: 136..150, name: \"test_full_path\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 157..191, focus_range: 178..186, name: \"test_foo\", kind: Function })", + "(Bench, NavigationTarget { file_id: FileId(0), full_range: 193..215, focus_range: 205..210, name: \"bench\", kind: Function })", ] "#]], ); @@ -835,155 +722,17 @@ trait Test { /// ``` impl Test for StructWithRunnable {} "#, - &[Bin, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 15..74, - name: "should_have_runnable", - }, - kind: DocTest { - test_id: Path( - "should_have_runnable", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 76..148, - name: "should_have_runnable_1", - }, - kind: DocTest { - test_id: Path( - "should_have_runnable_1", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 150..254, - name: "should_have_runnable_2", - }, - kind: DocTest { - test_id: Path( - "should_have_runnable_2", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 256..320, - name: "should_have_no_runnable_3", - }, - kind: DocTest { - test_id: Path( - "should_have_no_runnable_3", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 322..398, - name: "should_have_no_runnable_4", - }, - kind: DocTest { - test_id: Path( - "should_have_no_runnable_4", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 900..965, - name: "StructWithRunnable", - }, - kind: DocTest { - test_id: Path( - "StructWithRunnable", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 967..1024, - focus_range: 1003..1021, - name: "impl", - kind: Impl, - }, - kind: DocTest { - test_id: Path( - "StructWithRunnable", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1088..1154, - focus_range: 1133..1151, - name: "impl", - kind: Impl, - }, - kind: DocTest { - test_id: Path( - "StructWithRunnable", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 15..74, name: \"should_have_runnable\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 76..148, name: \"should_have_runnable_1\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 150..254, name: \"should_have_runnable_2\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 256..320, name: \"should_have_no_runnable_3\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 322..398, name: \"should_have_no_runnable_4\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 900..965, name: \"StructWithRunnable\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 967..1024, focus_range: 1003..1021, name: \"impl\", kind: Impl })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 1088..1154, focus_range: 1133..1151, name: \"impl\", kind: Impl })", ] "#]], ); @@ -1005,39 +754,10 @@ impl Data { fn foo() {} } "#, - &[Bin, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 44..98, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "Data::foo", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 44..98, name: \"foo\" })", ] "#]], ); @@ -1059,39 +779,10 @@ impl Data<'a> { fn foo() {} } "#, - &[Bin, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 52..106, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "Data<'a>::foo", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 52..106, name: \"foo\" })", ] "#]], ); @@ -1113,39 +804,10 @@ impl Data<'a, T, U> { fn foo() {} } "#, - &[Bin, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 70..124, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "Data<'a,T,U>::foo", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 70..124, name: \"foo\" })", ] "#]], ); @@ -1167,39 +829,10 @@ impl Data { fn foo() {} } "#, - &[Bin, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 79..133, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "Data::foo", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 79..133, name: \"foo\" })", ] "#]], ); @@ -1221,39 +854,10 @@ impl<'a, T, const N: usize> Data<'a, T, N> { fn foo() {} } "#, - &[Bin, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 100..154, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "Data<'a,T,N>::foo", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 100..154, name: \"foo\" })", ] "#]], ); @@ -1269,47 +873,10 @@ mod test_mod { fn test_foo1() {} } "#, - &[TestMod, Test], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..51, - focus_range: 5..13, - name: "test_mod", - kind: Module, - description: "mod test_mod", - }, - kind: TestMod { - path: "test_mod", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 20..49, - focus_range: 35..44, - name: "test_foo1", - kind: Function, - }, - kind: Test { - test_id: Path( - "test_mod::test_foo1", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 1..51, focus_range: 5..13, name: \"test_mod\", kind: Module, description: \"mod test_mod\" })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 20..49, focus_range: 35..44, name: \"test_foo1\", kind: Function })", ] "#]], ); @@ -1342,123 +909,14 @@ mod root_tests { mod nested_tests_4 {} } "#, - &[TestMod, TestMod, Test, Test, TestMod, Test], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 22..323, - focus_range: 26..40, - name: "nested_tests_0", - kind: Module, - description: "mod nested_tests_0", - }, - kind: TestMod { - path: "root_tests::nested_tests_0", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 51..192, - focus_range: 55..69, - name: "nested_tests_1", - kind: Module, - description: "mod nested_tests_1", - }, - kind: TestMod { - path: "root_tests::nested_tests_0::nested_tests_1", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 84..126, - focus_range: 107..121, - name: "nested_test_11", - kind: Function, - }, - kind: Test { - test_id: Path( - "root_tests::nested_tests_0::nested_tests_1::nested_test_11", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 140..182, - focus_range: 163..177, - name: "nested_test_12", - kind: Function, - }, - kind: Test { - test_id: Path( - "root_tests::nested_tests_0::nested_tests_1::nested_test_12", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 202..286, - focus_range: 206..220, - name: "nested_tests_2", - kind: Module, - description: "mod nested_tests_2", - }, - kind: TestMod { - path: "root_tests::nested_tests_0::nested_tests_2", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 235..276, - focus_range: 258..271, - name: "nested_test_2", - kind: Function, - }, - kind: Test { - test_id: Path( - "root_tests::nested_tests_0::nested_tests_2::nested_test_2", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 22..323, focus_range: 26..40, name: \"nested_tests_0\", kind: Module, description: \"mod nested_tests_0\" })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 51..192, focus_range: 55..69, name: \"nested_tests_1\", kind: Module, description: \"mod nested_tests_1\" })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 84..126, focus_range: 107..121, name: \"nested_test_11\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 140..182, focus_range: 163..177, name: \"nested_test_12\", kind: Function })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 202..286, focus_range: 206..220, name: \"nested_tests_2\", kind: Module, description: \"mod nested_tests_2\" })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 235..276, focus_range: 258..271, name: \"nested_test_2\", kind: Function })", ] "#]], ); @@ -1474,52 +932,10 @@ $0 #[cfg(feature = "foo")] fn test_foo1() {} "#, - &[TestMod, Test], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..51, - name: "", - kind: Module, - }, - kind: TestMod { - path: "", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..50, - focus_range: 36..45, - name: "test_foo1", - kind: Function, - }, - kind: Test { - test_id: Path( - "test_foo1", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: Some( - Atom( - KeyValue { - key: "feature", - value: "foo", - }, - ), - ), - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..51, name: \"\", kind: Module })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 1..50, focus_range: 36..45, name: \"test_foo1\", kind: Function }, Atom(KeyValue { key: \"feature\", value: \"foo\" }))", ] "#]], ); @@ -1535,62 +951,10 @@ $0 #[cfg(all(feature = "foo", feature = "bar"))] fn test_foo1() {} "#, - &[TestMod, Test], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..73, - name: "", - kind: Module, - }, - kind: TestMod { - path: "", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..72, - focus_range: 58..67, - name: "test_foo1", - kind: Function, - }, - kind: Test { - test_id: Path( - "test_foo1", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: Some( - All( - [ - Atom( - KeyValue { - key: "feature", - value: "foo", - }, - ), - Atom( - KeyValue { - key: "feature", - value: "bar", - }, - ), - ], - ), - ), - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..73, name: \"\", kind: Module })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 1..72, focus_range: 58..67, name: \"test_foo1\", kind: Function }, All([Atom(KeyValue { key: \"feature\", value: \"foo\" }), Atom(KeyValue { key: \"feature\", value: \"bar\" })]))", ] "#]], ); @@ -1606,7 +970,6 @@ mod test_mod { fn foo1() {} } "#, - &[], expect![[r#" [] "#]], @@ -1628,25 +991,9 @@ impl Foo { fn foo() {} } "#, - &[DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 27..81, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "foo::Foo::foo", - ), - }, - cfg: None, - }, + "(DocTest, NavigationTarget { file_id: FileId(1), full_range: 27..81, name: \"foo\" })", ] "#]], ); @@ -1683,110 +1030,14 @@ mod tests { gen2!(); gen_main!(); "#, - &[TestMod, TestMod, Test, Test, TestMod, Bin], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..315, - name: "", - kind: Module, - }, - kind: TestMod { - path: "", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 267..292, - focus_range: 271..276, - name: "tests", - kind: Module, - description: "mod tests", - }, - kind: TestMod { - path: "tests", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 283..290, - name: "foo_test", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests::foo_test", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 293..301, - name: "foo_test2", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests2::foo_test2", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 293..301, - name: "tests2", - kind: Module, - description: "mod tests2", - }, - kind: TestMod { - path: "tests2", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 302..314, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..315, name: \"\", kind: Module })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 267..292, focus_range: 271..276, name: \"tests\", kind: Module, description: \"mod tests\" })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 283..290, name: \"foo_test\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 293..301, name: \"foo_test2\", kind: Function }, true)", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 293..301, name: \"tests2\", kind: Module, description: \"mod tests2\" }, true)", + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 302..314, name: \"main\", kind: Function })", ] "#]], ); @@ -1812,85 +1063,12 @@ macro_rules! foo { } foo!(); "#, - &[Test, Test, Test, TestMod], expect![[r#" [ - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 210..217, - name: "foo0", - kind: Function, - }, - kind: Test { - test_id: Path( - "foo_tests::foo0", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 210..217, - name: "foo1", - kind: Function, - }, - kind: Test { - test_id: Path( - "foo_tests::foo1", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 210..217, - name: "foo2", - kind: Function, - }, - kind: Test { - test_id: Path( - "foo_tests::foo2", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 210..217, - name: "foo_tests", - kind: Module, - description: "mod foo_tests", - }, - kind: TestMod { - path: "foo_tests", - }, - cfg: None, - }, + "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo0\", kind: Function }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo1\", kind: Function }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo2\", kind: Function }, true)", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo_tests\", kind: Module, description: \"mod foo_tests\" }, true)", ] "#]], ); @@ -1909,7 +1087,6 @@ mod tests { fn t() {} } "#, - &[], expect![[r#" [] "#]], @@ -1929,26 +1106,9 @@ fn t0() {} #[test] fn t1() {} "#, - &[TestMod], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..7, - focus_range: 5..6, - name: "m", - kind: Module, - description: "mod m", - }, - kind: TestMod { - path: "m", - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 1..7, focus_range: 5..6, name: \"m\", kind: Module, description: \"mod m\" })", ] "#]], ); @@ -1967,66 +1127,11 @@ fn t0() {} #[test] fn t1() {} "#, - &[TestMod, Test, Test], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..39, - name: "m", - kind: Module, - }, - kind: TestMod { - path: "m", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 1..19, - focus_range: 12..14, - name: "t0", - kind: Function, - }, - kind: Test { - test_id: Path( - "m::t0", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 20..38, - focus_range: 31..33, - name: "t1", - kind: Function, - }, - kind: Test { - test_id: Path( - "m::t1", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(1), full_range: 0..39, name: \"m\", kind: Module })", + "(Test, NavigationTarget { file_id: FileId(1), full_range: 1..19, focus_range: 12..14, name: \"t0\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(1), full_range: 20..38, focus_range: 31..33, name: \"t1\", kind: Function })", ] "#]], ); @@ -2047,68 +1152,11 @@ mod module { fn t1() {} } "#, - &[TestMod, Test, Test], expect![[r#" [ - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 26..94, - focus_range: 30..36, - name: "module", - kind: Module, - description: "mod module", - }, - kind: TestMod { - path: "module", - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 43..65, - focus_range: 58..60, - name: "t0", - kind: Function, - }, - kind: Test { - test_id: Path( - "module::t0", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: true, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 70..92, - focus_range: 85..87, - name: "t1", - kind: Function, - }, - kind: Test { - test_id: Path( - "module::t1", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 26..94, focus_range: 30..36, name: \"module\", kind: Module, description: \"mod module\" }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 43..65, focus_range: 58..60, name: \"t0\", kind: Function }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 70..92, focus_range: 85..87, name: \"t1\", kind: Function }, true)", ] "#]], ); @@ -2143,26 +1191,14 @@ mod tests { "#, expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 31..85, - focus_range: 46..54, - name: "foo_test", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests::foo_test", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 31..85, + focus_range: 46..54, + name: "foo_test", + kind: Function, }, ] "#]], @@ -2188,26 +1224,14 @@ mod tests { "#, expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 71..122, - focus_range: 86..94, - name: "foo_test", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests::foo_test", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 71..122, + focus_range: 86..94, + name: "foo_test", + kind: Function, }, ] "#]], @@ -2240,26 +1264,14 @@ mod tests { "#, expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 133..183, - focus_range: 148..156, - name: "foo_test", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests::foo_test", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 133..183, + focus_range: 148..156, + name: "foo_test", + kind: Function, }, ] "#]], @@ -2292,47 +1304,23 @@ mod tests { "#, expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 121..185, - focus_range: 136..145, - name: "foo2_test", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests::foo2_test", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 121..185, + focus_range: 136..145, + name: "foo2_test", + kind: Function, }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 52..115, - focus_range: 67..75, - name: "foo_test", - kind: Function, - }, - kind: Test { - test_id: Path( - "tests::foo_test", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 52..115, + focus_range: 67..75, + name: "foo_test", + kind: Function, }, ] "#]], @@ -2354,39 +1342,10 @@ impl Data<'a, A, 12, C, D> { fn foo() {} } "#, - &[Bin, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..13, - focus_range: 4..8, - name: "main", - kind: Function, - }, - kind: Bin, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 121..156, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "Data<'a,A,12,C,D>::foo", - ), - }, - cfg: None, - }, + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 121..156, name: \"foo\" })", ] "#]], ); @@ -2416,77 +1375,12 @@ impl Foo, ()> { fn t() {} } "#, - &[DocTest, DocTest, DocTest, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 20..103, - focus_range: 47..56, - name: "impl", - kind: Impl, - }, - kind: DocTest { - test_id: Path( - "Foo", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 63..101, - name: "t", - }, - kind: DocTest { - test_id: Path( - "Foo::t", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 105..188, - focus_range: 126..146, - name: "impl", - kind: Impl, - }, - kind: DocTest { - test_id: Path( - "Foo,()>", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 153..186, - name: "t", - }, - kind: DocTest { - test_id: Path( - "Foo,()>::t", - ), - }, - cfg: None, - }, + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 20..103, focus_range: 47..56, name: \"impl\", kind: Impl })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 63..101, name: \"t\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 105..188, focus_range: 126..146, name: \"impl\", kind: Impl })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 153..186, name: \"t\" })", ] "#]], ); @@ -2512,7 +1406,6 @@ macro_rules! foo { }; } "#, - &[], expect![[r#" [] "#]], @@ -2532,25 +1425,9 @@ macro_rules! foo { }; } "#, - &[DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..94, - name: "foo", - }, - kind: DocTest { - test_id: Path( - "foo", - ), - }, - cfg: None, - }, + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 1..94, name: \"foo\" })", ] "#]], ); @@ -2596,149 +1473,16 @@ mod r#mod { impl r#trait for r#struct {} } "#, - &[TestMod, Test, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest], expect![[r#" [ - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 1..461, - focus_range: 5..10, - name: "r#mod", - kind: Module, - description: "mod r#mod", - }, - kind: TestMod { - path: "r#mod", - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 17..41, - focus_range: 32..36, - name: "r#fn", - kind: Function, - }, - kind: Test { - test_id: Path( - "r#mod::r#fn", - ), - attr: TestAttr { - ignore: false, - }, - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 47..84, - name: "r#for", - container_name: "r#mod", - }, - kind: DocTest { - test_id: Path( - "r#mod::r#for", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 90..146, - name: "r#struct", - container_name: "r#mod", - }, - kind: DocTest { - test_id: Path( - "r#mod::r#struct", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 152..266, - focus_range: 189..205, - name: "impl", - kind: Impl, - }, - kind: DocTest { - test_id: Path( - "r#struct", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 216..260, - name: "r#fn", - }, - kind: DocTest { - test_id: Path( - "r#mod::r#struct::r#fn", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 323..367, - name: "r#fn", - }, - kind: DocTest { - test_id: Path( - "r#mod::r#struct::r#fn", - ), - }, - cfg: None, - }, - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 401..459, - focus_range: 445..456, - name: "impl", - kind: Impl, - }, - kind: DocTest { - test_id: Path( - "r#struct", - ), - }, - cfg: None, - }, + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 1..461, focus_range: 5..10, name: \"r#mod\", kind: Module, description: \"mod r#mod\" })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 17..41, focus_range: 32..36, name: \"r#fn\", kind: Function })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 47..84, name: \"r#for\", container_name: \"r#mod\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 90..146, name: \"r#struct\", container_name: \"r#mod\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 152..266, focus_range: 189..205, name: \"impl\", kind: Impl })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 216..260, name: \"r#fn\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 323..367, name: \"r#fn\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 401..459, focus_range: 445..456, name: \"impl\", kind: Impl })", ] "#]], ) diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 3724dc282211..5b7094e6bcc0 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -17,7 +17,7 @@ use crate::navigation_target::UpmappingResult; use crate::{ hover::hover_for_definition, inlay_hints::AdjustmentHintsMode, - moniker::{def_to_moniker, MonikerResult}, + moniker::{def_to_kind, def_to_moniker, MonikerResult, SymbolInformationKind}, parent_module::crates_for, Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav, }; @@ -46,6 +46,10 @@ pub struct TokenStaticData { pub definition: Option, pub references: Vec, pub moniker: Option, + pub display_name: Option, + pub enclosing_moniker: Option, + pub signature: Option, + pub kind: SymbolInformationKind, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -129,6 +133,7 @@ impl StaticIndex<'_> { closure_capture_hints: false, closing_brace_hints_min_lines: Some(25), fields_to_resolve: InlayFieldsToResolve::empty(), + range_exclusive_hints: false, }, file_id, None, @@ -172,6 +177,12 @@ impl StaticIndex<'_> { }), references: vec![], moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)), + display_name: def.name(self.db).map(|name| name.display(self.db).to_string()), + enclosing_moniker: current_crate + .zip(def.enclosing_definition(self.db)) + .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), + signature: def.label(self.db), + kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); it diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 0558f658fd19..d686652bb3ec 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -1,5 +1,6 @@ //! Computes color for a single element. +use either::Either; use hir::{AsAssocItem, HasVisibility, MacroFileIdExt, Semantics}; use ide_db::{ defs::{Definition, IdentClass, NameClass, NameRefClass}, @@ -359,7 +360,9 @@ pub(super) fn highlight_def( let db = sema.db; let mut h = match def { Definition::Macro(m) => Highlight::new(HlTag::Symbol(m.kind(sema.db).into())), - Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)), + Definition::Field(_) | Definition::TupleField(_) => { + Highlight::new(HlTag::Symbol(SymbolKind::Field)) + } Definition::Module(module) => { let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module)); if module.is_crate_root() { @@ -647,8 +650,11 @@ fn highlight_name_ref_by_syntax( let h = HlTag::Symbol(SymbolKind::Field); let is_union = ast::FieldExpr::cast(parent) .and_then(|field_expr| sema.resolve_field(&field_expr)) - .map_or(false, |field| { - matches!(field.parent_def(sema.db), hir::VariantDef::Union(_)) + .map_or(false, |field| match field { + Either::Left(field) => { + matches!(field.parent_def(sema.db), hir::VariantDef::Union(_)) + } + Either::Right(_) => false, }); if is_union { h | HlMod::Unsafe diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 71f4d07245d2..6bf13ffd06fc 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -301,7 +301,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { Definition::TypeAlias(_) => SymbolKind::TypeAlias, Definition::BuiltinType(_) => return HlTag::BuiltinType, Definition::Macro(_) => SymbolKind::Macro, - Definition::Field(_) => SymbolKind::Field, + Definition::Field(_) | Definition::TupleField(_) => SymbolKind::Field, Definition::SelfType(_) => SymbolKind::Impl, Definition::Local(_) => SymbolKind::Local, Definition::GenericParam(gp) => match gp { diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html index e8b3a38c9e0f..4063cf9f7570 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html @@ -96,7 +96,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd include!(concat!("foo/", "foo.rs")); fn main() { - format_args!("Hello, {}!", 92); + format_args!("Hello, {}!", (92,).0); dont_color_me_braces!(); noop!(noop!(1)); } diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index afb6c555b4af..864c6d1cad79 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -103,7 +103,7 @@ macro without_args { include!(concat!("foo/", "foo.rs")); fn main() { - format_args!("Hello, {}!", 92); + format_args!("Hello, {}!", (92,).0); dont_color_me_braces!(); noop!(noop!(1)); } diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs index 3802978f4941..53f998e5457d 100644 --- a/crates/ide/src/view_memory_layout.rs +++ b/crates/ide/src/view_memory_layout.rs @@ -69,7 +69,7 @@ impl FieldOrTupleIdx { .as_str() .map(|s| s.to_owned()) .unwrap_or_else(|| format!(".{}", f.name(db).as_tuple_index().unwrap())), - FieldOrTupleIdx::TupleIdx(i) => format!(".{i}").to_owned(), + FieldOrTupleIdx::TupleIdx(i) => format!(".{i}"), } } } @@ -203,7 +203,7 @@ pub(crate) fn view_memory_layout( let mut nodes = vec![MemoryLayoutNode { item_name, - typename: typename.clone(), + typename, size: layout.size(), offset: 0, alignment: layout.align(), diff --git a/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 55be6bc23bbb..90545bb5130c 100644 --- a/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -13,7 +13,7 @@ doctest = false cargo_metadata = "0.18.1" # local deps -toolchain = { path = "../../toolchain", version = "0.0.0" } +toolchain.workspace = true [features] sysroot-abi = [] diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index d89c4598afc7..bc1fcd08e20c 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -274,7 +274,7 @@ impl CargoWorkspace { other_options.append( &mut targets .into_iter() - .flat_map(|target| ["--filter-platform".to_owned().to_string(), target]) + .flat_map(|target| ["--filter-platform".to_owned(), target]) .collect(), ); } diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index fe046dd14630..d52e448d7470 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -6,7 +6,7 @@ use std::{env, fs, iter, ops, path::PathBuf, process::Command}; -use anyhow::{format_err, Result}; +use anyhow::{format_err, Context, Result}; use base_db::CrateName; use la_arena::{Arena, Idx}; use paths::{AbsPath, AbsPathBuf}; @@ -119,12 +119,15 @@ impl Sysroot { get_rustc_src(&self.root) } - pub fn discover_rustc(&self) -> Result { + pub fn discover_rustc(&self) -> anyhow::Result { let rustc = self.root.join("bin/rustc"); tracing::debug!(?rustc, "checking for rustc binary at location"); match fs::metadata(&rustc) { Ok(_) => Ok(rustc), - Err(e) => Err(e), + Err(e) => Err(e).context(format!( + "failed to discover rustc in sysroot: {:?}", + AsRef::::as_ref(&self.root) + )), } } diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 4057493fa3a6..00cc7c30ee3e 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -1277,7 +1277,7 @@ fn add_target_crate_root( inject_cargo_env(pkg, &mut env); if let Ok(cname) = String::from_str(cargo_name) { // CARGO_CRATE_NAME is the name of the Cargo target with - converted to _, such as the name of the library, binary, example, integration test, or benchmark. - env.set("CARGO_CRATE_NAME", cname.replace("-", "_")); + env.set("CARGO_CRATE_NAME", cname.replace('-', "_")); } if let Some(envs) = build_data.map(|it| &it.envs) { diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 1908c73b3b46..e69302dbaccf 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -792,6 +792,7 @@ impl flags::AnalysisStats { max_length: Some(25), closing_brace_hints_min_lines: Some(20), fields_to_resolve: InlayFieldsToResolve::empty(), + range_exclusive_hints: true, }, file_id, None, diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index 95c8798d43c8..c86b2c0ba405 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -7,8 +7,8 @@ use std::{ }; use ide::{ - LineCol, MonikerDescriptorKind, StaticIndex, StaticIndexedFile, TextRange, TokenId, - TokenStaticData, + LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile, + SymbolInformationKind, TextRange, TokenId, }; use ide_db::LineIndexDatabase; use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; @@ -78,6 +78,7 @@ impl flags::Scip { let mut symbols_emitted: HashSet = HashSet::default(); let mut tokens_to_symbol: HashMap = HashMap::new(); + let mut tokens_to_enclosing_symbol: HashMap> = HashMap::new(); for StaticIndexedFile { file_id, tokens, .. } in si.files { let mut local_count = 0; @@ -109,10 +110,24 @@ impl flags::Scip { let symbol = tokens_to_symbol .entry(id) .or_insert_with(|| { - let symbol = token_to_symbol(token).unwrap_or_else(&mut new_local_symbol); + let symbol = token + .moniker + .as_ref() + .map(moniker_to_symbol) + .unwrap_or_else(&mut new_local_symbol); scip::symbol::format_symbol(symbol) }) .clone(); + let enclosing_symbol = tokens_to_enclosing_symbol + .entry(id) + .or_insert_with(|| { + token + .enclosing_moniker + .as_ref() + .map(moniker_to_symbol) + .map(scip::symbol::format_symbol) + }) + .clone(); let mut symbol_roles = Default::default(); @@ -128,15 +143,22 @@ impl flags::Scip { .map(|hover| hover.markup.as_str()) .filter(|it| !it.is_empty()) .map(|it| vec![it.to_owned()]); + let signature_documentation = + token.signature.clone().map(|text| scip_types::Document { + relative_path: relative_path.clone(), + language: "rust".to_string(), + text, + ..Default::default() + }); let symbol_info = scip_types::SymbolInformation { symbol: symbol.clone(), documentation: documentation.unwrap_or_default(), relationships: Vec::new(), special_fields: Default::default(), - kind: Default::default(), - display_name: String::new(), - signature_documentation: Default::default(), - enclosing_symbol: String::new(), + kind: symbol_kind(token.kind).into(), + display_name: token.display_name.clone().unwrap_or_default(), + signature_documentation: signature_documentation.into(), + enclosing_symbol: enclosing_symbol.unwrap_or_default(), }; symbols.push(symbol_info) @@ -228,14 +250,36 @@ fn new_descriptor(name: &str, suffix: scip_types::descriptor::Suffix) -> scip_ty } } -/// Loosely based on `def_to_moniker` -/// -/// Only returns a Symbol when it's a non-local symbol. -/// So if the visibility isn't outside of a document, then it will return None -fn token_to_symbol(token: &TokenStaticData) -> Option { - use scip_types::descriptor::Suffix::*; +fn symbol_kind(kind: SymbolInformationKind) -> scip_types::symbol_information::Kind { + use scip_types::symbol_information::Kind as ScipKind; + match kind { + SymbolInformationKind::AssociatedType => ScipKind::AssociatedType, + SymbolInformationKind::Attribute => ScipKind::Attribute, + SymbolInformationKind::Constant => ScipKind::Constant, + SymbolInformationKind::Enum => ScipKind::Enum, + SymbolInformationKind::EnumMember => ScipKind::EnumMember, + SymbolInformationKind::Field => ScipKind::Field, + SymbolInformationKind::Function => ScipKind::Function, + SymbolInformationKind::Macro => ScipKind::Macro, + SymbolInformationKind::Method => ScipKind::Method, + SymbolInformationKind::Module => ScipKind::Module, + SymbolInformationKind::Parameter => ScipKind::Parameter, + SymbolInformationKind::SelfParameter => ScipKind::SelfParameter, + SymbolInformationKind::StaticMethod => ScipKind::StaticMethod, + SymbolInformationKind::StaticVariable => ScipKind::StaticVariable, + SymbolInformationKind::Struct => ScipKind::Struct, + SymbolInformationKind::Trait => ScipKind::Trait, + SymbolInformationKind::TraitMethod => ScipKind::TraitMethod, + SymbolInformationKind::Type => ScipKind::Type, + SymbolInformationKind::TypeAlias => ScipKind::TypeAlias, + SymbolInformationKind::TypeParameter => ScipKind::TypeParameter, + SymbolInformationKind::Union => ScipKind::Union, + SymbolInformationKind::Variable => ScipKind::Variable, + } +} - let moniker = token.moniker.as_ref()?; +fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol { + use scip_types::descriptor::Suffix::*; let package_name = moniker.package_information.name.clone(); let version = moniker.package_information.version.clone(); @@ -260,7 +304,7 @@ fn token_to_symbol(token: &TokenStaticData) -> Option { }) .collect(); - Some(scip_types::Symbol { + scip_types::Symbol { scheme: "rust-analyzer".into(), package: Some(scip_types::Package { manager: "cargo".to_string(), @@ -271,7 +315,7 @@ fn token_to_symbol(token: &TokenStaticData) -> Option { .into(), descriptors, special_fields: Default::default(), - }) + } } #[cfg(test)] @@ -309,7 +353,7 @@ mod test { for &(range, id) in &file.tokens { if range.contains(offset - TextSize::from(1)) { let token = si.tokens.get(id).unwrap(); - found_symbol = token_to_symbol(token); + found_symbol = token.moniker.as_ref().map(moniker_to_symbol); break; } } @@ -359,6 +403,21 @@ pub mod module { ); } + #[test] + fn symbol_for_trait_alias() { + check_symbol( + r#" +//- /foo/lib.rs crate:foo@0.1.0,https://a.b/foo.git library +#![feature(trait_alias)] +pub mod module { + pub trait MyTrait {} + pub trait MyTraitAlias$0 = MyTrait; +} +"#, + "rust-analyzer cargo foo 0.1.0 module/MyTraitAlias#", + ); + } + #[test] fn symbol_for_trait_constant() { check_symbol( @@ -525,4 +584,15 @@ pub mod example_mod { "rust-analyzer cargo main . foo/Bar#", ); } + + #[test] + fn symbol_for_for_type_alias() { + check_symbol( + r#" + //- /lib.rs crate:main + pub type MyTypeAlias$0 = u8; + "#, + "rust-analyzer cargo main . MyTypeAlias#", + ); + } } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 88fb3708449f..fe009f82a71f 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -399,6 +399,8 @@ config_data! { /// Whether to show function parameter name inlay hints at the call /// site. inlayHints_parameterHints_enable: bool = "true", + /// Whether to show exclusive range inlay hints. + inlayHints_rangeExclusiveHints_enable: bool = "false", /// Whether to show inlay hints for compiler inserted reborrows. /// This setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#. inlayHints_reborrowHints_enable: ReborrowHintsDef = "\"never\"", @@ -1464,6 +1466,7 @@ impl Config { } else { None }, + range_exclusive_hints: self.data.inlayHints_rangeExclusiveHints_enable, fields_to_resolve: InlayFieldsToResolve { resolve_text_edits: client_capability_fields.contains("textEdits"), resolve_hint_tooltip: client_capability_fields.contains("tooltip"), diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index f1317ce2b401..13544558c50c 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -458,7 +458,6 @@ pub(crate) fn handle_workspace_symbol( let config = snap.config.workspace_symbol(); let (all_symbols, libs) = decide_search_scope_and_kind(¶ms, &config); - let limit = config.search_limit; let query = { let query: String = params.query.chars().filter(|&c| c != '#' && c != '*').collect(); @@ -469,14 +468,11 @@ pub(crate) fn handle_workspace_symbol( if libs { q.libs(); } - q.limit(limit); q }; - let mut res = exec_query(&snap, query)?; + let mut res = exec_query(&snap, query, config.search_limit)?; if res.is_empty() && !all_symbols { - let mut query = Query::new(params.query); - query.limit(limit); - res = exec_query(&snap, query)?; + res = exec_query(&snap, Query::new(params.query), config.search_limit)?; } return Ok(Some(lsp_types::WorkspaceSymbolResponse::Nested(res))); @@ -519,9 +515,10 @@ pub(crate) fn handle_workspace_symbol( fn exec_query( snap: &GlobalStateSnapshot, query: Query, + limit: usize, ) -> anyhow::Result> { let mut res = Vec::new(); - for nav in snap.analysis.symbol_search(query)? { + for nav in snap.analysis.symbol_search(query, limit)? { let container_name = nav.container_name.as_ref().map(|v| v.to_string()); let info = lsp_types::WorkspaceSymbol { diff --git a/crates/span/Cargo.toml b/crates/span/Cargo.toml index 69b88b5a17b5..a4abba29bb97 100644 --- a/crates/span/Cargo.toml +++ b/crates/span/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "span" version = "0.0.0" +description = "TBD" + rust-version.workspace = true edition.workspace = true license.workspace = true @@ -18,4 +20,4 @@ syntax.workspace = true stdx.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 71e269f74bc7..43909fff02cb 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -59,6 +59,17 @@ impl TupleExt for (T, U) { } } +impl TupleExt for (T, U, V) { + type Head = T; + type Tail = V; + fn head(self) -> Self::Head { + self.0 + } + fn tail(self) -> Self::Tail { + self.2 + } +} + pub fn to_lower_snake_case(s: &str) -> String { to_snake_case(s, char::to_lowercase) } diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 1e691befff62..cc90d2dd1d55 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -136,6 +136,16 @@ where { } +/// Trait to describe operations common to both `RangeExpr` and `RangePat`. +pub trait RangeItem { + type Bound; + + fn start(&self) -> Option; + fn end(&self) -> Option; + fn op_kind(&self) -> Option; + fn op_token(&self) -> Option; +} + mod support { use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken}; diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 4c2878f49f0e..aa56f10d6095 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -293,13 +293,12 @@ impl ast::GenericParamList { } /// Removes the corresponding generic arg - pub fn remove_generic_arg(&self, generic_arg: &ast::GenericArg) -> Option { + pub fn remove_generic_arg(&self, generic_arg: &ast::GenericArg) { let param_to_remove = self.find_generic_arg(generic_arg); if let Some(param) = ¶m_to_remove { self.remove_generic_param(param.clone()); } - param_to_remove } /// Constructs a matching [`ast::GenericArgList`] diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs index 36980b146ef5..18a56e2823ab 100644 --- a/crates/syntax/src/ast/expr_ext.rs +++ b/crates/syntax/src/ast/expr_ext.rs @@ -13,6 +13,8 @@ use crate::{ SyntaxNode, SyntaxToken, T, }; +use super::RangeItem; + impl ast::HasAttrs for ast::Expr {} impl ast::Expr { @@ -227,16 +229,12 @@ impl ast::RangeExpr { Some((ix, token, bin_op)) }) } +} - pub fn op_kind(&self) -> Option { - self.op_details().map(|t| t.2) - } +impl RangeItem for ast::RangeExpr { + type Bound = ast::Expr; - pub fn op_token(&self) -> Option { - self.op_details().map(|t| t.1) - } - - pub fn start(&self) -> Option { + fn start(&self) -> Option { let op_ix = self.op_details()?.0; self.syntax() .children_with_tokens() @@ -244,13 +242,21 @@ impl ast::RangeExpr { .find_map(|it| ast::Expr::cast(it.into_node()?)) } - pub fn end(&self) -> Option { + fn end(&self) -> Option { let op_ix = self.op_details()?.0; self.syntax() .children_with_tokens() .skip(op_ix + 1) .find_map(|it| ast::Expr::cast(it.into_node()?)) } + + fn op_token(&self) -> Option { + self.op_details().map(|t| t.1) + } + + fn op_kind(&self) -> Option { + self.op_details().map(|t| t.2) + } } impl ast::IndexExpr { diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 2abbfc81f675..b1dd1fe8c829 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -263,9 +263,6 @@ pub fn impl_( ast_from_text(&format!("impl{gen_params} {path_type}{tr_gen_args}{where_clause}{{{}}}", body)) } -// FIXME : We must make *_gen_args' type ast::GenericArgList but in order to do so we must implement in `edit_in_place.rs` -// `add_generic_arg()` just like `add_generic_param()` -// is implemented for `ast::GenericParamList` pub fn impl_trait( is_unsafe: bool, trait_gen_params: Option, diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index a7e4899fb7ee..8618018c0b6a 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -14,6 +14,8 @@ use crate::{ ted, NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T, }; +use super::{RangeItem, RangeOp}; + impl ast::Lifetime { pub fn text(&self) -> TokenText<'_> { text_of_first_token(self.syntax()) @@ -875,8 +877,10 @@ impl ast::Module { } } -impl ast::RangePat { - pub fn start(&self) -> Option { +impl RangeItem for ast::RangePat { + type Bound = ast::Pat; + + fn start(&self) -> Option { self.syntax() .children_with_tokens() .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=])) @@ -884,13 +888,37 @@ impl ast::RangePat { .find_map(ast::Pat::cast) } - pub fn end(&self) -> Option { + fn end(&self) -> Option { self.syntax() .children_with_tokens() .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=])) .filter_map(|it| it.into_node()) .find_map(ast::Pat::cast) } + + fn op_token(&self) -> Option { + self.syntax().children_with_tokens().find_map(|it| { + let token = it.into_token()?; + + match token.kind() { + T![..] => Some(token), + T![..=] => Some(token), + _ => None, + } + }) + } + + fn op_kind(&self) -> Option { + self.syntax().children_with_tokens().find_map(|it| { + let token = it.into_token()?; + + match token.kind() { + T![..] => Some(RangeOp::Exclusive), + T![..=] => Some(RangeOp::Inclusive), + _ => None, + } + }) + } } impl ast::TokenTree { diff --git a/crates/syntax/src/ast/prec.rs b/crates/syntax/src/ast/prec.rs index 8e04ab8bedcb..9ddf5a0a9804 100644 --- a/crates/syntax/src/ast/prec.rs +++ b/crates/syntax/src/ast/prec.rs @@ -1,7 +1,7 @@ //! Precedence representation. use crate::{ - ast::{self, BinaryOp, Expr, HasArgList}, + ast::{self, BinaryOp, Expr, HasArgList, RangeItem}, match_ast, AstNode, SyntaxNode, }; diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 2b1bbac08e52..eabbda2c3983 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -9,7 +9,7 @@ use rustc_dependencies::lexer::unescape::{self, unescape_literal, Mode}; use crate::{ algo, - ast::{self, HasAttrs, HasVisibility, IsString}, + ast::{self, HasAttrs, HasVisibility, IsString, RangeItem}, match_ast, AstNode, SyntaxError, SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS}, SyntaxNode, SyntaxToken, TextSize, T, diff --git a/docs/dev/guide.md b/docs/dev/guide.md index a5f1811bf24a..bb77aa0eaaef 100644 --- a/docs/dev/guide.md +++ b/docs/dev/guide.md @@ -2,13 +2,15 @@ ## About the guide -This guide describes the current state of rust-analyzer as of 2019-01-20 (git -tag [guide-2019-01]). Its purpose is to document various problems and +This guide describes the current state of rust-analyzer as of the 2024-01-01 release +(git tag [2024-01-01]). Its purpose is to document various problems and architectural solutions related to the problem of building IDE-first compiler -for Rust. There is a video version of this guide as well: +for Rust. There is a video version of this guide as well - +however, it's based on an older 2019-01-20 release (git tag [guide-2019-01]): https://youtu.be/ANKBNiSWyfc. [guide-2019-01]: https://github.com/rust-lang/rust-analyzer/tree/guide-2019-01 +[2024-01-01]: https://github.com/rust-lang/rust-analyzer/tree/2024-01-01 ## The big picture @@ -40,8 +42,8 @@ terms of files and offsets, and **not** in terms of Rust concepts like structs, traits, etc. The "typed" API with Rust specific types is slightly lower in the stack, we'll talk about it later. -[`AnalysisHost`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L265-L284 -[`Analysis`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L291-L478 +[`AnalysisHost`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide/src/lib.rs#L161-L213 +[`Analysis`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide/src/lib.rs#L220-L761 The reason for this separation of `Analysis` and `AnalysisHost` is that we want to apply changes "uniquely", but we might also want to fork an `Analysis` and send it to @@ -65,18 +67,23 @@ Next, let's talk about what the inputs to the `Analysis` are, precisely. rust-analyzer never does any I/O itself, all inputs get passed explicitly via the `AnalysisHost::apply_change` method, which accepts a single argument, a -`Change`. [`Change`] is a builder for a single change -"transaction", so it suffices to study its methods to understand all of the -input data. +`Change`. [`Change`] is a wrapper for `FileChange` that adds proc-macro knowledge. +[`FileChange`] is a builder for a single change "transaction", so it suffices +to study its methods to understand all the input data. -[`Change`]: https://github.com/rust-lang/rust-analyzer/blob/master/crates/base_db/src/change.rs#L14-L89 +[`Change`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-expand/src/change.rs#L10-L42 +[`FileChange`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/base-db/src/change.rs#L14-L78 -The `(add|change|remove)_file` methods control the set of the input files, where -each file has an integer id (`FileId`, picked by the client), text (`String`) -and a filesystem path. Paths are tricky; they'll be explained below, in source roots -section, together with the `add_root` method. The `add_library` method allows us to add a -group of files which are assumed to rarely change. It's mostly an optimization -and does not change the fundamental picture. +The `change_file` method controls the set of the input files, where each file +has an integer id (`FileId`, picked by the client) and text (`Option>`). +Paths are tricky; they'll be explained below, in source roots section, +together with the `set_roots` method. The "source root" [`is_library`] flag +along with the concept of [`durability`] allows us to add a group of files which +are assumed to rarely change. It's mostly an optimization and does not change +the fundamental picture. + +[`is_library`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/base-db/src/input.rs#L38 +[`durability`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/base-db/src/change.rs#L80-L86 The `set_crate_graph` method allows us to control how the input files are partitioned into compilation units -- crates. It also controls (in theory, not implemented @@ -118,7 +125,7 @@ can have `#[path="/dev/random"] mod foo;`. To solve (or explicitly refuse to solve) these problems rust-analyzer uses the concept of a "source root". Roughly speaking, source roots are the contents of a -directory on a file systems, like `/home/matklad/projects/rustraytracer/**.rs`. +directory on a file system, like `/home/matklad/projects/rustraytracer/**.rs`. More precisely, all files (`FileId`s) are partitioned into disjoint `SourceRoot`s. Each file has a relative UTF-8 path within the `SourceRoot`. @@ -134,49 +141,53 @@ the source root, even `/dev/random`. ## Language Server Protocol -Now let's see how the `Analysis` API is exposed via the JSON RPC based language server protocol. The -hard part here is managing changes (which can come either from the file system +Now let's see how the `Analysis` API is exposed via the JSON RPC based language server protocol. +The hard part here is managing changes (which can come either from the file system or from the editor) and concurrency (we want to spawn background jobs for things like syntax highlighting). We use the event loop pattern to manage the zoo, and -the loop is the [`main_loop_inner`] function. The [`main_loop`] does a one-time -initialization and tearing down of the resources. +the loop is the [`GlobalState::run`] function initiated by [`main_loop`] after +[`GlobalState::new`] does a one-time initialization and tearing down of the resources. -[`main_loop`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L51-L110 -[`main_loop_inner`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L156-L258 +[`main_loop`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/main_loop.rs#L31-L54 +[`GlobalState::new`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/global_state.rs#L148-L215 +[`GlobalState::run`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/main_loop.rs#L114-L140 Let's walk through a typical analyzer session! First, we need to figure out what to analyze. To do this, we run `cargo metadata` to learn about Cargo packages for current workspace and dependencies, -and we run `rustc --print sysroot` and scan the "sysroot" (the directory containing the current Rust toolchain's files) to learn about crates like -`std`. Currently we load this configuration once at the start of the server, but -it should be possible to dynamically reconfigure it later without restart. +and we run `rustc --print sysroot` and scan the "sysroot" +(the directory containing the current Rust toolchain's files) to learn about crates +like `std`. This happens in the [`GlobalState::fetch_workspaces`] method. +We load this configuration at the start of the server in [`GlobalState::new`], +but it's also triggered by workspace change events and requests to reload the +workspace from the client. -[main_loop.rs#L62-L70](https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L62-L70) +[`GlobalState::fetch_workspaces`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/reload.rs#L186-L257 The [`ProjectModel`] we get after this step is very Cargo and sysroot specific, -it needs to be lowered to get the input in the form of `Change`. This -happens in [`ServerWorldState::new`] method. Specifically +it needs to be lowered to get the input in the form of `Change`. This happens +in [`GlobalState::process_changes`] method. Specifically -* Create a `SourceRoot` for each Cargo package and sysroot. +* Create `SourceRoot`s for each Cargo package(s) and sysroot. * Schedule a filesystem scan of the roots. * Create an analyzer's `Crate` for each Cargo **target** and sysroot crate. * Setup dependencies between the crates. -[`ProjectModel`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/project_model.rs#L16-L20 -[`ServerWorldState::new`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/server_world.rs#L38-L160 +[`ProjectModel`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/project-model/src/workspace.rs#L57-L100 +[`GlobalState::process_changes`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/global_state.rs#L217-L356 The results of the scan (which may take a while) will be processed in the body of the main loop, just like any other change. Here's where we handle: -* [File system changes](https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L194) -* [Changes from the editor](https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L377) +* [File system changes](https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/main_loop.rs#L273) +* [Changes from the editor](https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/main_loop.rs#L801-L803) After a single loop's turn, we group the changes into one `Change` and [apply] it. This always happens on the main thread and blocks the loop. -[apply]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/server_world.rs#L216 +[apply]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/global_state.rs#L333 To handle requests, like ["goto definition"], we create an instance of the `Analysis` and [`schedule`] the task (which consumes `Analysis`) on the @@ -186,9 +197,9 @@ executing "goto definition" on the threadpool and a new change comes in, the task will be canceled as soon as the main loop calls `apply_change` on the `AnalysisHost`. -["goto definition"]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/server_world.rs#L216 -[`schedule`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L426-L455 -[The task]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop/handlers.rs#L205-L223 +["goto definition"]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/main_loop.rs#L767 +[`schedule`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/dispatch.rs#L138 +[The task]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/handlers/request.rs#L610-L623 This concludes the overview of the analyzer's programing *interface*. Next, let's dig into the implementation! @@ -247,16 +258,17 @@ confusing. This illustration by @killercup might help: ## Salsa Input Queries All analyzer information is stored in a salsa database. `Analysis` and -`AnalysisHost` types are newtype wrappers for [`RootDatabase`] -- a salsa -database. +`AnalysisHost` types are essentially newtype wrappers for [`RootDatabase`] +-- a salsa database. -[`RootDatabase`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/db.rs#L88-L134 +[`RootDatabase`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-db/src/lib.rs#L69-L324 -Salsa input queries are defined in [`FilesDatabase`] (which is a part of -`RootDatabase`). They closely mirror the familiar `Change` structure: -indeed, what `apply_change` does is it sets the values of input queries. +Salsa input queries are defined in [`SourceDatabase`] and [`SourceDatabaseExt`] +(which are a part of `RootDatabase`). They closely mirror the familiar `Change` +structure: indeed, what `apply_change` does is it sets the values of input queries. -[`FilesDatabase`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/base_db/src/input.rs#L150-L174 +[`SourceDatabase`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/base-db/src/lib.rs#L58-L65 +[`SourceDatabaseExt`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/base-db/src/lib.rs#L76-L88 ## From text to semantic model @@ -270,18 +282,18 @@ functions: for example, the same source file might get included as a module in several crates or a single crate might be present in the compilation DAG several times, with different sets of `cfg`s enabled. The IDE-specific task of mapping source code into a semantic model is inherently imprecise for -this reason and gets handled by the [`source_binder`]. +this reason and gets handled by the [`source_analyzer`]. -[`source_binder`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/source_binder.rs +[`source_analyzer`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir/src/source_analyzer.rs -The semantic interface is declared in the [`code_model_api`] module. Each entity is +The semantic interface is declared in the [`semantics`] module. Each entity is identified by an integer ID and has a bunch of methods which take a salsa database as an argument and returns other entities (which are also IDs). Internally, these methods invoke various queries on the database to build the model on demand. Here's [the list of queries]. -[`code_model_api`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/code_model_api.rs -[the list of queries]: https://github.com/rust-lang/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/ra_hir/src/db.rs#L20-L106 +[`semantics`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir/src/semantics.rs +[the list of queries]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-ty/src/db.rs#L29-L275 The first step of building the model is parsing the source code. @@ -327,7 +339,7 @@ The implementation is based on the generic [rowan] crate on top of which a [libsyntax]: https://github.com/apple/swift/tree/5e2c815edfd758f9b1309ce07bfc01c4bc20ec23/lib/Syntax [rowan]: https://github.com/rust-analyzer/rowan/tree/100a36dc820eb393b74abe0d20ddf99077b61f88 -[rust-specific]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_syntax/src/ast/generated.rs +[rust-specific]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/syntax/src/ast/generated.rs The next step in constructing the semantic model is ... @@ -336,9 +348,9 @@ The next step in constructing the semantic model is ... The algorithm for building a tree of modules is to start with a crate root (remember, each `Crate` from a `CrateGraph` has a `FileId`), collect all `mod` declarations and recursively process child modules. This is handled by the -[`module_tree_query`], with two slight variations. +[`crate_def_map_query`], with two slight variations. -[`module_tree_query`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L115-L133 +[`crate_def_map_query`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/nameres.rs#L307-L324 First, rust-analyzer builds a module tree for all crates in a source root simultaneously. The main reason for this is historical (`module_tree` predates @@ -347,21 +359,21 @@ part of any crate. That is, if you create a file but do not include it as a submodule anywhere, you still get semantic completion, and you get a warning about a free-floating module (the actual warning is not implemented yet). -The second difference is that `module_tree_query` does not *directly* depend on -the "parse" query (which is confusingly called `source_file`). Why would calling -the parse directly be bad? Suppose the user changes the file slightly, by adding -an insignificant whitespace. Adding whitespace changes the parse tree (because -it includes whitespace), and that means recomputing the whole module tree. +The second difference is that `crate_def_map_query` does not *directly* depend on +the `SourceDatabase::parse` query. Why would calling the parse directly be bad? +Suppose the user changes the file slightly, by adding an insignificant whitespace. +Adding whitespace changes the parse tree (because it includes whitespace), +and that means recomputing the whole module tree. -We deal with this problem by introducing an intermediate [`submodules_query`]. +We deal with this problem by introducing an intermediate [`block_def_map_query`]. This query processes the syntax tree and extracts a set of declared submodule -names. Now, changing the whitespace results in `submodules_query` being +names. Now, changing the whitespace results in `block_def_map_query` being re-executed for a *single* module, but because the result of this query stays -the same, we don't have to re-execute [`module_tree_query`]. In fact, we only +the same, we don't have to re-execute [`crate_def_map_query`]. In fact, we only need to re-execute it when we add/remove new files or when we change mod declarations. -[`submodules_query`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L41 +[`block_def_map_query`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/nameres.rs#L326-L354 We store the resulting modules in a `Vec`-based indexed arena. The indices in the arena becomes module IDs. And this brings us to the next topic: @@ -383,20 +395,23 @@ change the location. However, such "ID" types ceases to be a `Copy`able integer general can become pretty large if we account for nesting (for example: "third parameter of the `foo` function of the `bar` `impl` in the `baz` module"). -[`LocationInterner`] allows us to combine the benefits of positional and numeric -IDs. It is a bidirectional append-only map between locations and consecutive -integers which can "intern" a location and return an integer ID back. The salsa -database we use includes a couple of [interners]. How to "garbage collect" -unused locations is an open question. +[`Intern` and `Lookup`] traits allows us to combine the benefits of positional and numeric +IDs. Implementing both traits effectively creates a bidirectional append-only map +between locations and integer IDs (typically newtype wrappers for [`salsa::InternId`]) +which can "intern" a location and return an integer ID back. The salsa database we use +includes a couple of [interners]. How to "garbage collect" unused locations +is an open question. -[`LocationInterner`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/loc2id.rs#L65-L71 -[interners]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/db.rs#L22-L23 +[`Intern` and `Lookup`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-expand/src/lib.rs#L96-L106 +[interners]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-expand/src/lib.rs#L108-L122 +[`salsa::InternId`]: https://docs.rs/salsa/0.16.1/salsa/struct.InternId.html -For example, we use `LocationInterner` to assign IDs to definitions of functions, -structs, enums, etc. The location, [`DefLoc`] contains two bits of information: +For example, we use `Intern` and `Lookup` implementations to assign IDs to +definitions of functions, structs, enums, etc. The location, [`ItemLoc`] contains +two bits of information: * the ID of the module which contains the definition, -* the ID of the specific item in the modules source code. +* the ID of the specific item in the module's source code. We "could" use a text offset for the location of a particular item, but that would play badly with salsa: offsets change after edits. So, as a rule of thumb, we avoid @@ -404,7 +419,7 @@ using offsets, text ranges or syntax trees as keys and values for queries. What we do instead is we store "index" of the item among all of the items of a file (so, a positional based ID, but localized to a single file). -[`DefLoc`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L129-L139 +[`ItemLoc`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/lib.rs#L209-L212 One thing we've glossed over for the time being is support for macros. We have only proof of concept handling of macros at the moment, but they are extremely @@ -424,20 +439,21 @@ enum HirFileId { } ``` -`MacroCallId` is an interned ID that specifies a particular macro invocation. -Its `MacroCallLoc` contains: +`MacroCallId` is an interned ID that identifies a particular macro invocation. +Simplifying, it's a `HirFileId` of a file containing the call plus the offset +of the macro call in the file. -* `ModuleId` of the containing module -* `HirFileId` of the containing file or pseudo file -* an index of this particular macro invocation in this file (positional id - again). - -Note how `HirFileId` is defined in terms of `MacroCallLoc` which is defined in +Note how `HirFileId` is defined in terms of `MacroCallId` which is defined in terms of `HirFileId`! This does not recur infinitely though: any chain of `HirFileId`s bottoms out in `HirFileId::FileId`, that is, some source file actually written by the user. -[`HirFileId`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L31-L93 +Note also that in the actual implementation, the two variants are encoded in +a single `u32`, which are differentiated by the MSB (most significant bit). +If the MSB is 0, the value represents a `FileId`, otherwise the remaining +31 bits represent a `MacroCallId`. + +[`HirFileId`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/span/src/lib.rs#L148-L160 Now that we understand how to identify a definition, in a source or in a macro-generated file, we can discuss name resolution a bit. @@ -451,13 +467,13 @@ each module into a position-independent representation which does not change if we modify bodies of the items. After that we [loop] resolving all imports until we've reached a fixed point. -[lower]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L147 -[loop]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres.rs#L186-L196 +[lower]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/item_tree.rs#L110-L154 +[loop]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/nameres/collector.rs#L404-L437 And, given all our preparation with IDs and a position-independent representation, it is satisfying to [test] that typing inside function body does not invalidate name resolution results. -[test]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/tests.rs#L376 +[test]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/nameres/tests/incremental.rs#L31 An interesting fact about name resolution is that it "erases" all of the intermediate paths from the imports: in the end, we know which items are defined @@ -481,21 +497,18 @@ store the syntax node as a part of name resolution: this will break incrementality, due to the fact that syntax changes after every file modification. -We solve this problem during the lowering step of name resolution. The lowering -query actually produces a *pair* of outputs: `LoweredModule` and [`SourceMap`]. -The `LoweredModule` module contains [imports], but in a position-independent form. -The `SourceMap` contains a mapping from position-independent imports to -(position-dependent) syntax nodes. +We solve this problem during the lowering step of name resolution. Along with +the [`ItemTree`] output, the lowering query additionally produces an [`AstIdMap`] +via an [`ast_id_map`] query. The `ItemTree` contains [imports], but in a +position-independent form based on [`AstId`]. The `AstIdMap` contains a mapping +from position-independent `AstId`s to (position-dependent) syntax nodes. -The result of this basic lowering query changes after every modification. But -there's an intermediate [projection query] which returns only the first -position-independent part of the lowering. The result of this query is stable. -Naturally, name resolution [uses] this stable projection query. +[`ItemTree`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/item_tree.rs +[`AstIdMap`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-expand/src/ast_id_map.rs#L136-L142 +[`ast_id_map`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/item_tree/lower.rs#L32 +[imports]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/item_tree.rs#L559-L563 +[`AstId`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-expand/src/ast_id_map.rs#L29 -[imports]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 -[`SourceMap`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 -[projection query]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L97-L103 -[uses]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/query_definitions.rs#L49 ## Type inference @@ -517,10 +530,10 @@ construct a mapping from `ExprId`s to types. [@flodiebold]: https://github.com/flodiebold [#327]: https://github.com/rust-lang/rust-analyzer/pull/327 -[lower the AST]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs -[positional ID]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L13-L15 -[a source map]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L41-L44 -[type inference]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ty.rs#L1208-L1223 +[lower the AST]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/body.rs +[positional ID]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/hir.rs#L37 +[a source map]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-def/src/body.rs#L84-L88 +[type inference]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/hir-ty/src/infer.rs#L76-L131 ## Tying it all together: completion @@ -537,36 +550,38 @@ types (by converting a file url into a numeric `FileId`), [ask analysis for completion] and serialize results into the LSP. The [completion implementation] is finally the place where we start doing the actual -work. The first step is to collect the `CompletionContext` -- a struct which +work. The first step is to collect the [`CompletionContext`] -- a struct which describes the cursor position in terms of Rust syntax and semantics. For -example, `function_syntax: Option<&'a ast::FnDef>` stores a reference to -the enclosing function *syntax*, while `function: Option` is the -`Def` for this function. +example, `expected_name: Option` is the syntactic representation +for the expected name of what we're completing (usually the parameter name of +a function argument), while `expected_type: Option` is the semantic model +for the expected type of what we're completing. To construct the context, we first do an ["IntelliJ Trick"]: we insert a dummy identifier at the cursor's position and parse this modified file, to get a reasonably looking syntax tree. Then we do a bunch of "classification" routines -to figure out the context. For example, we [find an ancestor `fn` node] and we get a -[semantic model] for it (using the lossy `source_binder` infrastructure). +to figure out the context. For example, we [find an parent `fn` node], get a +[semantic model] for it (using the lossy `source_analyzer` infrastructure) +and use it to determine the [expected type at the cursor position]. The second step is to run a [series of independent completion routines]. Let's take a closer look at [`complete_dot`], which completes fields and methods in -`foo.bar|`. First we extract a semantic function and a syntactic receiver -expression out of the `Context`. Then we run type-inference for this single -function and map our syntactic expression to `ExprId`. Using the ID, we figure -out the type of the receiver expression. Then we add all fields & methods from -the type to completion. +`foo.bar|`. First we extract a semantic receiver type out of the `DotAccess` +argument. Then, using the semantic model for the type, we determine if the +receiver implements the `Future` trait, and add a `.await` completion item in +the affirmative case. Finally, we add all fields & methods from the type to +completion. -[receiving a message]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L203 -[schedule it on the threadpool]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L428 -[catch]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L436-L442 -[the handler]: https://salsa.zulipchat.com/#narrow/stream/181542-rfcs.2Fsalsa-query-group/topic/design.20next.20steps -[ask analysis for completion]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L439-L444 -[ask analysis for completion]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L439-L444 -[completion implementation]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion.rs#L46-L62 -[`CompletionContext`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L14-L37 -["IntelliJ Trick"]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L72-L75 -[find an ancestor `fn` node]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L116-L120 -[semantic model]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L123 -[series of independent completion routines]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion.rs#L52-L59 -[`complete_dot`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/complete_dot.rs#L6-L22 +[receiving a message]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/main_loop.rs#L213 +[schedule it on the threadpool]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/dispatch.rs#L197-L211 +[catch]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/dispatch.rs#L292 +[the handler]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/rust-analyzer/src/handlers/request.rs#L850-L876 +[ask analysis for completion]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide/src/lib.rs#L605-L615 +[completion implementation]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/lib.rs#L148-L229 +[`CompletionContext`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/context.rs#L407-L441 +["IntelliJ Trick"]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/context.rs#L644-L648 +[find an parent `fn` node]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/context/analysis.rs#L463 +[semantic model]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/context/analysis.rs#L466 +[expected type at the cursor position]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/context/analysis.rs#L467 +[series of independent completion routines]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/lib.rs#L157-L226 +[`complete_dot`]: https://github.com/rust-lang/rust-analyzer/blob/2024-01-01/crates/ide-completion/src/completions/dot.rs#L11-L41 diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index c3f249e0ce2c..ecc90abff135 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -596,6 +596,11 @@ Maximum length for inlay hints. Set to null to have an unlimited length. Whether to show function parameter name inlay hints at the call site. -- +[[rust-analyzer.inlayHints.rangeExclusiveHints.enable]]rust-analyzer.inlayHints.rangeExclusiveHints.enable (default: `false`):: ++ +-- +Whether to show exclusive range inlay hints. +-- [[rust-analyzer.inlayHints.reborrowHints.enable]]rust-analyzer.inlayHints.reborrowHints.enable (default: `"never"`):: + -- diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 9fc19a7d0745..fa8413c19ae0 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc @@ -186,18 +186,13 @@ $ pacman -S rust-analyzer ==== Gentoo Linux -`rust-analyzer` is available in the GURU repository: +There are two ways to install `rust-analyzer` under Gentoo: -- https://gitweb.gentoo.org/repo/proj/guru.git/tree/dev-util/rust-analyzer?id=9895cea62602cfe599bd48e0fb02127411ca6e81[`dev-util/rust-analyzer`] builds from source -- https://gitweb.gentoo.org/repo/proj/guru.git/tree/dev-util/rust-analyzer-bin?id=9895cea62602cfe599bd48e0fb02127411ca6e81[`dev-util/rust-analyzer-bin`] installs an official binary release +- when installing `dev-lang/rust` or `dev-lang/rust-bin`, enable the `rust-analyzer` and `rust-src` USE flags +- use the `rust-analyzer` component in `rustup` (see instructions above) -If not already, GURU must be enabled (e.g. using `app-eselect/eselect-repository`) and sync'd before running `emerge`: - -[source,bash] ----- -$ eselect repository enable guru && emaint sync -r guru -$ emerge rust-analyzer-bin ----- +Note that in both cases, the version installed lags for a couple of months behind the official releases on GitHub. +To obtain a newer one, you can download a binary from GitHub Releases or building from source. ==== macOS diff --git a/editors/code/package.json b/editors/code/package.json index 27ed8ac502b5..8307f6833e6f 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1308,6 +1308,11 @@ "default": true, "type": "boolean" }, + "rust-analyzer.inlayHints.rangeExclusiveHints.enable": { + "markdownDescription": "Whether to show exclusive range inlay hints.", + "default": false, + "type": "boolean" + }, "rust-analyzer.inlayHints.reborrowHints.enable": { "markdownDescription": "Whether to show inlay hints for compiler inserted reborrows.\nThis setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.", "default": "never", diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 987d936943a1..51a0aece820e 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -5,6 +5,7 @@ import * as vscode from "vscode"; import type { Env } from "./client"; import { log } from "./util"; import { expectNotUndefined, unwrapUndefinable } from "./undefinable"; +import type { JsonProject } from "./rust_project"; export type RunnableEnvCfgItem = { mask?: string; diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 63ae386c8ad1..55163241c2ac 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -23,6 +23,7 @@ import { execRevealDependency } from "./commands"; import { PersistentState } from "./persistent_state"; import { bootstrap } from "./bootstrap"; import type { RustAnalyzerExtensionApi } from "./main"; +import type { JsonProject } from "./rust_project"; // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // only those are in use. We use "Empty" to represent these scenarios diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 3073353674ce..599cfb4ff77a 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -6,6 +6,7 @@ import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx"; import * as diagnostics from "./diagnostics"; import { activateTaskProvider } from "./tasks"; import { setContextValue } from "./util"; +import type { JsonProject } from "./rust_project"; const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; diff --git a/editors/code/src/rust_project.ts b/editors/code/src/rust_project.ts index 187a1a96c10c..bf65ad43ba59 100644 --- a/editors/code/src/rust_project.ts +++ b/editors/code/src/rust_project.ts @@ -1,4 +1,4 @@ -interface JsonProject { +export interface JsonProject { /// Path to the directory with *source code* of /// sysroot crates. /// @@ -21,7 +21,7 @@ interface JsonProject { crates: Crate[]; } -interface Crate { +export interface Crate { /// Optional crate name used for display purposes, /// without affecting semantics. See the `deps` /// key for semantically-significant crate names. @@ -82,7 +82,7 @@ interface Crate { proc_macro_dylib_path?: string; } -interface Dep { +export interface Dep { /// Index of a crate in the `crates` array. crate: number; /// Name as should appear in the (implicit) diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index c74284a00d96..87cfd1b2ee11 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -2,7 +2,7 @@ "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "esModuleInterop": false, - "module": "CommonJS", + "module": "Node16", "moduleResolution": "Node16", "target": "ES2021", "outDir": "out", diff --git a/lib/line-index/README.md b/lib/line-index/README.md new file mode 100644 index 000000000000..93ac03696a0d --- /dev/null +++ b/lib/line-index/README.md @@ -0,0 +1,30 @@ +# line-index + +This crate is developed as part of `rust-analyzer`. + +line-index is a library to convert between text offsets and corresponding line/column coordinates. + +## Installation + +To add this crate to a project simply run `cargo add line-index`. + +## Usage + +The main structure is `LineIndex`. + +It is constructed with an UTF-8 string, but also supports UTF-16 and UTF-32 offsets. + +### Example + +```rust +use line_index::LineIndex; + +let line_index = LineIndex::new("This is a\nmulti-line\ntext."); +line_index.line_col(3.into()); // LineCol { line: 0, col: 3 } +line_index.line_col(13.into()); // LineCol { line: 1, col: 3 } +line_index.offset(LineCol { line: 2, col: 3 }); // Some (24) +``` + +## SemVer + +This crate uses [semver](https://semver.org/) versioning. From 7dd9f20ce30a22f1e10e02627bf98bee7c61f176 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 10:37:09 +0100 Subject: [PATCH 052/297] Builtin derives are hygienic --- .../builtin_derive_macro.rs | 83 +++++++------ .../macro_expansion_tests/builtin_fn_macro.rs | 2 +- crates/hir-expand/src/builtin_derive_macro.rs | 114 ++++-------------- crates/hir-expand/src/builtin_fn_macro.rs | 20 ++- crates/hir-expand/src/quote.rs | 4 + crates/hir-ty/src/tests/macros.rs | 30 +++-- crates/ide/src/expand_macro.rs | 8 +- crates/test-utils/src/minicore.rs | 10 ++ 8 files changed, 112 insertions(+), 159 deletions(-) diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs index abd84c6a46de..553c0b795336 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -16,13 +16,12 @@ struct Foo; #[derive(Copy)] struct Foo; -impl < > core::marker::Copy for Foo< > where {}"#]], +impl < > $crate::marker::Copy for Foo< > where {}"#]], ); } #[test] fn test_copy_expand_in_core() { - cov_mark::check!(test_copy_expand_in_core); check( r#" //- /lib.rs crate:core @@ -41,7 +40,7 @@ macro Copy {} #[derive(Copy)] struct Foo; -impl < > crate ::marker::Copy for Foo< > where {}"#]], +impl < > $crate::marker::Copy for Foo< > where {}"#]], ); } @@ -57,7 +56,7 @@ struct Foo; #[derive(Copy)] struct Foo; -impl core::marker::Copy for Foo where {}"#]], +impl $crate::marker::Copy for Foo where {}"#]], ); } @@ -74,7 +73,7 @@ struct Foo; #[derive(Copy)] struct Foo; -impl core::marker::Copy for Foo where {}"#]], +impl $crate::marker::Copy for Foo where {}"#]], ); } @@ -98,7 +97,7 @@ enum Command { Jump, } -impl core::clone::Clone for Command where { +impl $crate::clone::Clone for Command where { fn clone(&self ) -> Self { match self { Command::Move { @@ -158,7 +157,7 @@ where generic: Vec, } -impl core::clone::Clone for Foo where T: Trait, T::InFieldShorthand: core::clone::Clone, T::InGenericArg: core::clone::Clone, { +impl $crate::clone::Clone for Foo where T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, { fn clone(&self ) -> Self { match self { Foo { @@ -186,7 +185,7 @@ struct Foo(u32); #[derive(Clone)] struct Foo(u32); -impl core::clone::Clone for Foo where { +impl $crate::clone::Clone for Foo where { fn clone(&self ) -> Self { match self { Foo(f0, )=>Foo(f0.clone(), ), @@ -226,14 +225,14 @@ enum Bar { Bar, } -impl < > core::default::Default for Foo< > where { +impl < > $crate::default::Default for Foo< > where { fn default() -> Self { Foo { - field1: core::default::Default::default(), field2: core::default::Default::default(), + field1: $crate::default::Default::default(), field2: $crate::default::Default::default(), } } } -impl < > core::default::Default for Bar< > where { +impl < > $crate::default::Default for Bar< > where { fn default() -> Self { Bar::Bar } @@ -261,7 +260,7 @@ enum Command { Jump, } -impl < > core::cmp::PartialEq for Command< > where { +impl < > $crate::cmp::PartialEq for Command< > where { fn eq(&self , other: &Self ) -> bool { match (self , other) { (Command::Move { @@ -274,7 +273,7 @@ impl < > core::cmp::PartialEq for Command< > where { } } } -impl < > core::cmp::Eq for Command< > where {}"#]], +impl < > $crate::cmp::Eq for Command< > where {}"#]], ); } @@ -299,7 +298,7 @@ enum Command { Jump, } -impl < > core::cmp::PartialEq for Command< > where { +impl < > $crate::cmp::PartialEq for Command< > where { fn eq(&self , other: &Self ) -> bool { match (self , other) { (Command::Move { @@ -312,7 +311,7 @@ impl < > core::cmp::PartialEq for Command< > where { } } } -impl < > core::cmp::Eq for Command< > where {}"#]], +impl < > $crate::cmp::Eq for Command< > where {}"#]], ); } @@ -336,10 +335,10 @@ enum Command { Jump, } -impl < > core::cmp::PartialOrd for Command< > where { - fn partial_cmp(&self , other: &Self ) -> core::option::Option::Option { - match core::intrinsics::discriminant_value(self ).partial_cmp(&core::intrinsics::discriminant_value(other)) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { +impl < > $crate::cmp::PartialOrd for Command< > where { + fn partial_cmp(&self , other: &Self ) -> $crate::option::Option::Option<$crate::cmp::Ordering> { + match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) { + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { match (self , other) { (Command::Move { x: x_self, y: y_self, @@ -348,10 +347,10 @@ impl < > core::cmp::PartialOrd for Command< > where { x: x_other, y: y_other, } )=>match x_self.partial_cmp(&x_other) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { match y_self.partial_cmp(&y_other) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { - core::option::Option::Some(core::cmp::Ordering::Equal) + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { + $crate::option::Option::Some($crate::cmp::Ordering::Equal) } c=>return c, } @@ -359,22 +358,22 @@ impl < > core::cmp::PartialOrd for Command< > where { c=>return c, } , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.partial_cmp(&f0_other) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { - core::option::Option::Some(core::cmp::Ordering::Equal) + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { + $crate::option::Option::Some($crate::cmp::Ordering::Equal) } c=>return c, } - , (Command::Jump, Command::Jump)=>core::option::Option::Some(core::cmp::Ordering::Equal), _unused=>core::option::Option::Some(core::cmp::Ordering::Equal) + , (Command::Jump, Command::Jump)=>$crate::option::Option::Some($crate::cmp::Ordering::Equal), _unused=>$crate::option::Option::Some($crate::cmp::Ordering::Equal) } } c=>return c, } } } -impl < > core::cmp::Ord for Command< > where { - fn cmp(&self , other: &Self ) -> core::cmp::Ordering { - match core::intrinsics::discriminant_value(self ).cmp(&core::intrinsics::discriminant_value(other)) { - core::cmp::Ordering::Equal=> { +impl < > $crate::cmp::Ord for Command< > where { + fn cmp(&self , other: &Self ) -> $crate::cmp::Ordering { + match $crate::intrinsics::discriminant_value(self ).cmp(&$crate::intrinsics::discriminant_value(other)) { + $crate::cmp::Ordering::Equal=> { match (self , other) { (Command::Move { x: x_self, y: y_self, @@ -383,10 +382,10 @@ impl < > core::cmp::Ord for Command< > where { x: x_other, y: y_other, } )=>match x_self.cmp(&x_other) { - core::cmp::Ordering::Equal=> { + $crate::cmp::Ordering::Equal=> { match y_self.cmp(&y_other) { - core::cmp::Ordering::Equal=> { - core::cmp::Ordering::Equal + $crate::cmp::Ordering::Equal=> { + $crate::cmp::Ordering::Equal } c=>return c, } @@ -394,12 +393,12 @@ impl < > core::cmp::Ord for Command< > where { c=>return c, } , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.cmp(&f0_other) { - core::cmp::Ordering::Equal=> { - core::cmp::Ordering::Equal + $crate::cmp::Ordering::Equal=> { + $crate::cmp::Ordering::Equal } c=>return c, } - , (Command::Jump, Command::Jump)=>core::cmp::Ordering::Equal, _unused=>core::cmp::Ordering::Equal + , (Command::Jump, Command::Jump)=>$crate::cmp::Ordering::Equal, _unused=>$crate::cmp::Ordering::Equal } } c=>return c, @@ -433,8 +432,8 @@ struct Foo { z: (i32, u64), } -impl < > core::hash::Hash for Foo< > where { - fn hash(&self , ra_expand_state: &mut H) { +impl < > $crate::hash::Hash for Foo< > where { + fn hash(&self , ra_expand_state: &mut H) { match self { Foo { x: x, y: y, z: z, @@ -471,9 +470,9 @@ enum Command { Jump, } -impl < > core::hash::Hash for Command< > where { - fn hash(&self , ra_expand_state: &mut H) { - core::mem::discriminant(self ).hash(ra_expand_state); +impl < > $crate::hash::Hash for Command< > where { + fn hash(&self , ra_expand_state: &mut H) { + $crate::mem::discriminant(self ).hash(ra_expand_state); match self { Command::Move { x: x, y: y, @@ -517,8 +516,8 @@ enum Command { Jump, } -impl < > core::fmt::Debug for Command< > where { - fn fmt(&self , f: &mut core::fmt::Formatter) -> core::fmt::Result { +impl < > $crate::fmt::Debug for Command< > where { + fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result { match self { Command::Move { x: x, y: y, diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index d4798f4507d1..4690ca5d363c 100644 --- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -136,7 +136,7 @@ fn main() { option_env!("TEST_ENV_VAR"); } #[rustc_builtin_macro] macro_rules! option_env {() => {}} -fn main() { ::core::option::Option::None:: < &str>; } +fn main() { $crate::option::Option::None:: < &str>; } "#]], ); } diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs index 8f240ef07320..46bbb7f92c07 100644 --- a/crates/hir-expand/src/builtin_derive_macro.rs +++ b/crates/hir-expand/src/builtin_derive_macro.rs @@ -1,6 +1,5 @@ //! Builtin derives. -use base_db::{CrateOrigin, LangCrateOrigin}; use itertools::izip; use rustc_hash::FxHashSet; use span::{MacroCallId, Span}; @@ -10,6 +9,7 @@ use tracing::debug; use crate::{ hygiene::span_with_def_site_ctxt, name::{AsName, Name}, + quote::dollar_crate, span_map::SpanMapRef, tt, }; @@ -38,7 +38,7 @@ macro_rules! register_builtin { let span = db.lookup_intern_macro_call(id).call_site; let span = span_with_def_site_ctxt(db, span, id); - expander(db, id, span, tt, token_map) + expander(span, tt, token_map) } fn find_by_name(name: &name::Name) -> Option { @@ -398,41 +398,13 @@ fn expand_simple_derive( ExpandResult::ok(expanded) } -fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: Span) -> tt::TokenTree { - // FIXME: make hygiene works for builtin derive macro - // such that $crate can be used here. - let cg = db.crate_graph(); - let krate = db.lookup_intern_macro_call(id).krate; - - let tt = if matches!(cg[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) { - cov_mark::hit!(test_copy_expand_in_core); - quote! {span => crate } - } else { - quote! {span => core } - }; - - tt.token_trees[0].clone() -} - -fn copy_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn copy_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) } -fn clone_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| { if matches!(adt.shape, AdtShape::Union) { let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; @@ -482,14 +454,8 @@ fn and_and(span: Span) -> tt::Subtree { quote! {span => #and& } } -fn default_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| { let body = match &adt.shape { AdtShape::Struct(fields) => { @@ -527,14 +493,8 @@ fn default_expand( }) } -fn debug_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::fmt::Debug }, |adt| { let for_variant = |name: String, v: &VariantShape| match v { VariantShape::Struct(fields) => { @@ -605,14 +565,8 @@ fn debug_expand( }) } -fn hash_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here @@ -658,25 +612,13 @@ fn hash_expand( }) } -fn eq_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) } -fn partial_eq_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn partial_eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here @@ -747,17 +689,11 @@ fn self_and_other_patterns( (self_patterns, other_patterns) } -fn ord_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| { fn compare( - krate: &tt::TokenTree, + krate: &tt::Ident, left: tt::Subtree, right: tt::Subtree, rest: tt::Subtree, @@ -811,17 +747,11 @@ fn ord_expand( }) } -fn partial_ord_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn partial_ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| { fn compare( - krate: &tt::TokenTree, + krate: &tt::Ident, left: tt::Subtree, right: tt::Subtree, rest: tt::Subtree, diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs index f99a89176233..65a55f8b5b89 100644 --- a/crates/hir-expand/src/builtin_fn_macro.rs +++ b/crates/hir-expand/src/builtin_fn_macro.rs @@ -6,16 +6,14 @@ use either::Either; use itertools::Itertools; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; use span::{Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; -use syntax::{ - ast::{self, AstToken}, - SmolStr, -}; +use syntax::ast::{self, AstToken}; use crate::{ db::ExpandDatabase, hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt}, name::{self, known}, quote, + quote::dollar_crate, tt::{self, DelimSpan}, ExpandError, ExpandResult, HirFileIdExt, MacroCallId, }; @@ -205,7 +203,7 @@ fn assert_expand( ) -> ExpandResult { let call_site_span = span_with_call_site_ctxt(db, span, id); let args = parse_exprs_with_sep(tt, ',', call_site_span); - let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_crate = dollar_crate(span); let expanded = match &*args { [cond, panic_args @ ..] => { let comma = tt::Subtree { @@ -300,7 +298,7 @@ fn asm_expand( [tt::TokenTree::Leaf(tt::Leaf::Literal(lit))] | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', span: _, spacing: _ }))] => { - let dollar_krate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_krate = dollar_crate(span); literals.push(quote!(span=>#dollar_krate::format_args!(#lit);)); } _ => break, @@ -345,7 +343,7 @@ fn panic_expand( tt: &tt::Subtree, span: Span, ) -> ExpandResult { - let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_crate = dollar_crate(span); let call_site_span = span_with_call_site_ctxt(db, span, id); let mac = @@ -371,7 +369,7 @@ fn unreachable_expand( tt: &tt::Subtree, span: Span, ) -> ExpandResult { - let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_crate = dollar_crate(span); let call_site_span = span_with_call_site_ctxt(db, span, id); let mac = if use_panic_2021(db, call_site_span) { @@ -763,10 +761,10 @@ fn option_env_expand( return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e) } }; - // FIXME: Use `DOLLAR_CRATE` when that works in eager macros. + let dollar_crate = dollar_crate(span); let expanded = match get_env_inner(db, arg_id, &key) { - None => quote! {span => ::core::option::Option::None::<&str> }, - Some(s) => quote! {span => ::core::option::Option::Some(#s) }, + None => quote! {span => #dollar_crate::option::Option::None::<&str> }, + Some(s) => quote! {span => #dollar_crate::option::Option::Some(#s) }, }; ExpandResult::ok(expanded) diff --git a/crates/hir-expand/src/quote.rs b/crates/hir-expand/src/quote.rs index 9bdd75f9d224..a3b84afd2ae4 100644 --- a/crates/hir-expand/src/quote.rs +++ b/crates/hir-expand/src/quote.rs @@ -4,6 +4,10 @@ use span::Span; use crate::name::Name; +pub(crate) fn dollar_crate(span: Span) -> tt::Ident { + tt::Ident { text: syntax::SmolStr::new_inline("$crate"), span } +} + // A helper macro quote macro // FIXME: // 1. Not all puncts are handled diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index d16e0eb0137b..622b4f56d4ff 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -987,15 +987,12 @@ fn infer_builtin_macros_env() { fn infer_builtin_macros_option_env() { check_types( r#" - //- minicore: option - //- /main.rs env:foo=bar - #[rustc_builtin_macro] - macro_rules! option_env {() => {}} - - fn main() { - let x = option_env!("foo"); - //^ Option<&str> - } +//- minicore: env +//- /main.rs env:foo=bar +fn main() { + let x = option_env!("foo"); + //^ Option<&str> +} "#, ); } @@ -1014,6 +1011,21 @@ fn test() { ); } +#[test] +fn infer_builtin_derive_resolves_with_core_module() { + check_types( + r#" +//- minicore: derive, clone +mod core {} +#[derive(Clone)] +struct S; +fn test() { + S.clone(); +} //^^^^^^^^^ S +"#, + ); +} + #[test] fn infer_derive_clone_with_params() { check_types( diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 024053effe42..17c701ad0359 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -481,7 +481,7 @@ struct Foo {} "#, expect![[r#" Clone - impl < >core::clone::Clone for Foo< >where { + impl < >$crate::clone::Clone for Foo< >where { fn clone(&self) -> Self { match self { Foo{} @@ -507,7 +507,7 @@ struct Foo {} "#, expect![[r#" Copy - impl < >core::marker::Copy for Foo< >where{}"#]], + impl < >$crate::marker::Copy for Foo< >where{}"#]], ); } @@ -522,7 +522,7 @@ struct Foo {} "#, expect![[r#" Copy - impl < >core::marker::Copy for Foo< >where{}"#]], + impl < >$crate::marker::Copy for Foo< >where{}"#]], ); check( r#" @@ -533,7 +533,7 @@ struct Foo {} "#, expect![[r#" Clone - impl < >core::clone::Clone for Foo< >where { + impl < >$crate::clone::Clone for Foo< >where { fn clone(&self) -> Self { match self { Foo{} diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index 1f3136404c61..140bb0804278 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -25,6 +25,7 @@ //! derive: //! discriminant: //! drop: +//! env: option //! eq: sized //! error: fmt //! fmt: result, transmute, coerce_unsized @@ -1450,6 +1451,15 @@ mod macros { #[macro_export] macro_rules! concat {} // endregion:concat + + // region:env + #[rustc_builtin_macro] + #[macro_export] + macro_rules! env {} + #[rustc_builtin_macro] + #[macro_export] + macro_rules! option_env {} + // endregion:env } // region:non_zero From 1c40ac79c8570a05b143823159bbc83904bf9730 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 7 Jan 2024 20:31:56 +0100 Subject: [PATCH 053/297] VFS no longer stores all source files in memory --- crates/load-cargo/src/lib.rs | 5 +- crates/rust-analyzer/src/global_state.rs | 83 ++++++------- .../src/handlers/notification.rs | 25 ++-- crates/rust-analyzer/src/handlers/request.rs | 1 - crates/rust-analyzer/src/lsp/utils.rs | 35 +++--- crates/rust-analyzer/src/main_loop.rs | 2 + crates/rust-analyzer/src/mem_docs.rs | 5 +- crates/rust-analyzer/src/reload.rs | 7 +- crates/vfs/src/lib.rs | 110 +++++++++--------- 9 files changed, 130 insertions(+), 143 deletions(-) diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index 556ed73a04c2..ee0b9e6d5040 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -331,9 +331,8 @@ fn load_crate_graph( } let changes = vfs.take_changes(); for file in changes { - if file.exists() { - let contents = vfs.file_contents(file.file_id); - if let Ok(text) = std::str::from_utf8(contents) { + if let vfs::Change::Create(v) | vfs::Change::Modify(v) = file.change { + if let Ok(text) = std::str::from_utf8(&v) { analysis_change.change_file(file.file_id, Some(text.into())) } } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index f57a27305f03..da132f93968d 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -3,7 +3,7 @@ //! //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. -use std::time::Instant; +use std::{collections::hash_map::Entry, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; @@ -21,7 +21,7 @@ use proc_macro_api::ProcMacroServer; use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts}; use rustc_hash::{FxHashMap, FxHashSet}; use triomphe::Arc; -use vfs::{AnchoredPathBuf, Vfs}; +use vfs::{AnchoredPathBuf, ChangedFile, Vfs}; use crate::{ config::{Config, ConfigError}, @@ -217,8 +217,8 @@ impl GlobalState { pub(crate) fn process_changes(&mut self) -> bool { let _p = profile::span("GlobalState::process_changes"); - let mut file_changes = FxHashMap::default(); - let (change, changed_files, workspace_structure_change) = { + let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); + let (change, modified_files, workspace_structure_change) = { let mut change = Change::new(); let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); @@ -233,64 +233,63 @@ impl GlobalState { // id that is followed by a delete we actually skip observing the file text from the // earlier event, to avoid problems later on. for changed_file in changed_files { - use vfs::ChangeKind::*; - - file_changes - .entry(changed_file.file_id) - .and_modify(|(change, just_created)| { - // None -> Delete => keep - // Create -> Delete => collapse - // - match (change, just_created, changed_file.change_kind) { + use vfs::Change::*; + match file_changes.entry(changed_file.file_id) { + Entry::Occupied(mut o) => { + let (just_created, change) = o.get_mut(); + match (&mut change.change, just_created, changed_file.change) { // latter `Delete` wins (change, _, Delete) => *change = Delete, // merge `Create` with `Create` or `Modify` - (Create, _, Create | Modify) => {} + (Create(prev), _, Create(new) | Modify(new)) => *prev = new, // collapse identical `Modify`es - (Modify, _, Modify) => {} + (Modify(prev), _, Modify(new)) => *prev = new, // equivalent to `Modify` - (change @ Delete, just_created, Create) => { - *change = Modify; + (change @ Delete, just_created, Create(new)) => { + *change = Modify(new); *just_created = true; } // shouldn't occur, but collapse into `Create` - (change @ Delete, just_created, Modify) => { - *change = Create; + (change @ Delete, just_created, Modify(new)) => { + *change = Create(new); *just_created = true; } // shouldn't occur, but collapse into `Modify` - (Modify, _, Create) => {} + (Modify(prev), _, Create(new)) => *prev = new, } - }) - .or_insert(( - changed_file.change_kind, - matches!(changed_file.change_kind, Create), - )); + } + Entry::Vacant(v) => { + _ = v.insert((matches!(&changed_file.change, Create(_)), changed_file)) + } + } } let changed_files: Vec<_> = file_changes .into_iter() - .filter(|(_, (change_kind, just_created))| { - !matches!((change_kind, just_created), (vfs::ChangeKind::Delete, true)) + .filter(|(_, (just_created, change))| { + !(*just_created && matches!(change.change, vfs::Change::Delete)) }) - .map(|(file_id, (change_kind, _))| vfs::ChangedFile { file_id, change_kind }) + .map(|(file_id, (_, change))| vfs::ChangedFile { file_id, ..change }) .collect(); let mut workspace_structure_change = None; // A file was added or deleted let mut has_structure_changes = false; let mut bytes = vec![]; - for file in &changed_files { + let mut modified_files = vec![]; + for file in changed_files { let vfs_path = &vfs.file_path(file.file_id); if let Some(path) = vfs_path.as_path() { let path = path.to_path_buf(); - if reload::should_refresh_for_change(&path, file.change_kind) { + if reload::should_refresh_for_change(&path, file.kind()) { workspace_structure_change = Some((path.clone(), false)); } if file.is_created_or_deleted() { has_structure_changes = true; workspace_structure_change = Some((path, self.crate_graph_file_dependencies.contains(vfs_path))); + } else { + modified_files.push(file.file_id); } } @@ -299,10 +298,8 @@ impl GlobalState { self.diagnostics.clear_native_for(file.file_id); } - let text = if file.exists() { - let bytes = vfs.file_contents(file.file_id).to_vec(); - - String::from_utf8(bytes).ok().and_then(|text| { + let text = if let vfs::Change::Create(v) | vfs::Change::Modify(v) = file.change { + String::from_utf8(v).ok().and_then(|text| { // FIXME: Consider doing normalization in the `vfs` instead? That allows // getting rid of some locking let (text, line_endings) = LineEndings::normalize(text); @@ -327,11 +324,10 @@ impl GlobalState { let roots = self.source_root_config.partition(vfs); change.set_roots(roots); } - (change, changed_files, workspace_structure_change) + (change, modified_files, workspace_structure_change) }; self.analysis_host.apply_change(change); - { let raw_database = self.analysis_host.raw_database(); // FIXME: ideally we should only trigger a workspace fetch for non-library changes @@ -343,13 +339,12 @@ impl GlobalState { force_crate_graph_reload, ); } - self.proc_macro_changed = - changed_files.iter().filter(|file| !file.is_created_or_deleted()).any(|file| { - let crates = raw_database.relevant_crates(file.file_id); - let crate_graph = raw_database.crate_graph(); + self.proc_macro_changed = modified_files.into_iter().any(|file_id| { + let crates = raw_database.relevant_crates(file_id); + let crate_graph = raw_database.crate_graph(); - crates.iter().any(|&krate| crate_graph[krate].is_proc_macro) - }); + crates.iter().any(|&krate| crate_graph[krate].is_proc_macro) + }); } true @@ -494,10 +489,6 @@ impl GlobalStateSnapshot { }) } - pub(crate) fn vfs_memory_usage(&self) -> usize { - self.vfs_read().memory_usage() - } - pub(crate) fn file_exists(&self, file_id: FileId) -> bool { self.vfs.read().0.exists(file_id) } diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index 7e6219991b66..c0d35498c665 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -59,7 +59,13 @@ pub(crate) fn handle_did_open_text_document( if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { let already_exists = state .mem_docs - .insert(path.clone(), DocumentData::new(params.text_document.version)) + .insert( + path.clone(), + DocumentData::new( + params.text_document.version, + params.text_document.text.clone().into_bytes(), + ), + ) .is_err(); if already_exists { tracing::error!("duplicate DidOpenTextDocument: {}", path); @@ -76,11 +82,12 @@ pub(crate) fn handle_did_change_text_document( let _p = profile::span("handle_did_change_text_document"); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { - match state.mem_docs.get_mut(&path) { + let data = match state.mem_docs.get_mut(&path) { Some(doc) => { // The version passed in DidChangeTextDocument is the version after all edits are applied // so we should apply it before the vfs is notified. doc.version = params.text_document.version; + &mut doc.data } None => { tracing::error!("unexpected DidChangeTextDocument: {}", path); @@ -88,16 +95,14 @@ pub(crate) fn handle_did_change_text_document( } }; - let text = apply_document_changes( + let new_contents = apply_document_changes( state.config.position_encoding(), - || { - let vfs = &state.vfs.read().0; - let file_id = vfs.file_id(&path).unwrap(); - std::str::from_utf8(vfs.file_contents(file_id)).unwrap().into() - }, + std::str::from_utf8(data).unwrap(), params.content_changes, - ); - state.vfs.write().0.set_file_contents(path, Some(text.into_bytes())); + ) + .into_bytes(); + *data = new_contents.clone(); + state.vfs.write().0.set_file_contents(path, Some(new_contents)); } Ok(()) } diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 13544558c50c..22c7e9b0503c 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -103,7 +103,6 @@ pub(crate) fn handle_analyzer_status( .collect::>() ); } - format_to!(buf, "\nVfs memory usage: {}\n", profile::Bytes::new(snap.vfs_memory_usage() as _)); buf.push_str("\nAnalysis:\n"); buf.push_str( &snap diff --git a/crates/rust-analyzer/src/lsp/utils.rs b/crates/rust-analyzer/src/lsp/utils.rs index a4417e4d4a14..fa5ea5b57db0 100644 --- a/crates/rust-analyzer/src/lsp/utils.rs +++ b/crates/rust-analyzer/src/lsp/utils.rs @@ -168,7 +168,7 @@ impl GlobalState { pub(crate) fn apply_document_changes( encoding: PositionEncoding, - file_contents: impl FnOnce() -> String, + file_contents: &str, mut content_changes: Vec, ) -> String { // If at least one of the changes is a full document change, use the last @@ -179,7 +179,7 @@ pub(crate) fn apply_document_changes( let text = mem::take(&mut content_changes[idx].text); (text, &content_changes[idx + 1..]) } - None => (file_contents(), &content_changes[..]), + None => (file_contents.to_owned(), &content_changes[..]), }; if content_changes.is_empty() { return text; @@ -276,11 +276,11 @@ mod tests { } let encoding = PositionEncoding::Wide(WideEncoding::Utf16); - let text = apply_document_changes(encoding, || String::new(), vec![]); + let text = apply_document_changes(encoding, "", vec![]); assert_eq!(text, ""); let text = apply_document_changes( encoding, - || text, + &text, vec![TextDocumentContentChangeEvent { range: None, range_length: None, @@ -288,49 +288,46 @@ mod tests { }], ); assert_eq!(text, "the"); - let text = apply_document_changes(encoding, || text, c![0, 3; 0, 3 => " quick"]); + let text = apply_document_changes(encoding, &text, c![0, 3; 0, 3 => " quick"]); assert_eq!(text, "the quick"); let text = - apply_document_changes(encoding, || text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); + apply_document_changes(encoding, &text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); assert_eq!(text, "quick foxes"); - let text = apply_document_changes(encoding, || text, c![0, 11; 0, 11 => "\ndream"]); + let text = apply_document_changes(encoding, &text, c![0, 11; 0, 11 => "\ndream"]); assert_eq!(text, "quick foxes\ndream"); - let text = apply_document_changes(encoding, || text, c![1, 0; 1, 0 => "have "]); + let text = apply_document_changes(encoding, &text, c![1, 0; 1, 0 => "have "]); assert_eq!(text, "quick foxes\nhave dream"); let text = apply_document_changes( encoding, - || text, + &text, c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"], ); assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); - let text = apply_document_changes( - encoding, - || text, - c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"], - ); + let text = + apply_document_changes(encoding, &text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]); assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); let text = apply_document_changes( encoding, - || text, + &text, c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], ); assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); let text = - apply_document_changes(encoding, || text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); + apply_document_changes(encoding, &text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); assert_eq!(text, "the quick \nthey have quiet dreams\n"); let text = String::from("❤️"); - let text = apply_document_changes(encoding, || text, c![0, 0; 0, 0 => "a"]); + let text = apply_document_changes(encoding, &text, c![0, 0; 0, 0 => "a"]); assert_eq!(text, "a❤️"); let text = String::from("a\nb"); let text = - apply_document_changes(encoding, || text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); + apply_document_changes(encoding, &text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); assert_eq!(text, "adcb"); let text = String::from("a\nb"); let text = - apply_document_changes(encoding, || text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); + apply_document_changes(encoding, &text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); assert_eq!(text, "ațc\ncb"); } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index cdf41c955d26..356c332f90d9 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -576,6 +576,8 @@ impl GlobalState { let vfs = &mut self.vfs.write().0; for (path, contents) in files { let path = VfsPath::from(path); + // if the file is in mem docs, it's managed by the client via notifications + // so only set it if its not in there if !self.mem_docs.contains(&path) { vfs.set_file_contents(path, contents); } diff --git a/crates/rust-analyzer/src/mem_docs.rs b/crates/rust-analyzer/src/mem_docs.rs index 45a1dab9772f..6a93a0ebb4ce 100644 --- a/crates/rust-analyzer/src/mem_docs.rs +++ b/crates/rust-analyzer/src/mem_docs.rs @@ -62,10 +62,11 @@ impl MemDocs { #[derive(Debug, Clone)] pub(crate) struct DocumentData { pub(crate) version: i32, + pub(crate) data: Vec, } impl DocumentData { - pub(crate) fn new(version: i32) -> Self { - DocumentData { version } + pub(crate) fn new(version: i32, data: Vec) -> Self { + DocumentData { version, data } } } diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 91dc6c2e4b41..8e3fa7fa4dac 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -503,10 +503,9 @@ impl GlobalState { match vfs.file_id(&vfs_path) { Some(file_id) => Some(file_id), None => { - if !self.mem_docs.contains(&vfs_path) { - let contents = loader.handle.load_sync(path); - vfs.set_file_contents(vfs_path.clone(), contents); - } + // FIXME: Consider not loading this here? + let contents = loader.handle.load_sync(path); + vfs.set_file_contents(vfs_path.clone(), contents); vfs.file_id(&vfs_path) } } diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index ef5b10ee9db2..34a85818eb84 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs @@ -1,8 +1,8 @@ //! # Virtual File System //! -//! VFS stores all files read by rust-analyzer. Reading file contents from VFS -//! always returns the same contents, unless VFS was explicitly modified with -//! [`set_file_contents`]. All changes to VFS are logged, and can be retrieved via +//! VFS records all file changes pushed to it via [`set_file_contents`]. +//! As such it only ever stores changes, not the actual content of a file at any given moment. +//! All file changes are logged, and can be retrieved via //! [`take_changes`] method. The pack of changes is then pushed to `salsa` and //! triggers incremental recomputation. //! @@ -84,40 +84,65 @@ impl FileId { /// safe because `FileId` is a newtype of `u32` impl nohash_hasher::IsEnabled for FileId {} -/// Storage for all files read by rust-analyzer. +/// Storage for all file changes and the file id to path mapping. /// /// For more information see the [crate-level](crate) documentation. #[derive(Default)] pub struct Vfs { interner: PathInterner, - data: Vec>>, + data: Vec, changes: Vec, } +#[derive(Copy, PartialEq, PartialOrd, Clone)] +pub enum FileState { + Exists, + Deleted, +} + /// Changed file in the [`Vfs`]. #[derive(Debug)] pub struct ChangedFile { /// Id of the changed file pub file_id: FileId, /// Kind of change - pub change_kind: ChangeKind, + pub change: Change, } impl ChangedFile { /// Returns `true` if the change is not [`Delete`](ChangeKind::Delete). pub fn exists(&self) -> bool { - self.change_kind != ChangeKind::Delete + !matches!(self.change, Change::Delete) } /// Returns `true` if the change is [`Create`](ChangeKind::Create) or - /// [`Delete`](ChangeKind::Delete). + /// [`Delete`](Change::Delete). pub fn is_created_or_deleted(&self) -> bool { - matches!(self.change_kind, ChangeKind::Create | ChangeKind::Delete) + matches!(self.change, Change::Create(_) | Change::Delete) + } + + pub fn kind(&self) -> ChangeKind { + match self.change { + Change::Create(_) => ChangeKind::Create, + Change::Modify(_) => ChangeKind::Modify, + Change::Delete => ChangeKind::Delete, + } } } /// Kind of [file change](ChangedFile). -#[derive(Eq, PartialEq, Copy, Clone, Debug)] +#[derive(Eq, PartialEq, Debug)] +pub enum Change { + /// The file was (re-)created + Create(Vec), + /// The file was modified + Modify(Vec), + /// The file was deleted + Delete, +} + +/// Kind of [file change](ChangedFile). +#[derive(Eq, PartialEq, Debug)] pub enum ChangeKind { /// The file was (re-)created Create, @@ -130,7 +155,7 @@ pub enum ChangeKind { impl Vfs { /// Id of the given path if it exists in the `Vfs` and is not deleted. pub fn file_id(&self, path: &VfsPath) -> Option { - self.interner.get(path).filter(|&it| self.get(it).is_some()) + self.interner.get(path).filter(|&it| matches!(self.get(it), FileState::Exists)) } /// File path corresponding to the given `file_id`. @@ -142,28 +167,13 @@ impl Vfs { self.interner.lookup(file_id).clone() } - /// File content corresponding to the given `file_id`. - /// - /// # Panics - /// - /// Panics if the id is not present in the `Vfs`, or if the corresponding file is - /// deleted. - pub fn file_contents(&self, file_id: FileId) -> &[u8] { - self.get(file_id).as_deref().unwrap() - } - - /// Returns the overall memory usage for the stored files. - pub fn memory_usage(&self) -> usize { - self.data.iter().flatten().map(|d| d.capacity()).sum() - } - /// Returns an iterator over the stored ids and their corresponding paths. /// /// This will skip deleted files. pub fn iter(&self) -> impl Iterator + '_ { (0..self.data.len()) .map(|it| FileId(it as u32)) - .filter(move |&file_id| self.get(file_id).is_some()) + .filter(move |&file_id| matches!(self.get(file_id), FileState::Exists)) .map(move |file_id| { let path = self.interner.lookup(file_id); (file_id, path) @@ -176,28 +186,21 @@ impl Vfs { /// /// If the path does not currently exists in the `Vfs`, allocates a new /// [`FileId`] for it. - pub fn set_file_contents(&mut self, path: VfsPath, mut contents: Option>) -> bool { + pub fn set_file_contents(&mut self, path: VfsPath, contents: Option>) -> bool { let file_id = self.alloc_file_id(path); - let change_kind = match (self.get(file_id), &contents) { - (None, None) => return false, - (Some(old), Some(new)) if old == new => return false, - (None, Some(_)) => ChangeKind::Create, - (Some(_), None) => ChangeKind::Delete, - (Some(_), Some(_)) => ChangeKind::Modify, + let change_kind = match (self.get(file_id), contents) { + (FileState::Deleted, None) => return false, + (FileState::Deleted, Some(v)) => Change::Create(v), + (FileState::Exists, None) => Change::Delete, + (FileState::Exists, Some(v)) => Change::Modify(v), }; - if let Some(contents) = &mut contents { - contents.shrink_to_fit(); - } - *self.get_mut(file_id) = contents; - self.changes.push(ChangedFile { file_id, change_kind }); + let changed_file = ChangedFile { file_id, change: change_kind }; + self.data[file_id.0 as usize] = + if changed_file.exists() { FileState::Exists } else { FileState::Deleted }; + self.changes.push(changed_file); true } - /// Returns `true` if the `Vfs` contains [changes](ChangedFile). - pub fn has_changes(&self) -> bool { - !self.changes.is_empty() - } - /// Drain and returns all the changes in the `Vfs`. pub fn take_changes(&mut self) -> Vec { mem::take(&mut self.changes) @@ -205,7 +208,7 @@ impl Vfs { /// Provides a panic-less way to verify file_id validity. pub fn exists(&self, file_id: FileId) -> bool { - self.get(file_id).is_some() + matches!(self.get(file_id), FileState::Exists) } /// Returns the id associated with `path` @@ -219,26 +222,17 @@ impl Vfs { let file_id = self.interner.intern(path); let idx = file_id.0 as usize; let len = self.data.len().max(idx + 1); - self.data.resize_with(len, || None); + self.data.resize(len, FileState::Deleted); file_id } - /// Returns the content associated with the given `file_id`. + /// Returns the status of the file associated with the given `file_id`. /// /// # Panics /// /// Panics if no file is associated to that id. - fn get(&self, file_id: FileId) -> &Option> { - &self.data[file_id.0 as usize] - } - - /// Mutably returns the content associated with the given `file_id`. - /// - /// # Panics - /// - /// Panics if no file is associated to that id. - fn get_mut(&mut self, file_id: FileId) -> &mut Option> { - &mut self.data[file_id.0 as usize] + fn get(&self, file_id: FileId) -> FileState { + self.data[file_id.0 as usize] } } From 72200641c1702fe143ba11218c3ecc6604c3d9db Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:09:19 +0100 Subject: [PATCH 054/297] fix: Fix incorrect parsing error on method call on range --- crates/parser/src/grammar/expressions.rs | 10 +++- .../ok/0208_closure_range_method_call.rast | 49 +++++++++++++++++++ .../ok/0208_closure_range_method_call.rs | 4 ++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast create mode 100644 crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index e346ece2f94b..c8626111145d 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs @@ -371,7 +371,15 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik if p.at(op) { m = p.start(); p.bump(op); - if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) { + + // test closure_range_method_call + // fn foo() { + // || .. .method(); + // || .. .field; + // } + let has_access_after = p.at(T![.]) && p.nth_at(1, SyntaxKind::IDENT); + let struct_forbidden = r.forbid_structs && p.at(T!['{']); + if p.at_ts(EXPR_FIRST) && !has_access_after && !struct_forbidden { expr_bp(p, None, r, 2); } let cm = m.complete(p, RANGE_EXPR); diff --git a/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast b/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast new file mode 100644 index 000000000000..542711339d19 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast @@ -0,0 +1,49 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + METHOD_CALL_EXPR + CLOSURE_EXPR + PARAM_LIST + PIPE "|" + PIPE "|" + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + WHITESPACE " " + DOT "." + NAME_REF + IDENT "method" + ARG_LIST + L_PAREN "(" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + FIELD_EXPR + CLOSURE_EXPR + PARAM_LIST + PIPE "|" + PIPE "|" + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + WHITESPACE " " + DOT "." + NAME_REF + IDENT "field" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs b/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs new file mode 100644 index 000000000000..a81d3c37133a --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs @@ -0,0 +1,4 @@ +fn foo() { + || .. .method(); + || .. .field; +} From b97ab00bd404bc5e6fb3eb92a123062a02ab7f23 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:24:46 +0100 Subject: [PATCH 055/297] Split out rustc_lexer from rustc_dependencies --- Cargo.lock | 5 ++--- Cargo.toml | 2 ++ crates/parser/Cargo.toml | 7 +++---- crates/parser/src/lexed_str.rs | 2 -- crates/parser/src/lib.rs | 5 +++++ crates/rustc-dependencies/Cargo.toml | 3 +-- crates/rustc-dependencies/src/lib.rs | 11 ----------- crates/syntax/Cargo.toml | 6 +++--- crates/syntax/src/ast/token_ext.rs | 2 -- crates/syntax/src/lib.rs | 5 +++++ crates/syntax/src/validation.rs | 2 +- 11 files changed, 22 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6670e92f51bc..98ae47640f2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1196,7 +1196,7 @@ dependencies = [ "drop_bomb", "expect-test", "limit", - "rustc-dependencies", + "ra-ap-rustc_lexer", "sourcegen", "stdx", ] @@ -1605,7 +1605,6 @@ version = "0.0.0" dependencies = [ "ra-ap-rustc_abi", "ra-ap-rustc_index", - "ra-ap-rustc_lexer", "ra-ap-rustc_parse_format", ] @@ -1808,9 +1807,9 @@ dependencies = [ "proc-macro2", "profile", "quote", + "ra-ap-rustc_lexer", "rayon", "rowan", - "rustc-dependencies", "rustc-hash", "smol_str", "sourcegen", diff --git a/Cargo.toml b/Cargo.toml index 4ee8064b5e34..296ccb2dfaa5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,8 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" } +ra-ap-rustc_lexer = "0.21.0" + # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } test-fixture = { path = "./crates/test-fixture" } diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index 0c63484634be..e74b340126c0 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -13,8 +13,7 @@ doctest = false [dependencies] drop_bomb = "0.1.5" -rustc-dependencies.workspace = true - +ra-ap-rustc_lexer.workspace = true limit.workspace = true [dev-dependencies] @@ -24,7 +23,7 @@ stdx.workspace = true sourcegen.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index b9e7566fdf9b..f47ec49df1d9 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -8,8 +8,6 @@ //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. -use rustc_dependencies::lexer as rustc_lexer; - use std::ops; use rustc_lexer::unescape::{EscapeError, Mode}; diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index d9b3f46f2001..ed0aec3cab32 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -21,6 +21,11 @@ #![allow(rustdoc::private_intra_doc_links)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_lexer as rustc_lexer; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + mod lexed_str; mod token_set; mod syntax_kind; diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml index 0bf04301df16..ae8abc6cc7be 100644 --- a/crates/rustc-dependencies/Cargo.toml +++ b/crates/rustc-dependencies/Cargo.toml @@ -11,7 +11,6 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ra-ap-rustc_lexer = { version = "0.21.0" } ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } ra-ap-rustc_index = { version = "0.21.0", default-features = false } ra-ap-rustc_abi = { version = "0.21.0", default-features = false } @@ -20,4 +19,4 @@ ra-ap-rustc_abi = { version = "0.21.0", default-features = false } in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/rustc-dependencies/src/lib.rs b/crates/rustc-dependencies/src/lib.rs index 13fcbc491937..d3f386fe08a6 100644 --- a/crates/rustc-dependencies/src/lib.rs +++ b/crates/rustc-dependencies/src/lib.rs @@ -3,17 +3,6 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[cfg(feature = "in-rust-tree")] -extern crate rustc_lexer; - -pub mod lexer { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_lexer::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_lexer::*; -} - #[cfg(feature = "in-rust-tree")] extern crate rustc_parse_format; diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 40a93fec2cec..9f78614bba66 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -23,7 +23,7 @@ indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true -rustc-dependencies.workspace = true +ra-ap-rustc_lexer.workspace = true parser.workspace = true profile.workspace = true @@ -41,7 +41,7 @@ test-utils.workspace = true sourcegen.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index d5d565a015a0..ede392fc62a2 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs @@ -2,8 +2,6 @@ use std::borrow::Cow; -use rustc_dependencies::lexer as rustc_lexer; - use rustc_lexer::unescape::{ unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode, }; diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index d600698040dc..1b41596a5f27 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -22,6 +22,11 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![warn(rust_2018_idioms, unused_lifetimes)] +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_lexer as rustc_lexer; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + #[allow(unused)] macro_rules! eprintln { ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index eabbda2c3983..6c6916c585f1 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_dependencies::lexer::unescape::{self, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_literal, Mode}; use crate::{ algo, From e25e0dd0adb7bc4b402872af8414e7d99e0adec0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:30:26 +0100 Subject: [PATCH 056/297] Split out rustc_parse_format from rustc_dependencies --- Cargo.lock | 2 +- Cargo.toml | 3 ++- crates/hir-def/Cargo.toml | 3 ++- crates/hir-def/src/hir/format_args.rs | 2 +- crates/hir-def/src/lib.rs | 9 +++++---- crates/rustc-dependencies/Cargo.toml | 1 - crates/rustc-dependencies/src/lib.rs | 11 ----------- 7 files changed, 11 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 98ae47640f2b..547940c91d6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -513,6 +513,7 @@ dependencies = [ "mbe", "once_cell", "profile", + "ra-ap-rustc_parse_format", "rustc-dependencies", "rustc-hash", "smallvec", @@ -1605,7 +1606,6 @@ version = "0.0.0" dependencies = [ "ra-ap-rustc_abi", "ra-ap-rustc_index", - "ra-ap-rustc_parse_format", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 296ccb2dfaa5..1734c55a3f23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,7 +80,8 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" } -ra-ap-rustc_lexer = "0.21.0" +ra-ap-rustc_lexer = { version = "0.21.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index 5933d30040fa..fea7d81c6a6b 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -29,6 +29,7 @@ smallvec.workspace = true hashbrown.workspace = true triomphe.workspace = true +ra-ap-rustc_parse_format.workspace = true rustc-dependencies.workspace = true # local deps @@ -56,4 +57,4 @@ test-fixture.workspace = true in-rust-tree = ["rustc-dependencies/in-rust-tree"] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs index 7fc33abc7c9a..c0d1738b5048 100644 --- a/crates/hir-def/src/hir/format_args.rs +++ b/crates/hir-def/src/hir/format_args.rs @@ -2,7 +2,7 @@ use std::mem; use hir_expand::name::Name; -use rustc_dependencies::parse_format as parse; +use rustc_parse_format as parse; use stdx::TupleExt; use syntax::{ ast::{self, IsString}, diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 250d7b677b5d..9d042ea93543 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -10,10 +10,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[allow(unused)] -macro_rules! eprintln { - ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; -} +#[cfg(feature = "in-rust-tree")] +extern crate rustc_parse_format; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_parse_format as rustc_parse_format; pub mod db; diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml index ae8abc6cc7be..a14cc60860ce 100644 --- a/crates/rustc-dependencies/Cargo.toml +++ b/crates/rustc-dependencies/Cargo.toml @@ -11,7 +11,6 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } ra-ap-rustc_index = { version = "0.21.0", default-features = false } ra-ap-rustc_abi = { version = "0.21.0", default-features = false } diff --git a/crates/rustc-dependencies/src/lib.rs b/crates/rustc-dependencies/src/lib.rs index d3f386fe08a6..d2aafe8a02bc 100644 --- a/crates/rustc-dependencies/src/lib.rs +++ b/crates/rustc-dependencies/src/lib.rs @@ -3,17 +3,6 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[cfg(feature = "in-rust-tree")] -extern crate rustc_parse_format; - -pub mod parse_format { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_parse_format::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_parse_format::*; -} - #[cfg(feature = "in-rust-tree")] extern crate rustc_abi; From f972da70d4b6ce79e43e07f68002227fd4db86f2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:39:35 +0100 Subject: [PATCH 057/297] Remove rustc_dependencies crate --- Cargo.lock | 14 +++----------- Cargo.toml | 3 ++- crates/hir-def/Cargo.toml | 4 ++-- crates/hir-def/src/data/adt.rs | 2 +- crates/hir-def/src/lib.rs | 8 +++++++- crates/hir-ty/Cargo.toml | 6 ++++-- crates/hir-ty/src/layout.rs | 11 +++++------ crates/hir-ty/src/layout/adt.rs | 2 +- crates/hir-ty/src/lib.rs | 15 +++++++++++---- crates/rust-analyzer/Cargo.toml | 4 +--- crates/rustc-dependencies/Cargo.toml | 21 --------------------- crates/rustc-dependencies/src/lib.rs | 26 -------------------------- 12 files changed, 37 insertions(+), 79 deletions(-) delete mode 100644 crates/rustc-dependencies/Cargo.toml delete mode 100644 crates/rustc-dependencies/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 547940c91d6e..b1a1c8fb9fd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -513,8 +513,8 @@ dependencies = [ "mbe", "once_cell", "profile", + "ra-ap-rustc_abi", "ra-ap-rustc_parse_format", - "rustc-dependencies", "rustc-hash", "smallvec", "span", @@ -580,7 +580,8 @@ dependencies = [ "oorandom", "profile", "project-model", - "rustc-dependencies", + "ra-ap-rustc_abi", + "ra-ap-rustc_index", "rustc-hash", "scoped-tls", "smallvec", @@ -1541,7 +1542,6 @@ dependencies = [ "profile", "project-model", "rayon", - "rustc-dependencies", "rustc-hash", "scip", "serde", @@ -1600,14 +1600,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-dependencies" -version = "0.0.0" -dependencies = [ - "ra-ap-rustc_abi", - "ra-ap-rustc_index", -] - [[package]] name = "rustc-hash" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 1734c55a3f23..a81c4659636e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,10 +78,11 @@ toolchain = { path = "./crates/toolchain", version = "0.0.0" } tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" } ra-ap-rustc_lexer = { version = "0.21.0", default-features = false } ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } +ra-ap-rustc_index = { version = "0.21.0", default-features = false } +ra-ap-rustc_abi = { version = "0.21.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index fea7d81c6a6b..523ff6fc404e 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -30,7 +30,7 @@ hashbrown.workspace = true triomphe.workspace = true ra-ap-rustc_parse_format.workspace = true -rustc-dependencies.workspace = true +ra-ap-rustc_abi.workspace = true # local deps stdx.workspace = true @@ -54,7 +54,7 @@ test-utils.workspace = true test-fixture.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] workspace = true diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index a95b78614e82..8772c34f02f1 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -11,7 +11,7 @@ use hir_expand::{ }; use intern::Interned; use la_arena::{Arena, ArenaMap}; -use rustc_dependencies::abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; +use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; use syntax::ast::{self, HasName, HasVisibility}; use triomphe::Arc; diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 9d042ea93543..aa84ccaee6ee 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -16,6 +16,12 @@ extern crate rustc_parse_format; #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_parse_format as rustc_parse_format; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_abi; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_abi as rustc_abi; + pub mod db; pub mod attr; @@ -50,7 +56,7 @@ pub mod visibility; pub mod find_path; pub mod import_map; -pub use rustc_dependencies::abi as layout; +pub use rustc_abi as layout; use triomphe::Arc; #[cfg(test)] diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index c7807bcf9aa1..803c18677da5 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -34,7 +34,9 @@ nohash-hasher.workspace = true typed-arena = "2.0.1" indexmap.workspace = true -rustc-dependencies.workspace = true +ra-ap-rustc_abi.workspace = true +ra-ap-rustc_index.workspace = true + # local deps stdx.workspace = true @@ -58,7 +60,7 @@ test-utils.workspace = true test-fixture.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] workspace = true diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 68619bb8b18c..b7bfaf2931b6 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -12,10 +12,9 @@ use hir_def::{ LocalEnumVariantId, LocalFieldId, StructId, }; use la_arena::{Idx, RawIdx}; -use rustc_dependencies::{ - abi::AddressSpace, - index::{IndexSlice, IndexVec}, -}; +use rustc_abi::AddressSpace; +use rustc_index::{IndexSlice, IndexVec}; + use stdx::never; use triomphe::Arc; @@ -35,7 +34,7 @@ mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); -impl rustc_dependencies::index::Idx for RustcEnumVariantIdx { +impl rustc_index::Idx for RustcEnumVariantIdx { fn new(idx: usize) -> Self { RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) } @@ -54,7 +53,7 @@ impl RustcFieldIdx { } } -impl rustc_dependencies::index::Idx for RustcFieldIdx { +impl rustc_index::Idx for RustcFieldIdx { fn new(idx: usize) -> Self { RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) } diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index 39788a950299..8a7715ce8729 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -9,7 +9,7 @@ use hir_def::{ AdtId, EnumVariantId, LocalEnumVariantId, VariantId, }; use la_arena::RawIdx; -use rustc_dependencies::index::IndexVec; +use rustc_index::IndexVec; use smallvec::SmallVec; use triomphe::Arc; diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 793b52b49faa..e72864a12eec 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -3,10 +3,17 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[allow(unused)] -macro_rules! eprintln { - ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; -} +#[cfg(feature = "in-rust-tree")] +extern crate rustc_index; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_index as rustc_index; + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_abi; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_abi as rustc_abi; mod builder; mod chalk_db; diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index ad24d6d28cd7..76414160716c 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -49,7 +49,6 @@ flycheck.workspace = true hir-def.workspace = true hir-ty.workspace = true hir.workspace = true -rustc-dependencies.workspace = true ide-db.workspace = true # This should only be used in CLI ide-ssr.workspace = true @@ -89,11 +88,10 @@ in-rust-tree = [ "ide/in-rust-tree", "syntax/in-rust-tree", "parser/in-rust-tree", - "rustc-dependencies/in-rust-tree", "hir/in-rust-tree", "hir-def/in-rust-tree", "hir-ty/in-rust-tree", ] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml deleted file mode 100644 index a14cc60860ce..000000000000 --- a/crates/rustc-dependencies/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "rustc-dependencies" -version = "0.0.0" -description = "TBD" - -rust-version.workspace = true -edition.workspace = true -license.workspace = true -authors.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -ra-ap-rustc_index = { version = "0.21.0", default-features = false } -ra-ap-rustc_abi = { version = "0.21.0", default-features = false } - -[features] -in-rust-tree = [] - -[lints] -workspace = true diff --git a/crates/rustc-dependencies/src/lib.rs b/crates/rustc-dependencies/src/lib.rs deleted file mode 100644 index d2aafe8a02bc..000000000000 --- a/crates/rustc-dependencies/src/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! A wrapper around rustc internal crates, which enables switching between compiler provided -//! ones and stable ones published in crates.io - -#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] - -#[cfg(feature = "in-rust-tree")] -extern crate rustc_abi; - -pub mod abi { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_abi::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_abi::*; -} - -#[cfg(feature = "in-rust-tree")] -extern crate rustc_index; - -pub mod index { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_index::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_index::*; -} From df5c6479823fda0c346e00f6cc89fcaa2f03168e Mon Sep 17 00:00:00 2001 From: dfireBird Date: Sat, 6 Jan 2024 15:48:10 +0530 Subject: [PATCH 058/297] add notable_trait predicate to `CompletionRelevance` implement the predicate set on the case function from traits --- crates/hir-def/src/attr.rs | 7 +++++++ crates/ide-completion/src/context.rs | 5 +++++ crates/ide-completion/src/item.rs | 6 ++++++ crates/ide-completion/src/render.rs | 4 ++++ crates/ide-completion/src/render/function.rs | 6 ++++++ 5 files changed, 28 insertions(+) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 26f76afb1f09..dfee397619c6 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -207,6 +207,13 @@ impl Attrs { }) } + pub fn has_doc_notable_trait(&self) -> bool { + self.by_key("doc").tt_values().any(|tt| { + tt.delimiter.kind == DelimiterKind::Parenthesis && + matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "notable_trait") + }) + } + pub fn doc_exprs(&self) -> impl Iterator + '_ { self.by_key("doc").tt_values().map(DocExpr::parse) } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 108b040de6ba..92aa1da89c41 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -529,6 +529,11 @@ impl CompletionContext<'_> { } } + /// Whether the given trait has `#[doc(notable_trait)]` + pub(crate) fn is_doc_notable_trait(&self, trait_: hir::Trait) -> bool { + trait_.attrs(self.db).has_doc_notable_trait() + } + /// Returns the traits in scope, with the [`Drop`] trait removed. pub(crate) fn traits_in_scope(&self) -> hir::VisibleTraits { let mut traits_in_scope = self.scope.visible_traits(); diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index de41a5bd70c4..affd9b729646 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -152,6 +152,8 @@ pub struct CompletionRelevance { pub is_local: bool, /// This is set when trait items are completed in an impl of that trait. pub is_item_from_trait: bool, + /// This is set for when trait items are from traits with `#[doc(notable_trait)]` + pub is_item_from_notable_trait: bool, /// This is set when an import is suggested whose name is already imported. pub is_name_already_imported: bool, /// This is set for completions that will insert a `use` item. @@ -228,6 +230,7 @@ impl CompletionRelevance { is_private_editable, postfix_match, is_definite, + is_item_from_notable_trait, } = self; // lower rank private things @@ -266,6 +269,9 @@ impl CompletionRelevance { if is_item_from_trait { score += 1; } + if is_item_from_notable_trait { + score += 1; + } if is_definite { score += 10; } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 581d557e831a..f924c9aedb60 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -1170,6 +1170,7 @@ fn main() { let _: m::Spam = S$0 } ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -1196,6 +1197,7 @@ fn main() { let _: m::Spam = S$0 } ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -1274,6 +1276,7 @@ fn foo() { A { the$0 } } ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -2089,6 +2092,7 @@ fn foo() { ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index b306bede653b..ccd312b03fb7 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -79,6 +79,11 @@ fn render( .and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db())) .map_or(false, |trait_| completion.is_ops_trait(trait_)); + let is_item_from_notable_trait = func + .as_assoc_item(ctx.db()) + .and_then(|trait_| trait_.containing_trait(ctx.db())) + .map_or(false, |trait_| completion.is_doc_notable_trait(trait_)); + let (has_dot_receiver, has_call_parens, cap) = match func_kind { FuncKind::Function(&PathCompletionCtx { kind: PathKind::Expr { .. }, @@ -105,6 +110,7 @@ fn render( }, exact_name_match: compute_exact_name_match(completion, &call), is_op_method, + is_item_from_notable_trait, ..ctx.completion_relevance() }); From d94f572fe249e1adc95a2dc876cc9f1d028c47bb Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 8 Jan 2024 18:10:48 +0100 Subject: [PATCH 059/297] Remove newline and add dot --- docs/dev/syntax.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md index 97e376787c82..fd6f220f4fa9 100644 --- a/docs/dev/syntax.md +++ b/docs/dev/syntax.md @@ -41,7 +41,6 @@ Syntax trees are a semi-transient data structure. In general, frontend does not keep syntax trees for all files in memory. Instead, it *lowers* syntax trees to more compact and rigid representation, which is not full-fidelity, but which can be mapped back to a syntax tree if so desired. - ### GreenNode GreenNode is a purely-functional tree with arbitrary arity. Conceptually, it is equivalent to the following run of the mill struct: @@ -500,7 +499,7 @@ Specifically, `TreeSink` constructs the tree in lockstep with draining the origi In the process, it records which tokens of the tree correspond to which tokens of the input, by using text ranges to identify syntax tokens. The end result is that parsing an expanded code yields a syntax tree and a mapping of text-ranges of the tree to original tokens. -To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitly handled by the parser +To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitly handled by the parser. ### Whitespace & Comments From 1b08e25c9db5dbe000397b96db1c0ad45d5a9bb1 Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:08:19 +0800 Subject: [PATCH 060/297] fix typo --- tests/rustdoc-ui/error-in-impl-trait/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rustdoc-ui/error-in-impl-trait/README.md b/tests/rustdoc-ui/error-in-impl-trait/README.md index d969ab10ef5e..0b42ff1771e2 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/README.md +++ b/tests/rustdoc-ui/error-in-impl-trait/README.md @@ -1,5 +1,5 @@ Each of these needs to be in a separate file, -because the `span_delayed_bug` ICE in rustdoc won't be triggerred +because the `span_delayed_bug` ICE in rustdoc won't be triggered if even a single other error was emitted. However, conceptually they are all testing basically the same thing. From 0ae73738adfbe0a6eaceed6b198cd3a124bce77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 9 Jan 2024 08:56:53 +0200 Subject: [PATCH 061/297] Try to fix feature gates --- crates/proc-macro-srv/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index f1575a5b0bd8..67b9f57a1636 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -11,11 +11,13 @@ //! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)… #![cfg(any(feature = "sysroot-abi", rust_analyzer))] -#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unreachable_pub, internal_features)] extern crate proc_macro; +#[cfg(feature = "in-rust-tree")] extern crate rustc_driver as _; mod dylib; From b0b2b1c5f1c4d4d989d0e21ebfe575db2cbf4e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 9 Jan 2024 10:00:57 +0200 Subject: [PATCH 062/297] Fix allow(dead_code) --- crates/hir-ty/src/layout/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs index ef0be7ab2daf..57214193cfbc 100644 --- a/crates/hir-ty/src/layout/tests.rs +++ b/crates/hir-ty/src/layout/tests.rs @@ -118,7 +118,7 @@ fn check_fail(ra_fixture: &str, e: LayoutError) { macro_rules! size_and_align { (minicore: $($x:tt),*;$($t:tt)*) => { { - #[allow(dead_code)] + #![allow(dead_code)] $($t)* check_size_and_align( stringify!($($t)*), @@ -130,7 +130,7 @@ macro_rules! size_and_align { }; ($($t:tt)*) => { { - #[allow(dead_code)] + #![allow(dead_code)] $($t)* check_size_and_align( stringify!($($t)*), From 4413aeb9e8a710bcbc11e90cb87f3ba7420c851f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 9 Jan 2024 10:27:36 +0200 Subject: [PATCH 063/297] Temporarily disable resolve_proc_macro test --- crates/rust-analyzer/tests/slow-tests/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index 78411e2d58d0..f76ff7db38c5 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -835,7 +835,7 @@ fn main() { #[cfg(any(feature = "sysroot-abi", rust_analyzer))] fn resolve_proc_macro() { use expect_test::expect; - if skip_slow_tests() { + if skip_slow_tests() || true { return; } From 3926ff5d20af9e75ecdfc7eacb4f988c57d46b9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 08:49:11 +0000 Subject: [PATCH 064/297] Bump follow-redirects from 1.15.2 to 1.15.4 in /editors/code Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.4. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.4) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] --- editors/code/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 8b9d5d4a7461..291cef926f82 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -2290,9 +2290,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true, "funding": [ { From e1c67485bf02bdaa1234df174a48aba402a2d707 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 10:30:16 +0100 Subject: [PATCH 065/297] fix: Differentiate between vfs config load and file changed events --- crates/load-cargo/src/lib.rs | 2 +- crates/project-model/src/workspace.rs | 2 +- crates/rust-analyzer/src/global_state.rs | 16 ++++++++-------- .../rust-analyzer/src/handlers/notification.rs | 6 ++++-- crates/rust-analyzer/src/main_loop.rs | 7 +++++-- crates/rust-analyzer/tests/slow-tests/main.rs | 2 +- crates/vfs-notify/src/lib.rs | 2 +- crates/vfs/src/loader.rs | 5 +++++ 8 files changed, 26 insertions(+), 16 deletions(-) diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index ee0b9e6d5040..e6ddfd580c30 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -322,7 +322,7 @@ fn load_crate_graph( break; } } - vfs::loader::Message::Loaded { files } => { + vfs::loader::Message::Loaded { files } | vfs::loader::Message::Changed { files } => { for (path, contents) in files { vfs.set_file_contents(path.into(), contents); } diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 00cc7c30ee3e..c04eddc56fb7 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -1398,7 +1398,7 @@ fn sysroot_to_crate_graph( let public_deps = SysrootPublicDeps { deps: sysroot .public_deps() - .map(|(name, idx, prelude)| (name, sysroot_crates[&idx], prelude)) + .filter_map(|(name, idx, prelude)| Some((name, *sysroot_crates.get(&idx)?, prelude))) .collect::>(), }; diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index da132f93968d..c4a29e0cbb03 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -218,7 +218,7 @@ impl GlobalState { let _p = profile::span("GlobalState::process_changes"); let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); - let (change, modified_files, workspace_structure_change) = { + let (change, modified_rust_files, workspace_structure_change) = { let mut change = Change::new(); let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); @@ -254,8 +254,8 @@ impl GlobalState { *change = Create(new); *just_created = true; } - // shouldn't occur, but collapse into `Modify` - (Modify(prev), _, Create(new)) => *prev = new, + // shouldn't occur, but keep the Create + (prev @ Modify(_), _, new @ Create(_)) => *prev = new, } } Entry::Vacant(v) => { @@ -276,7 +276,7 @@ impl GlobalState { // A file was added or deleted let mut has_structure_changes = false; let mut bytes = vec![]; - let mut modified_files = vec![]; + let mut modified_rust_files = vec![]; for file in changed_files { let vfs_path = &vfs.file_path(file.file_id); if let Some(path) = vfs_path.as_path() { @@ -288,8 +288,8 @@ impl GlobalState { has_structure_changes = true; workspace_structure_change = Some((path, self.crate_graph_file_dependencies.contains(vfs_path))); - } else { - modified_files.push(file.file_id); + } else if path.extension() == Some("rs".as_ref()) { + modified_rust_files.push(file.file_id); } } @@ -324,7 +324,7 @@ impl GlobalState { let roots = self.source_root_config.partition(vfs); change.set_roots(roots); } - (change, modified_files, workspace_structure_change) + (change, modified_rust_files, workspace_structure_change) }; self.analysis_host.apply_change(change); @@ -339,7 +339,7 @@ impl GlobalState { force_crate_graph_reload, ); } - self.proc_macro_changed = modified_files.into_iter().any(|file_id| { + self.proc_macro_changed = modified_rust_files.into_iter().any(|file_id| { let crates = raw_database.relevant_crates(file_id); let crate_graph = raw_database.crate_graph(); diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index c0d35498c665..ce69d612255a 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -101,8 +101,10 @@ pub(crate) fn handle_did_change_text_document( params.content_changes, ) .into_bytes(); - *data = new_contents.clone(); - state.vfs.write().0.set_file_contents(path, Some(new_contents)); + if *data != new_contents { + *data = new_contents.clone(); + state.vfs.write().0.set_file_contents(path, Some(new_contents)); + } } Ok(()) } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 356c332f90d9..ca7893faf5dd 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -571,15 +571,18 @@ impl GlobalState { } fn handle_vfs_msg(&mut self, message: vfs::loader::Message) { + let is_changed = matches!(message, vfs::loader::Message::Changed { .. }); match message { - vfs::loader::Message::Loaded { files } => { + vfs::loader::Message::Changed { files } | vfs::loader::Message::Loaded { files } => { let vfs = &mut self.vfs.write().0; for (path, contents) in files { let path = VfsPath::from(path); // if the file is in mem docs, it's managed by the client via notifications // so only set it if its not in there if !self.mem_docs.contains(&path) { - vfs.set_file_contents(path, contents); + if is_changed || vfs.file_id(&path).is_none() { + vfs.set_file_contents(path, contents); + } } } } diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index f76ff7db38c5..78411e2d58d0 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -835,7 +835,7 @@ fn main() { #[cfg(any(feature = "sysroot-abi", rust_analyzer))] fn resolve_proc_macro() { use expect_test::expect; - if skip_slow_tests() || true { + if skip_slow_tests() { return; } diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index 030650437146..19b34ffe6b9d 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs @@ -160,7 +160,7 @@ impl NotifyActor { Some((path, contents)) }) .collect(); - self.send(loader::Message::Loaded { files }); + self.send(loader::Message::Changed { files }); } } } diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs index e2d74782ae52..89a544c81d8c 100644 --- a/crates/vfs/src/loader.rs +++ b/crates/vfs/src/loader.rs @@ -51,6 +51,8 @@ pub enum Message { Progress { n_total: usize, n_done: usize, config_version: u32 }, /// The handle loaded the following files' content. Loaded { files: Vec<(AbsPathBuf, Option>)> }, + /// The handle loaded the following files' content. + Changed { files: Vec<(AbsPathBuf, Option>)> }, } /// Type that will receive [`Messages`](Message) from a [`Handle`]. @@ -199,6 +201,9 @@ impl fmt::Debug for Message { Message::Loaded { files } => { f.debug_struct("Loaded").field("n_files", &files.len()).finish() } + Message::Changed { files } => { + f.debug_struct("Changed").field("n_files", &files.len()).finish() + } Message::Progress { n_total, n_done, config_version } => f .debug_struct("Progress") .field("n_total", n_total) From a8c94eaf131cdadad07296fd1d69edeb51aa0970 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 16:28:18 +0100 Subject: [PATCH 066/297] fix: Fix rust-analyzer-proc-macro-srv failing to spawn on windows --- crates/proc-macro-api/src/process.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs index 3494164c0675..0f64f9195d84 100644 --- a/crates/proc-macro-api/src/process.rs +++ b/crates/proc-macro-api/src/process.rs @@ -131,12 +131,19 @@ impl Process { } fn mk_child(path: &AbsPath, null_stderr: bool) -> io::Result { - Command::new(path.as_os_str()) - .env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable") + let mut cmd = Command::new(path.as_os_str()); + cmd.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable") .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() }) - .spawn() + .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() }); + if cfg!(windows) { + let mut path_var = std::ffi::OsString::new(); + path_var.push(path.parent().unwrap().parent().unwrap().as_os_str()); + path_var.push("\\bin;"); + path_var.push(std::env::var_os("PATH").unwrap_or_default()); + cmd.env("PATH", path_var); + } + cmd.spawn() } fn send_request( From 21a953fe37635d5f37a49af5505f6391ed62e53d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 11:40:27 +0100 Subject: [PATCH 067/297] Recognize proc macro server unexpectedly exiting and report the exit code --- crates/proc-macro-api/src/lib.rs | 10 ++++-- crates/proc-macro-api/src/process.rs | 51 ++++++++++++++++++++++----- crates/proc-macro-srv-cli/src/main.rs | 3 +- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs index a87becd63e28..208051113a7d 100644 --- a/crates/proc-macro-api/src/lib.rs +++ b/crates/proc-macro-api/src/lib.rs @@ -14,8 +14,10 @@ mod version; use indexmap::IndexSet; use paths::AbsPathBuf; use span::Span; -use std::{fmt, io, sync::Mutex}; -use triomphe::Arc; +use std::{ + fmt, io, + sync::{Arc, Mutex}, +}; use serde::{Deserialize, Serialize}; @@ -81,9 +83,11 @@ impl PartialEq for ProcMacro { } } +#[derive(Clone, Debug)] pub struct ServerError { pub message: String, - pub io: Option, + // io::Error isn't Clone for some reason + pub io: Option>, } impl fmt::Display for ServerError { diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs index 3494164c0675..a22d8628f16f 100644 --- a/crates/proc-macro-api/src/process.rs +++ b/crates/proc-macro-api/src/process.rs @@ -1,8 +1,9 @@ //! Handle process life-time and message passing for proc-macro client use std::{ - io::{self, BufRead, BufReader, Write}, + io::{self, BufRead, BufReader, Read, Write}, process::{Child, ChildStdin, ChildStdout, Command, Stdio}, + sync::Arc, }; use paths::{AbsPath, AbsPathBuf}; @@ -15,9 +16,11 @@ use crate::{ #[derive(Debug)] pub(crate) struct ProcMacroProcessSrv { - _process: Process, + process: Process, stdin: ChildStdin, stdout: BufReader, + /// Populated when the server exits. + server_exited: Option, version: u32, mode: SpanMode, } @@ -29,9 +32,10 @@ impl ProcMacroProcessSrv { let (stdin, stdout) = process.stdio().expect("couldn't access child stdio"); io::Result::Ok(ProcMacroProcessSrv { - _process: process, + process, stdin, stdout, + server_exited: None, version: 0, mode: SpanMode::Id, }) @@ -105,8 +109,35 @@ impl ProcMacroProcessSrv { } pub(crate) fn send_task(&mut self, req: Request) -> Result { + if let Some(server_error) = &self.server_exited { + return Err(server_error.clone()); + } + let mut buf = String::new(); - send_request(&mut self.stdin, &mut self.stdout, req, &mut buf) + send_request(&mut self.stdin, &mut self.stdout, req, &mut buf).map_err(|e| { + if e.io.as_ref().map(|it| it.kind()) == Some(io::ErrorKind::BrokenPipe) { + match self.process.child.try_wait() { + Ok(None) => e, + Ok(Some(status)) => { + let mut msg = String::new(); + if !status.success() { + if let Some(stderr) = self.process.child.stderr.as_mut() { + _ = stderr.read_to_string(&mut msg); + } + } + let server_error = ServerError { + message: format!("server exited with {status}: {msg}"), + io: None, + }; + self.server_exited = Some(server_error.clone()); + server_error + } + Err(_) => e, + } + } else { + e + } + }) } } @@ -145,9 +176,13 @@ fn send_request( req: Request, buf: &mut String, ) -> Result { - req.write(&mut writer) - .map_err(|err| ServerError { message: "failed to write request".into(), io: Some(err) })?; - let res = Response::read(&mut reader, buf) - .map_err(|err| ServerError { message: "failed to read response".into(), io: Some(err) })?; + req.write(&mut writer).map_err(|err| ServerError { + message: "failed to write request".into(), + io: Some(Arc::new(err)), + })?; + let res = Response::read(&mut reader, buf).map_err(|err| ServerError { + message: "failed to read response".into(), + io: Some(Arc::new(err)), + })?; res.ok_or_else(|| ServerError { message: "server exited".into(), io: None }) } diff --git a/crates/proc-macro-srv-cli/src/main.rs b/crates/proc-macro-srv-cli/src/main.rs index 87f7555b02ce..af9a03826ffc 100644 --- a/crates/proc-macro-srv-cli/src/main.rs +++ b/crates/proc-macro-srv-cli/src/main.rs @@ -24,7 +24,8 @@ fn main() -> std::io::Result<()> { #[cfg(not(any(feature = "sysroot-abi", rust_analyzer)))] fn run() -> io::Result<()> { - panic!("proc-macro-srv-cli requires the `sysroot-abi` feature to be enabled"); + eprintln!("proc-macro-srv-cli requires the `sysroot-abi` feature to be enabled"); + std::process::exit(70); } #[cfg(any(feature = "sysroot-abi", rust_analyzer))] From 7a7bb3ef85ca2f827c39db9fd1594db5162cea13 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Mon, 8 Jan 2024 14:43:31 +0100 Subject: [PATCH 068/297] Backlog for HorizonOS UnixListener --- library/std/src/os/unix/net/listener.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index f6835472e2ca..8bf1e2dca6f7 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -73,7 +73,12 @@ impl UnixListener { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; let (addr, len) = sockaddr_un(path.as_ref())?; - #[cfg(any(target_os = "windows", target_os = "redox", target_os = "espidf"))] + #[cfg(any( + target_os = "windows", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + ))] const backlog: libc::c_int = 128; #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))] const backlog: libc::c_int = -1; @@ -83,7 +88,8 @@ impl UnixListener { target_os = "linux", target_os = "freebsd", target_os = "openbsd", - target_os = "espidf" + target_os = "espidf", + target_os = "horizon" )))] const backlog: libc::c_int = libc::SOMAXCONN; From 342ea154906163a678c257469823d7c7383014d6 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 10:08:47 +0100 Subject: [PATCH 069/297] Add tests --- tests/ui/pattern/never_patterns.rs | 23 ---------- tests/ui/pattern/never_patterns.stderr | 34 +-------------- .../rfcs/rfc-0000-never_patterns/bindings.rs | 28 ++++++++++++ .../rfc-0000-never_patterns/bindings.stderr | 43 +++++++++++++++++++ 4 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs index 915f3e75e7bf..eb2421204aed 100644 --- a/tests/ui/pattern/never_patterns.rs +++ b/tests/ui/pattern/never_patterns.rs @@ -74,26 +74,3 @@ fn never_pattern_location(void: Void) { Some(&(_, !)), } } - -fn never_and_bindings() { - let x: Result = Ok(false); - - // FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings. - match x { - Ok(_x) | Err(&!) => {} - //~^ ERROR: is not bound in all patterns - } - let (Ok(_x) | Err(&!)) = x; - //~^ ERROR: is not bound in all patterns - - // FIXME(never_patterns): A never pattern mustn't have bindings. - match x { - Ok(_) => {} - Err(&(_b, !)), - } - match x { - Ok(_a) | Err(&(_b, !)) => {} - //~^ ERROR: is not bound in all patterns - //~| ERROR: is not bound in all patterns - } -} diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr index 11e50debfd39..f3787f9816a2 100644 --- a/tests/ui/pattern/never_patterns.stderr +++ b/tests/ui/pattern/never_patterns.stderr @@ -14,38 +14,6 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref(); | | | variable not in all patterns -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:83:18 - | -LL | Ok(_x) | Err(&!) => {} - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:86:19 - | -LL | let (Ok(_x) | Err(&!)) = x; - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_b` is not bound in all patterns - --> $DIR/never_patterns.rs:95:9 - | -LL | Ok(_a) | Err(&(_b, !)) => {} - | ^^^^^^ -- variable not in all patterns - | | - | pattern doesn't bind `_b` - -error[E0408]: variable `_a` is not bound in all patterns - --> $DIR/never_patterns.rs:95:18 - | -LL | Ok(_a) | Err(&(_b, !)) => {} - | -- ^^^^^^^^^^^^^ pattern doesn't bind `_a` - | | - | variable not in all patterns - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs new file mode 100644 index 000000000000..61a4231e5da7 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -0,0 +1,28 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() { + let x: Result = Ok(false); + + // FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings. + match x { + Ok(_x) | Err(&!) => {} + //~^ ERROR: is not bound in all patterns + } + let (Ok(_x) | Err(&!)) = x; + //~^ ERROR: is not bound in all patterns + + // FIXME(never_patterns): A never pattern mustn't have bindings. + match x { + Ok(_) => {} + Err(&(_a, _b, !)), + } + match x { + Ok(_ok) | Err(&(_a, _b, !)) => {} + //~^ ERROR: is not bound in all patterns + //~| ERROR: is not bound in all patterns + //~| ERROR: is not bound in all patterns + } +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr new file mode 100644 index 000000000000..56cefcb51f38 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -0,0 +1,43 @@ +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/bindings.rs:11:18 + | +LL | Ok(_x) | Err(&!) => {} + | -- ^^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/bindings.rs:14:19 + | +LL | let (Ok(_x) | Err(&!)) = x; + | -- ^^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0408]: variable `_a` is not bound in all patterns + --> $DIR/bindings.rs:23:9 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | ^^^^^^^ -- variable not in all patterns + | | + | pattern doesn't bind `_a` + +error[E0408]: variable `_b` is not bound in all patterns + --> $DIR/bindings.rs:23:9 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | ^^^^^^^ -- variable not in all patterns + | | + | pattern doesn't bind `_b` + +error[E0408]: variable `_ok` is not bound in all patterns + --> $DIR/bindings.rs:23:19 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | --- ^^^^^^^^^^^^^^^^^ pattern doesn't bind `_ok` + | | + | variable not in all patterns + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0408`. From b31735a401941910f5ae2fbf06eba8594a1b2d4b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 22 Nov 2023 01:15:36 +0100 Subject: [PATCH 070/297] Tweak binding map computation --- compiler/rustc_resolve/src/late.rs | 54 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a82f7bdfbf3f..536ecd0fa241 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3190,11 +3190,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.resolve_pattern_top(&local.pat, PatternSource::Let); } - /// build a map from pattern identifiers to binding-info's. - /// this is done hygienically. This could arise for a macro - /// that expands into an or-pattern where one 'x' was from the - /// user and one 'x' came from the macro. - fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap { + /// Build a map from pattern identifiers to binding-info's, and check the bindings are + /// consistent when encountering or-patterns. + /// This is done hygienically: this could arise for a macro that expands into an or-pattern + /// where one 'x' was from the user and one 'x' came from the macro. + fn compute_and_check_binding_map(&mut self, pat: &Pat) -> FxIndexMap { let mut binding_map = FxIndexMap::default(); pat.walk(&mut |pat| { @@ -3207,9 +3207,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PatKind::Or(ref ps) => { // Check the consistency of this or-pattern and // then add all bindings to the larger map. - for bm in self.check_consistent_bindings(ps) { - binding_map.extend(bm); - } + let bm = self.compute_and_check_or_pat_binding_map(ps); + binding_map.extend(bm); return false; } _ => {} @@ -3228,18 +3227,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ) } - /// Checks that all of the arms in an or-pattern have exactly the - /// same set of bindings, with the same binding modes for each. - fn check_consistent_bindings( + /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern + /// have exactly the same set of bindings, with the same binding modes for each. + /// Returns the computed binding map. + fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P], - ) -> Vec> { - // pats is consistent. + ) -> FxIndexMap { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); // 1) Compute the binding maps of all arms. - let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::>(); + let maps = + pats.iter().map(|pat| self.compute_and_check_binding_map(pat)).collect::>(); // 2) Record any missing bindings or binding mode inconsistencies. for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) { @@ -3248,13 +3248,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { .iter() .zip(pats.iter()) .filter(|(_, pat)| pat.id != pat_outer.id) - .flat_map(|(map, _)| map) - .map(|(key, binding)| (key.name, map_outer.get(key), binding)); + .flat_map(|(map, _)| map); - let inners = inners.collect::>(); - - for (name, info, &binding_inner) in inners { - match info { + for (key, binding_inner) in inners { + let name = key.name; + match map_outer.get(key) { None => { // The inner binding is missing in the outer. let binding_error = @@ -3295,15 +3293,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1)); } - // 5) Finally bubble up all the binding maps. - maps + // 5) Bubble up the final binding map. + let mut binding_map = FxIndexMap::default(); + for bm in maps { + binding_map.extend(bm); + } + binding_map } - /// Check the consistency of the outermost or-patterns. - fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) { + /// Check the consistency of bindings wrt or-patterns. + fn check_consistent_bindings(&mut self, pat: &'ast Pat) { pat.walk(&mut |pat| match pat.kind { PatKind::Or(ref ps) => { - self.check_consistent_bindings(ps); + let _ = self.compute_and_check_or_pat_binding_map(ps); false } _ => true, @@ -3336,7 +3338,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { visit::walk_pat(self, pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: - self.check_consistent_bindings_top(pat); + self.check_consistent_bindings(pat); } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. From 560beb1ad423a9f3e447bdeefded8994cd8af75c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 10:11:18 +0100 Subject: [PATCH 071/297] Check bindings around never patterns --- compiler/rustc_resolve/messages.ftl | 4 ++ compiler/rustc_resolve/src/diagnostics.rs | 3 + compiler/rustc_resolve/src/errors.rs | 9 +++ compiler/rustc_resolve/src/late.rs | 59 ++++++++++++------- compiler/rustc_resolve/src/lib.rs | 2 + .../feature-gate-never_patterns.rs | 1 - .../feature-gate-never_patterns.stderr | 37 +++++------- tests/ui/pattern/never_patterns.rs | 5 +- tests/ui/pattern/never_patterns.stderr | 28 ++++----- .../rfcs/rfc-0000-never_patterns/bindings.rs | 11 ++-- .../rfc-0000-never_patterns/bindings.stderr | 47 +++++---------- .../ui/rfcs/rfc-0000-never_patterns/parse.rs | 1 + .../rfcs/rfc-0000-never_patterns/parse.stderr | 8 ++- 13 files changed, 110 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 3f8df16e03f7..c8ec10cad17c 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -36,6 +36,10 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = this would need to be a `{$suggestion}` +resolve_binding_in_never_pattern = + never patterns cannot contain variable bindings + .suggestion = use a wildcard `_` instead + resolve_binding_shadows_something_unacceptable = {$shadowing_binding}s cannot shadow {$shadowed_binding}s .label = cannot be named the same as {$article} {$shadowed_binding} diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c1cb20f6bb09..5f53733276ab 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -960,6 +960,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }), ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }), + ResolutionError::BindingInNeverPattern => { + self.dcx().create_err(errs::BindingInNeverPattern { span }) + } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 1fdb193e571f..821b1e946f31 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf { pub(crate) span: Span, } +#[derive(Debug)] +#[derive(Diagnostic)] +#[diag(resolve_binding_in_never_pattern)] +pub(crate) struct BindingInNeverPattern { + #[primary_span] + #[suggestion(code = "_", applicability = "machine-applicable", style = "short")] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(resolve_trait_impl_duplicate, code = "E0201")] pub(crate) struct TraitImplDuplicate { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 536ecd0fa241..90b278561612 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -65,6 +65,8 @@ enum IsRepeatExpr { Yes, } +struct IsNeverPattern; + /// Describes whether an `AnonConst` is a type level const arg or /// some other form of anon const (i.e. inline consts or enum discriminants) #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -3191,11 +3193,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } /// Build a map from pattern identifiers to binding-info's, and check the bindings are - /// consistent when encountering or-patterns. + /// consistent when encountering or-patterns and never patterns. /// This is done hygienically: this could arise for a macro that expands into an or-pattern /// where one 'x' was from the user and one 'x' came from the macro. - fn compute_and_check_binding_map(&mut self, pat: &Pat) -> FxIndexMap { + fn compute_and_check_binding_map( + &mut self, + pat: &Pat, + ) -> Result, IsNeverPattern> { let mut binding_map = FxIndexMap::default(); + let mut is_never_pat = false; pat.walk(&mut |pat| { match pat.kind { @@ -3207,17 +3213,26 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PatKind::Or(ref ps) => { // Check the consistency of this or-pattern and // then add all bindings to the larger map. - let bm = self.compute_and_check_or_pat_binding_map(ps); + let (bm, np) = self.compute_and_check_or_pat_binding_map(ps); binding_map.extend(bm); + is_never_pat |= np; return false; } + PatKind::Never => is_never_pat = true, _ => {} } true }); - binding_map + if is_never_pat { + for (_, binding) in binding_map { + self.report_error(binding.span, ResolutionError::BindingInNeverPattern); + } + Err(IsNeverPattern) + } else { + Ok(binding_map) + } } fn is_base_res_local(&self, nid: NodeId) -> bool { @@ -3229,24 +3244,29 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern /// have exactly the same set of bindings, with the same binding modes for each. - /// Returns the computed binding map. + /// Returns the computed binding map and a boolean indicating whether the pattern is a never + /// pattern. fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P], - ) -> FxIndexMap { + ) -> (FxIndexMap, bool) { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); - // 1) Compute the binding maps of all arms. - let maps = - pats.iter().map(|pat| self.compute_and_check_binding_map(pat)).collect::>(); + // 1) Compute the binding maps of all arms; never patterns don't participate in this. + let not_never_pats = pats + .iter() + .filter_map(|pat| { + let binding_map = self.compute_and_check_binding_map(pat).ok()?; + Some((binding_map, pat)) + }) + .collect::>(); // 2) Record any missing bindings or binding mode inconsistencies. - for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) { + for (map_outer, pat_outer) in not_never_pats.iter() { // Check against all arms except for the same pattern which is always self-consistent. - let inners = maps + let inners = not_never_pats .iter() - .zip(pats.iter()) .filter(|(_, pat)| pat.id != pat_outer.id) .flat_map(|(map, _)| map); @@ -3294,22 +3314,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } // 5) Bubble up the final binding map. + let is_never_pat = not_never_pats.is_empty(); let mut binding_map = FxIndexMap::default(); - for bm in maps { + for (bm, _) in not_never_pats { binding_map.extend(bm); } - binding_map + (binding_map, is_never_pat) } - /// Check the consistency of bindings wrt or-patterns. + /// Check the consistency of bindings wrt or-patterns and never patterns. fn check_consistent_bindings(&mut self, pat: &'ast Pat) { - pat.walk(&mut |pat| match pat.kind { - PatKind::Or(ref ps) => { - let _ = self.compute_and_check_or_pat_binding_map(ps); - false - } - _ => true, - }) + let _ = self.compute_and_check_binding_map(pat); } fn resolve_arm(&mut self, arm: &'ast Arm) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a14f3d494fb4..5a9bf22de51e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -265,6 +265,8 @@ enum ResolutionError<'a> { InvalidAsmSym, /// `self` used instead of `Self` in a generic parameter LowercaseSelf, + /// A never pattern has a binding. + BindingInNeverPattern, } enum VisResolutionError<'a> { diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs index f3910622313d..d23405ada2d4 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.rs +++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs @@ -7,7 +7,6 @@ fn main() { let res: Result = Ok(0); let (Ok(_x) | Err(&!)) = res.as_ref(); //~^ ERROR `!` patterns are experimental - //~| ERROR: is not bound in all patterns unsafe { let ptr: *const Void = NonNull::dangling().as_ptr(); diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr index dd10829d4959..3181dac69e52 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr @@ -1,5 +1,5 @@ error: unexpected `,` in pattern - --> $DIR/feature-gate-never_patterns.rs:34:16 + --> $DIR/feature-gate-never_patterns.rs:33:16 | LL | Some(_), | ^ @@ -13,14 +13,6 @@ help: ...or a vertical bar to match on multiple alternatives LL | Some(_) | | -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/feature-gate-never_patterns.rs:8:19 - | -LL | let (Ok(_x) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - error[E0658]: `!` patterns are experimental --> $DIR/feature-gate-never_patterns.rs:8:24 | @@ -31,7 +23,7 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref(); = help: add `#![feature(never_patterns)]` to the crate attributes to enable error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:15:13 + --> $DIR/feature-gate-never_patterns.rs:14:13 | LL | ! | ^ @@ -40,7 +32,7 @@ LL | ! = help: add `#![feature(never_patterns)]` to the crate attributes to enable error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:21:13 + --> $DIR/feature-gate-never_patterns.rs:20:13 | LL | ! | ^ @@ -49,7 +41,7 @@ LL | ! = help: add `#![feature(never_patterns)]` to the crate attributes to enable error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:26:13 + --> $DIR/feature-gate-never_patterns.rs:25:13 | LL | ! => {} | ^ @@ -58,25 +50,25 @@ LL | ! => {} = help: add `#![feature(never_patterns)]` to the crate attributes to enable error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:39:9 + --> $DIR/feature-gate-never_patterns.rs:38:9 | LL | Some(_) | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:44:9 + --> $DIR/feature-gate-never_patterns.rs:43:9 | LL | Some(_) if false, | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:46:9 + --> $DIR/feature-gate-never_patterns.rs:45:9 | LL | Some(_) if false | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:51:13 + --> $DIR/feature-gate-never_patterns.rs:50:13 | LL | Err(!), | ^ @@ -85,7 +77,7 @@ LL | Err(!), = help: add `#![feature(never_patterns)]` to the crate attributes to enable error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:55:13 + --> $DIR/feature-gate-never_patterns.rs:54:13 | LL | Err(!) if false, | ^ @@ -94,24 +86,23 @@ LL | Err(!) if false, = help: add `#![feature(never_patterns)]` to the crate attributes to enable error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:65:9 + --> $DIR/feature-gate-never_patterns.rs:64:9 | LL | Some(_) | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:71:9 + --> $DIR/feature-gate-never_patterns.rs:70:9 | LL | Some(_) if false | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: a guard on a never pattern will never be run - --> $DIR/feature-gate-never_patterns.rs:55:19 + --> $DIR/feature-gate-never_patterns.rs:54:19 | LL | Err(!) if false, | ^^^^^ help: remove this guard -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors -Some errors have detailed explanations: E0408, E0658. -For more information about an error, try `rustc --explain E0408`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs index eb2421204aed..8f44f8a65593 100644 --- a/tests/ui/pattern/never_patterns.rs +++ b/tests/ui/pattern/never_patterns.rs @@ -7,12 +7,9 @@ fn main() {} // The classic use for empty types. fn safe_unwrap_result(res: Result) { - let Ok(_x) = res; - // FIXME(never_patterns): These should be allowed + let Ok(_x) = res; //~ ERROR refutable pattern in local binding let (Ok(_x) | Err(!)) = &res; - //~^ ERROR: is not bound in all patterns let (Ok(_x) | Err(&!)) = res.as_ref(); - //~^ ERROR: is not bound in all patterns } // Check we only accept `!` where we want to. diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr index f3787f9816a2..20eeb01cf714 100644 --- a/tests/ui/pattern/never_patterns.stderr +++ b/tests/ui/pattern/never_patterns.stderr @@ -1,19 +1,17 @@ -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:12:19 +error[E0005]: refutable pattern in local binding + --> $DIR/never_patterns.rs:10:9 | -LL | let (Ok(_x) | Err(!)) = &res; - | -- ^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:14:19 +LL | let Ok(_x) = res; + | ^^^^^^ pattern `Err(_)` not covered | -LL | let (Ok(_x) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = res else { todo!() }; + | ++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0408`. +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs index 61a4231e5da7..756ead9e184e 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -6,23 +6,20 @@ enum Void {} fn main() { let x: Result = Ok(false); - // FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings. match x { Ok(_x) | Err(&!) => {} - //~^ ERROR: is not bound in all patterns } let (Ok(_x) | Err(&!)) = x; - //~^ ERROR: is not bound in all patterns - // FIXME(never_patterns): A never pattern mustn't have bindings. match x { Ok(_) => {} Err(&(_a, _b, !)), + //~^ ERROR: never patterns cannot contain variable bindings + //~| ERROR: never patterns cannot contain variable bindings } match x { Ok(_ok) | Err(&(_a, _b, !)) => {} - //~^ ERROR: is not bound in all patterns - //~| ERROR: is not bound in all patterns - //~| ERROR: is not bound in all patterns + //~^ ERROR: never patterns cannot contain variable bindings + //~| ERROR: never patterns cannot contain variable bindings } } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr index 56cefcb51f38..4e83b843ae85 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -1,43 +1,26 @@ -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/bindings.rs:11:18 +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:16:15 | -LL | Ok(_x) | Err(&!) => {} - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns +LL | Err(&(_a, _b, !)), + | ^^ help: use a wildcard `_` instead -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/bindings.rs:14:19 +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:16:19 | -LL | let (Ok(_x) | Err(&!)) = x; - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns +LL | Err(&(_a, _b, !)), + | ^^ help: use a wildcard `_` instead -error[E0408]: variable `_a` is not bound in all patterns - --> $DIR/bindings.rs:23:9 +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:21:25 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} - | ^^^^^^^ -- variable not in all patterns - | | - | pattern doesn't bind `_a` + | ^^ help: use a wildcard `_` instead -error[E0408]: variable `_b` is not bound in all patterns - --> $DIR/bindings.rs:23:9 +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:21:29 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} - | ^^^^^^^ -- variable not in all patterns - | | - | pattern doesn't bind `_b` + | ^^ help: use a wildcard `_` instead -error[E0408]: variable `_ok` is not bound in all patterns - --> $DIR/bindings.rs:23:19 - | -LL | Ok(_ok) | Err(&(_a, _b, !)) => {} - | --- ^^^^^^^^^^^^^^^^^ pattern doesn't bind `_ok` - | | - | variable not in all patterns +error: aborting due to 4 previous errors -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs index f254b9c201c1..566bb0716464 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs @@ -71,6 +71,7 @@ fn parse(x: Void) { let ! = x; let y @ ! = x; + //~^ ERROR: never patterns cannot contain variable bindings } fn foo(!: Void) {} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr index e81a13a3967c..17d1b7e0d43b 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr @@ -22,6 +22,12 @@ error: top-level or-patterns are not allowed in `let` bindings LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048. | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))` +error: never patterns cannot contain variable bindings + --> $DIR/parse.rs:73:9 + | +LL | let y @ ! = x; + | ^ help: use a wildcard `_` instead + error: a guard on a never pattern will never be run --> $DIR/parse.rs:31:20 | @@ -40,5 +46,5 @@ error: a guard on a never pattern will never be run LL | never!() if true, | ^^^^ help: remove this guard -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors From 807d618676052befa3e621dc42e7be0b4c5f1576 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 9 Jan 2024 17:05:55 +0100 Subject: [PATCH 072/297] Only check bindings if the pattern is an or- or never- pattern --- compiler/rustc_resolve/src/late.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 90b278561612..2a8bf1fe2d3c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3324,7 +3324,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Check the consistency of bindings wrt or-patterns and never patterns. fn check_consistent_bindings(&mut self, pat: &'ast Pat) { - let _ = self.compute_and_check_binding_map(pat); + let mut is_or_or_never = false; + pat.walk(&mut |pat| match pat.kind { + PatKind::Or(..) | PatKind::Never => { + is_or_or_never = true; + false + } + _ => true, + }); + if is_or_or_never { + let _ = self.compute_and_check_binding_map(pat); + } } fn resolve_arm(&mut self, arm: &'ast Arm) { From 223cda41071416c20d3d1db458ce7c6c789e2b08 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 9 Jan 2024 17:04:20 +0100 Subject: [PATCH 073/297] Use `Result<_, IsNeverPattern>` consistently --- compiler/rustc_resolve/src/late.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2a8bf1fe2d3c..5c246893d87d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3213,9 +3213,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PatKind::Or(ref ps) => { // Check the consistency of this or-pattern and // then add all bindings to the larger map. - let (bm, np) = self.compute_and_check_or_pat_binding_map(ps); - binding_map.extend(bm); - is_never_pat |= np; + match self.compute_and_check_or_pat_binding_map(ps) { + Ok(bm) => binding_map.extend(bm), + Err(IsNeverPattern) => is_never_pat = true, + } return false; } PatKind::Never => is_never_pat = true, @@ -3249,7 +3250,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P], - ) -> (FxIndexMap, bool) { + ) -> Result, IsNeverPattern> { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); @@ -3314,12 +3315,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } // 5) Bubble up the final binding map. - let is_never_pat = not_never_pats.is_empty(); - let mut binding_map = FxIndexMap::default(); - for (bm, _) in not_never_pats { - binding_map.extend(bm); + if not_never_pats.is_empty() { + // All the patterns are never patterns, so the whole or-pattern is one too. + Err(IsNeverPattern) + } else { + let mut binding_map = FxIndexMap::default(); + for (bm, _) in not_never_pats { + binding_map.extend(bm); + } + Ok(binding_map) } - (binding_map, is_never_pat) } /// Check the consistency of bindings wrt or-patterns and never patterns. From 06aaf20f1000fca742fdb84f016d46c45b6f36d6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 20:43:17 +0100 Subject: [PATCH 074/297] Some minor perf improvements --- crates/base-db/src/lib.rs | 1 + crates/hir-def/src/generics.rs | 241 ++++++++++++++----------- crates/hir-def/src/hir/type_ref.rs | 3 +- crates/hir-def/src/item_tree/lower.rs | 12 +- crates/hir-ty/src/lower.rs | 2 +- crates/hir-ty/src/method_resolution.rs | 45 ++--- crates/ide-db/src/apply_change.rs | 143 ++++++++------- crates/ide-db/src/lib.rs | 11 +- crates/ide/src/lib.rs | 2 +- 9 files changed, 242 insertions(+), 218 deletions(-) diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index a0a55df5f99a..28931676eedd 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -44,6 +44,7 @@ pub trait Upcast { } pub const DEFAULT_PARSE_LRU_CAP: usize = 128; +pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256; pub trait FileLoader { /// Text of the file. diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index f5324f052e59..26a836f25e92 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -107,11 +107,11 @@ impl TypeOrConstParamData { impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData); /// Data about the generic parameters of a function, struct, impl, etc. -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct GenericParams { pub type_or_consts: Arena, pub lifetimes: Arena, - pub where_predicates: Vec, + pub where_predicates: Box<[WherePredicate]>, } /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined @@ -142,109 +142,14 @@ pub enum WherePredicateTypeTarget { TypeOrConstParam(LocalTypeOrConstParamId), } -impl GenericParams { - /// Iterator of type_or_consts field - pub fn iter( - &self, - ) -> impl DoubleEndedIterator, &TypeOrConstParamData)> { - self.type_or_consts.iter() - } - - pub(crate) fn generic_params_query( - db: &dyn DefDatabase, - def: GenericDefId, - ) -> Interned { - let _p = profile::span("generic_params_query"); - - let krate = def.module(db).krate; - let cfg_options = db.crate_graph(); - let cfg_options = &cfg_options[krate].cfg_options; - - // Returns the generic parameters that are enabled under the current `#[cfg]` options - let enabled_params = |params: &Interned, item_tree: &ItemTree| { - let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); - - // In the common case, no parameters will by disabled by `#[cfg]` attributes. - // Therefore, make a first pass to check if all parameters are enabled and, if so, - // clone the `Interned` instead of recreating an identical copy. - let all_type_or_consts_enabled = - params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); - let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); - - if all_type_or_consts_enabled && all_lifetimes_enabled { - params.clone() - } else { - Interned::new(GenericParams { - type_or_consts: all_type_or_consts_enabled - .then(|| params.type_or_consts.clone()) - .unwrap_or_else(|| { - params - .type_or_consts - .iter() - .filter_map(|(idx, param)| { - enabled(idx.into()).then(|| param.clone()) - }) - .collect() - }), - lifetimes: all_lifetimes_enabled - .then(|| params.lifetimes.clone()) - .unwrap_or_else(|| { - params - .lifetimes - .iter() - .filter_map(|(idx, param)| { - enabled(idx.into()).then(|| param.clone()) - }) - .collect() - }), - where_predicates: params.where_predicates.clone(), - }) - } - }; - macro_rules! id_to_generics { - ($id:ident) => {{ - let id = $id.lookup(db).id; - let tree = id.item_tree(db); - let item = &tree[id.value]; - enabled_params(&item.generic_params, &tree) - }}; - } - - match def { - GenericDefId::FunctionId(id) => { - let loc = id.lookup(db); - let tree = loc.id.item_tree(db); - let item = &tree[loc.id.value]; - - let enabled_params = enabled_params(&item.explicit_generic_params, &tree); - let mut generic_params = GenericParams::clone(&enabled_params); - - let module = loc.container.module(db); - let func_data = db.function_data(id); - - // Don't create an `Expander` if not needed since this - // could cause a reparse after the `ItemTree` has been created due to the spanmap. - let mut expander = - Lazy::new(|| (module.def_map(db), Expander::new(db, loc.id.file_id(), module))); - for param in func_data.params.iter() { - generic_params.fill_implicit_impl_trait_args(db, &mut expander, param); - } - - Interned::new(generic_params) - } - GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id), - GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id), - GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id), - GenericDefId::TraitId(id) => id_to_generics!(id), - GenericDefId::TraitAliasId(id) => id_to_generics!(id), - GenericDefId::TypeAliasId(id) => id_to_generics!(id), - GenericDefId::ImplId(id) => id_to_generics!(id), - GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { - Interned::new(GenericParams::default()) - } - } - } +#[derive(Clone, Default)] +pub(crate) struct GenericParamsCollector { + pub type_or_consts: Arena, + pub lifetimes: Arena, + pub where_predicates: Vec, +} +impl GenericParamsCollector { pub(crate) fn fill( &mut self, lower_ctx: &LowerCtx<'_>, @@ -444,11 +349,131 @@ impl GenericParams { }); } - pub(crate) fn shrink_to_fit(&mut self) { - let Self { lifetimes, type_or_consts: types, where_predicates } = self; + pub(crate) fn finish(self) -> GenericParams { + let Self { mut lifetimes, mut type_or_consts, where_predicates } = self; lifetimes.shrink_to_fit(); - types.shrink_to_fit(); - where_predicates.shrink_to_fit(); + type_or_consts.shrink_to_fit(); + GenericParams { + type_or_consts, + lifetimes, + where_predicates: where_predicates.into_boxed_slice(), + } + } +} + +impl GenericParams { + /// Iterator of type_or_consts field + pub fn iter( + &self, + ) -> impl DoubleEndedIterator, &TypeOrConstParamData)> { + self.type_or_consts.iter() + } + + pub(crate) fn generic_params_query( + db: &dyn DefDatabase, + def: GenericDefId, + ) -> Interned { + let _p = profile::span("generic_params_query"); + + let krate = def.module(db).krate; + let cfg_options = db.crate_graph(); + let cfg_options = &cfg_options[krate].cfg_options; + + // Returns the generic parameters that are enabled under the current `#[cfg]` options + let enabled_params = |params: &Interned, item_tree: &ItemTree| { + let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); + + // In the common case, no parameters will by disabled by `#[cfg]` attributes. + // Therefore, make a first pass to check if all parameters are enabled and, if so, + // clone the `Interned` instead of recreating an identical copy. + let all_type_or_consts_enabled = + params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); + let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); + + if all_type_or_consts_enabled && all_lifetimes_enabled { + params.clone() + } else { + Interned::new(GenericParams { + type_or_consts: all_type_or_consts_enabled + .then(|| params.type_or_consts.clone()) + .unwrap_or_else(|| { + params + .type_or_consts + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + lifetimes: all_lifetimes_enabled + .then(|| params.lifetimes.clone()) + .unwrap_or_else(|| { + params + .lifetimes + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + where_predicates: params.where_predicates.clone(), + }) + } + }; + macro_rules! id_to_generics { + ($id:ident) => {{ + let id = $id.lookup(db).id; + let tree = id.item_tree(db); + let item = &tree[id.value]; + enabled_params(&item.generic_params, &tree) + }}; + } + + match def { + GenericDefId::FunctionId(id) => { + let loc = id.lookup(db); + let tree = loc.id.item_tree(db); + let item = &tree[loc.id.value]; + + let enabled_params = enabled_params(&item.explicit_generic_params, &tree); + + let module = loc.container.module(db); + let func_data = db.function_data(id); + if func_data.params.is_empty() { + enabled_params + } else { + let mut generic_params = GenericParamsCollector { + type_or_consts: enabled_params.type_or_consts.clone(), + lifetimes: enabled_params.lifetimes.clone(), + where_predicates: enabled_params.where_predicates.clone().into(), + }; + + // Don't create an `Expander` if not needed since this + // could cause a reparse after the `ItemTree` has been created due to the spanmap. + let mut expander = Lazy::new(|| { + (module.def_map(db), Expander::new(db, loc.id.file_id(), module)) + }); + for param in func_data.params.iter() { + generic_params.fill_implicit_impl_trait_args(db, &mut expander, param); + } + Interned::new(generic_params.finish()) + } + } + GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id), + GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id), + GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id), + GenericDefId::TraitId(id) => id_to_generics!(id), + GenericDefId::TraitAliasId(id) => id_to_generics!(id), + GenericDefId::TypeAliasId(id) => id_to_generics!(id), + GenericDefId::ImplId(id) => id_to_generics!(id), + GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { + Interned::new(GenericParams { + type_or_consts: Default::default(), + lifetimes: Default::default(), + where_predicates: Default::default(), + }) + } + } } pub fn find_type_by_name(&self, name: &Name, parent: GenericDefId) -> Option { diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index 75adf21abdcb..935a8ebad165 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -116,8 +116,7 @@ pub enum TypeRef { Path(Path), RawPtr(Box, Mutability), Reference(Box, Option, Mutability), - // FIXME: for full const generics, the latter element (length) here is going to have to be an - // expression that is further lowered later in hir_ty. + // FIXME: This should be Array(Box, Ast), Array(Box, ConstRef), Slice(Box), /// A fn pointer. Last element of the vector is the return type. diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 8e2fafe81b50..6343b43a016b 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId}; use syntax::ast::{self, HasModuleItem, HasTypeBounds}; use crate::{ - generics::{GenericParams, TypeParamData, TypeParamProvenance}, + generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, type_ref::{LifetimeRef, TraitBoundModifier, TraitRef}, LocalLifetimeParamId, LocalTypeOrConstParamId, }; @@ -386,17 +386,16 @@ impl<'a> Ctx<'a> { flags |= FnFlags::HAS_UNSAFE_KW; } - let mut res = Function { + let res = Function { name, visibility, - explicit_generic_params: Interned::new(GenericParams::default()), + explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func), abi, params, ret_type: Interned::new(ret_type), ast_id, flags, }; - res.explicit_generic_params = self.lower_generic_params(HasImplicitSelf::No, func); Some(id(self.data().functions.alloc(res))) } @@ -604,7 +603,7 @@ impl<'a> Ctx<'a> { has_implicit_self: HasImplicitSelf, node: &dyn ast::HasGenericParams, ) -> Interned { - let mut generics = GenericParams::default(); + let mut generics = GenericParamsCollector::default(); if let HasImplicitSelf::Yes(bounds) = has_implicit_self { // Traits and trait aliases get the Self type as an implicit first type parameter. @@ -642,8 +641,7 @@ impl<'a> Ctx<'a> { }; generics.fill(&self.body_ctx, node, add_param_attrs); - generics.shrink_to_fit(); - Interned::new(generics) + Interned::new(generics.finish()) } fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned]> { diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 97c4a741ff2a..e371e4276156 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1601,7 +1601,7 @@ fn implicitly_sized_clauses<'a>( pub(crate) fn generic_defaults_query( db: &dyn HirDatabase, def: GenericDefId, -) -> Arc<[Binders>]> { +) -> Arc<[Binders]> { let resolver = def.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 33619edfee93..3b1697a07b07 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -132,34 +132,33 @@ pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)), ]; +type TraitFpMap = FxHashMap, Box<[ImplId]>>>; +type TraitFpMapCollector = FxHashMap, Vec>>; + /// Trait impls defined or available in some crate. #[derive(Debug, Eq, PartialEq)] pub struct TraitImpls { // If the `Option` is `None`, the impl may apply to any self type. - map: FxHashMap, Vec>>, + map: TraitFpMap, } impl TraitImpls { pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc { let _p = profile::span("trait_impls_in_crate_query").detail(|| format!("{krate:?}")); - let mut impls = Self { map: FxHashMap::default() }; + let mut impls = FxHashMap::default(); - let crate_def_map = db.crate_def_map(krate); - impls.collect_def_map(db, &crate_def_map); - impls.shrink_to_fit(); + Self::collect_def_map(db, &mut impls, &db.crate_def_map(krate)); - Arc::new(impls) + Arc::new(Self::finish(impls)) } pub(crate) fn trait_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc { let _p = profile::span("trait_impls_in_block_query"); - let mut impls = Self { map: FxHashMap::default() }; + let mut impls = FxHashMap::default(); - let block_def_map = db.block_def_map(block); - impls.collect_def_map(db, &block_def_map); - impls.shrink_to_fit(); + Self::collect_def_map(db, &mut impls, &db.block_def_map(block)); - Arc::new(impls) + Arc::new(Self::finish(impls)) } pub(crate) fn trait_impls_in_deps_query( @@ -174,15 +173,16 @@ impl TraitImpls { ) } - fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit(); - self.map.values_mut().for_each(|map| { - map.shrink_to_fit(); - map.values_mut().for_each(Vec::shrink_to_fit); - }); + fn finish(map: TraitFpMapCollector) -> TraitImpls { + TraitImpls { + map: map + .into_iter() + .map(|(k, v)| (k, v.into_iter().map(|(k, v)| (k, v.into_boxed_slice())).collect())) + .collect(), + } } - fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) { + fn collect_def_map(db: &dyn HirDatabase, map: &mut TraitFpMapCollector, def_map: &DefMap) { for (_module_id, module_data) in def_map.modules() { for impl_id in module_data.scope.impls() { // Reservation impls should be ignored during trait resolution, so we never need @@ -200,12 +200,7 @@ impl TraitImpls { }; let self_ty = db.impl_self_ty(impl_id); let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders()); - self.map - .entry(target_trait) - .or_default() - .entry(self_ty_fp) - .or_default() - .push(impl_id); + map.entry(target_trait).or_default().entry(self_ty_fp).or_default().push(impl_id); } // To better support custom derives, collect impls in all unnamed const items. @@ -213,7 +208,7 @@ impl TraitImpls { for konst in collect_unnamed_consts(db, &module_data.scope) { let body = db.body(konst.into()); for (_, block_def_map) in body.blocks(db.upcast()) { - self.collect_def_map(db, &block_def_map); + Self::collect_def_map(db, map, &block_def_map); } } } diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index db6cd128e83d..6399f83c4756 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -84,26 +84,53 @@ impl RootDatabase { )*} } purge_each_query![ - // SourceDatabase - base_db::ParseQuery - base_db::CrateGraphQuery - - // SourceDatabaseExt - base_db::FileTextQuery - base_db::FileSourceRootQuery - base_db::SourceRootQuery - base_db::SourceRootCratesQuery - - // ExpandDatabase - hir::db::AstIdMapQuery - hir::db::DeclMacroExpanderQuery - hir::db::ExpandProcMacroQuery - hir::db::InternMacroCallQuery - hir::db::InternSyntaxContextQuery - hir::db::MacroArgQuery - hir::db::ParseMacroExpansionQuery - hir::db::RealSpanMapQuery - hir::db::ProcMacrosQuery + // SymbolsDatabase + crate::symbol_index::ModuleSymbolsQuery + crate::symbol_index::LibrarySymbolsQuery + crate::symbol_index::LocalRootsQuery + crate::symbol_index::LibraryRootsQuery + // HirDatabase + hir::db::InferQueryQuery + hir::db::MirBodyQuery + hir::db::BorrowckQuery + hir::db::TyQuery + hir::db::ValueTyQuery + hir::db::ImplSelfTyQuery + hir::db::ConstParamTyQuery + hir::db::ConstEvalQuery + hir::db::ConstEvalDiscriminantQuery + hir::db::ImplTraitQuery + hir::db::FieldTypesQuery + hir::db::LayoutOfAdtQuery + hir::db::TargetDataLayoutQuery + hir::db::CallableItemSignatureQuery + hir::db::ReturnTypeImplTraitsQuery + hir::db::GenericPredicatesForParamQuery + hir::db::GenericPredicatesQuery + hir::db::TraitEnvironmentQuery + hir::db::GenericDefaultsQuery + hir::db::InherentImplsInCrateQuery + hir::db::InherentImplsInBlockQuery + hir::db::IncoherentInherentImplCratesQuery + hir::db::TraitImplsInCrateQuery + hir::db::TraitImplsInBlockQuery + hir::db::TraitImplsInDepsQuery + hir::db::InternCallableDefQuery + hir::db::InternLifetimeParamIdQuery + hir::db::InternImplTraitIdQuery + hir::db::InternTypeOrConstParamIdQuery + hir::db::InternClosureQuery + hir::db::InternGeneratorQuery + hir::db::AssociatedTyDataQuery + hir::db::TraitDatumQuery + hir::db::StructDatumQuery + hir::db::ImplDatumQuery + hir::db::FnDefDatumQuery + hir::db::FnDefVarianceQuery + hir::db::AdtVarianceQuery + hir::db::AssociatedTyValueQuery + hir::db::TraitSolveQueryQuery + hir::db::ProgramClausesForChalkEnvQuery // DefDatabase hir::db::FileItemTreeQuery @@ -151,58 +178,6 @@ impl RootDatabase { hir::db::InternInTypeConstQuery hir::db::InternUseQuery - // HirDatabase - hir::db::InferQueryQuery - hir::db::MirBodyQuery - hir::db::BorrowckQuery - hir::db::TyQuery - hir::db::ValueTyQuery - hir::db::ImplSelfTyQuery - hir::db::ConstParamTyQuery - hir::db::ConstEvalQuery - hir::db::ConstEvalDiscriminantQuery - hir::db::ImplTraitQuery - hir::db::FieldTypesQuery - hir::db::LayoutOfAdtQuery - hir::db::TargetDataLayoutQuery - hir::db::CallableItemSignatureQuery - hir::db::ReturnTypeImplTraitsQuery - hir::db::GenericPredicatesForParamQuery - hir::db::GenericPredicatesQuery - hir::db::TraitEnvironmentQuery - hir::db::GenericDefaultsQuery - hir::db::InherentImplsInCrateQuery - hir::db::InherentImplsInBlockQuery - hir::db::IncoherentInherentImplCratesQuery - hir::db::TraitImplsInCrateQuery - hir::db::TraitImplsInBlockQuery - hir::db::TraitImplsInDepsQuery - hir::db::InternCallableDefQuery - hir::db::InternLifetimeParamIdQuery - hir::db::InternImplTraitIdQuery - hir::db::InternTypeOrConstParamIdQuery - hir::db::InternClosureQuery - hir::db::InternGeneratorQuery - hir::db::AssociatedTyDataQuery - hir::db::TraitDatumQuery - hir::db::StructDatumQuery - hir::db::ImplDatumQuery - hir::db::FnDefDatumQuery - hir::db::FnDefVarianceQuery - hir::db::AdtVarianceQuery - hir::db::AssociatedTyValueQuery - hir::db::TraitSolveQueryQuery - hir::db::ProgramClausesForChalkEnvQuery - - // SymbolsDatabase - crate::symbol_index::ModuleSymbolsQuery - crate::symbol_index::LibrarySymbolsQuery - crate::symbol_index::LocalRootsQuery - crate::symbol_index::LibraryRootsQuery - - // LineIndexDatabase - crate::LineIndexQuery - // InternDatabase hir::db::InternFunctionQuery hir::db::InternStructQuery @@ -219,6 +194,30 @@ impl RootDatabase { hir::db::InternMacro2Query hir::db::InternProcMacroQuery hir::db::InternMacroRulesQuery + + // ExpandDatabase + hir::db::AstIdMapQuery + hir::db::DeclMacroExpanderQuery + hir::db::ExpandProcMacroQuery + hir::db::InternMacroCallQuery + hir::db::InternSyntaxContextQuery + hir::db::MacroArgQuery + hir::db::ParseMacroExpansionQuery + hir::db::RealSpanMapQuery + hir::db::ProcMacrosQuery + + // LineIndexDatabase + crate::LineIndexQuery + + // SourceDatabase + base_db::ParseQuery + base_db::CrateGraphQuery + + // SourceDatabaseExt + base_db::FileTextQuery + base_db::FileSourceRootQuery + base_db::SourceRootQuery + base_db::SourceRootCratesQuery ]; acc.sort_by_key(|it| std::cmp::Reverse(it.1)); diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 128971994f64..79531936fde4 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -145,7 +145,7 @@ impl RootDatabase { db.set_local_roots_with_durability(Default::default(), Durability::HIGH); db.set_library_roots_with_durability(Default::default(), Durability::HIGH); db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH); - db.update_parse_query_lru_capacity(lru_capacity); + db.update_base_query_lru_capacities(lru_capacity); db.setup_syntax_context_root(); db } @@ -154,11 +154,12 @@ impl RootDatabase { self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); } - pub fn update_parse_query_lru_capacity(&mut self, lru_capacity: Option) { + pub fn update_base_query_lru_capacities(&mut self, lru_capacity: Option) { let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP); base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity); // macro expansions are usually rather small, so we can afford to keep more of them alive hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(4 * lru_capacity); + hir::db::BorrowckQuery.in_db_mut(self).set_lru_capacity(base_db::DEFAULT_BORROWCK_LRU_CAP); } pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap, usize>) { @@ -176,6 +177,12 @@ impl RootDatabase { .copied() .unwrap_or(4 * base_db::DEFAULT_PARSE_LRU_CAP), ); + hir_db::BorrowckQuery.in_db_mut(self).set_lru_capacity( + lru_capacities + .get(stringify!(BorrowckQuery)) + .copied() + .unwrap_or(base_db::DEFAULT_BORROWCK_LRU_CAP), + ); macro_rules! update_lru_capacity_per_query { ($( $module:ident :: $query:ident )*) => {$( diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index c98e9fba120a..60a9367adcee 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -171,7 +171,7 @@ impl AnalysisHost { } pub fn update_lru_capacity(&mut self, lru_capacity: Option) { - self.db.update_parse_query_lru_capacity(lru_capacity); + self.db.update_base_query_lru_capacities(lru_capacity); } pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap, usize>) { From 967391504523adadc01c70f675a0d66923df1c32 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 20:52:10 +0100 Subject: [PATCH 075/297] Make `DefDatabase::lang_attr` transparent --- crates/hir-def/src/db.rs | 1 + crates/hir/src/db.rs | 4 ++-- crates/ide-db/src/apply_change.rs | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index d5831022f28f..8c1e3aca98ec 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -210,6 +210,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Attrs; + #[salsa::transparent] #[salsa::invoke(lang_item::lang_attr_query)] fn lang_attr(&self, def: AttrDefId) -> Option; diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 7204868464b3..403a6c88ab0f 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs @@ -15,8 +15,8 @@ pub use hir_def::db::{ InternExternBlockQuery, InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, InternStructQuery, InternTraitAliasQuery, InternTraitQuery, - InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangAttrQuery, LangItemQuery, - Macro2DataQuery, MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery, + InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, + MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataQuery, UnionDataWithDiagnosticsQuery, VariantsAttrsQuery, VariantsAttrsSourceMapQuery, diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 6399f83c4756..259d141404d3 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -172,7 +172,6 @@ impl RootDatabase { hir::db::CrateSupportsNoStdQuery hir::db::BlockItemTreeQueryQuery hir::db::ExternCrateDeclDataQuery - hir::db::LangAttrQuery hir::db::InternAnonymousConstQuery hir::db::InternExternCrateQuery hir::db::InternInTypeConstQuery From 4e16e0f2c126c7250c16d7c2256da169a602b215 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 21:06:21 +0100 Subject: [PATCH 076/297] Don't allocate `DefDatabase::crate_lang_items` if its empty --- crates/hir-def/src/attr.rs | 2 +- crates/hir-def/src/db.rs | 6 +----- crates/hir-def/src/lang_item.rs | 17 ++++++++++++----- crates/hir/src/attrs.rs | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 26f76afb1f09..a0dfcb6a286c 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -355,7 +355,7 @@ fn parse_comma_sep(subtree: &tt::Subtree) -> Vec { } impl AttrsWithOwner { - pub(crate) fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self { + pub fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self { Self { attrs: db.attrs(owner), owner } } diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 8c1e3aca98ec..70c0d5193d4b 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -214,10 +214,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Option; - #[salsa::transparent] - #[salsa::invoke(AttrsWithOwner::attrs_with_owner)] - fn attrs_with_owner(&self, def: AttrDefId) -> AttrsWithOwner; - // endregion:attrs #[salsa::invoke(LangItems::lang_item_query)] @@ -241,7 +237,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc; + fn crate_lang_items(&self, krate: CrateId) -> Option>; fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; } diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index 1ae6bd4c9194..66e0d2cc346b 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -87,7 +87,10 @@ impl LangItems { } /// Salsa query. This will look for lang items in a specific crate. - pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { + pub(crate) fn crate_lang_items_query( + db: &dyn DefDatabase, + krate: CrateId, + ) -> Option> { let _p = profile::span("crate_lang_items_query"); let mut lang_items = LangItems::default(); @@ -150,7 +153,11 @@ impl LangItems { } } - Arc::new(lang_items) + if lang_items.items.is_empty() { + None + } else { + Some(Arc::new(lang_items)) + } } /// Salsa query. Look for a lang item, starting from the specified crate and recursively @@ -161,9 +168,9 @@ impl LangItems { item: LangItem, ) -> Option { let _p = profile::span("lang_item_query"); - let lang_items = db.crate_lang_items(start_crate); - let start_crate_target = lang_items.items.get(&item); - if let Some(&target) = start_crate_target { + if let Some(target) = + db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied()) + { return Some(target); } db.crate_graph()[start_crate] diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 60ddc4aa86fe..5a21f41dca84 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -35,7 +35,7 @@ macro_rules! impl_has_attrs { impl HasAttrs for $def { fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { let def = AttrDefId::$def_id(self.into()); - db.attrs_with_owner(def) + AttrsWithOwner::attrs_with_owner(db.upcast(), def) } fn attr_id(self) -> AttrDefId { AttrDefId::$def_id(self.into()) From c4b3075be0d2829de5172c38969b0f5d0ea06292 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 21:20:03 +0100 Subject: [PATCH 077/297] Don't allocate `inherent_impls_in_block` and `trait_impls_in_block` if its empty --- crates/hir-ty/src/chalk_db.rs | 8 +++-- crates/hir-ty/src/db.rs | 36 +++++++++++--------- crates/hir-ty/src/method_resolution.rs | 47 +++++++++++++++++--------- 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index f4fbace19e35..e81d4ced5543 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -167,7 +167,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { } }); }) - .map(|block_id| self.db.trait_impls_in_block(block_id)); + .filter_map(|block_id| self.db.trait_impls_in_block(block_id)); let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); let mut result = vec![]; @@ -183,7 +183,8 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { def_blocks .into_iter() .flatten() - .for_each(|it| f(&self.db.trait_impls_in_block(it))); + .filter_map(|it| self.db.trait_impls_in_block(it)) + .for_each(|it| f(&it)); } fps => { let mut f = @@ -198,7 +199,8 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { def_blocks .into_iter() .flatten() - .for_each(|it| f(&self.db.trait_impls_in_block(it))); + .filter_map(|it| self.db.trait_impls_in_block(it)) + .for_each(|it| f(&it)); } } diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 410bcbf0356f..ad790fa094d8 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -34,6 +34,8 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::infer::infer_query)] fn infer_query(&self, def: DefWithBodyId) -> Arc; + // region:mir + #[salsa::invoke(crate::mir::mir_body_query)] #[salsa::cycle(crate::mir::mir_body_recover)] fn mir_body(&self, def: DefWithBodyId) -> Result, MirLowerError>; @@ -61,20 +63,6 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::mir::borrowck_query)] fn borrowck(&self, def: DefWithBodyId) -> Result, MirLowerError>; - #[salsa::invoke(crate::lower::ty_query)] - #[salsa::cycle(crate::lower::ty_recover)] - fn ty(&self, def: TyDefId) -> Binders; - - #[salsa::invoke(crate::lower::value_ty_query)] - fn value_ty(&self, def: ValueTyDefId) -> Binders; - - #[salsa::invoke(crate::lower::impl_self_ty_query)] - #[salsa::cycle(crate::lower::impl_self_ty_recover)] - fn impl_self_ty(&self, def: ImplId) -> Binders; - - #[salsa::invoke(crate::lower::const_param_ty_query)] - fn const_param_ty(&self, def: ConstParamId) -> Ty; - #[salsa::invoke(crate::consteval::const_eval_query)] #[salsa::cycle(crate::consteval::const_eval_recover)] fn const_eval( @@ -92,6 +80,22 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::cycle(crate::consteval::const_eval_discriminant_recover)] fn const_eval_discriminant(&self, def: EnumVariantId) -> Result; + // endregion:mir + + #[salsa::invoke(crate::lower::ty_query)] + #[salsa::cycle(crate::lower::ty_recover)] + fn ty(&self, def: TyDefId) -> Binders; + + #[salsa::invoke(crate::lower::value_ty_query)] + fn value_ty(&self, def: ValueTyDefId) -> Binders; + + #[salsa::invoke(crate::lower::impl_self_ty_query)] + #[salsa::cycle(crate::lower::impl_self_ty_recover)] + fn impl_self_ty(&self, def: ImplId) -> Binders; + + #[salsa::invoke(crate::lower::const_param_ty_query)] + fn const_param_ty(&self, def: ConstParamId) -> Ty; + #[salsa::invoke(crate::lower::impl_trait_query)] fn impl_trait(&self, def: ImplId) -> Option>; @@ -158,7 +162,7 @@ pub trait HirDatabase: DefDatabase + Upcast { fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc; #[salsa::invoke(InherentImpls::inherent_impls_in_block_query)] - fn inherent_impls_in_block(&self, block: BlockId) -> Arc; + fn inherent_impls_in_block(&self, block: BlockId) -> Option>; /// Collects all crates in the dependency graph that have impls for the /// given fingerprint. This is only used for primitive types and types @@ -175,7 +179,7 @@ pub trait HirDatabase: DefDatabase + Upcast { fn trait_impls_in_crate(&self, krate: CrateId) -> Arc; #[salsa::invoke(TraitImpls::trait_impls_in_block_query)] - fn trait_impls_in_block(&self, block: BlockId) -> Arc; + fn trait_impls_in_block(&self, block: BlockId) -> Option>; #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc]>; diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 3b1697a07b07..06df30582aa7 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -152,13 +152,20 @@ impl TraitImpls { Arc::new(Self::finish(impls)) } - pub(crate) fn trait_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc { + pub(crate) fn trait_impls_in_block_query( + db: &dyn HirDatabase, + block: BlockId, + ) -> Option> { let _p = profile::span("trait_impls_in_block_query"); let mut impls = FxHashMap::default(); Self::collect_def_map(db, &mut impls, &db.block_def_map(block)); - Arc::new(Self::finish(impls)) + if impls.is_empty() { + None + } else { + Some(Arc::new(Self::finish(impls))) + } } pub(crate) fn trait_impls_in_deps_query( @@ -276,7 +283,10 @@ impl InherentImpls { Arc::new(impls) } - pub(crate) fn inherent_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc { + pub(crate) fn inherent_impls_in_block_query( + db: &dyn HirDatabase, + block: BlockId, + ) -> Option> { let _p = profile::span("inherent_impls_in_block_query"); let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() }; @@ -284,7 +294,11 @@ impl InherentImpls { impls.collect_def_map(db, &block_def_map); impls.shrink_to_fit(); - Arc::new(impls) + if impls.map.is_empty() && impls.invalid_impls.is_empty() { + None + } else { + Some(Arc::new(impls)) + } } fn shrink_to_fit(&mut self) { @@ -732,7 +746,7 @@ fn lookup_impl_assoc_item_for_trait_ref( let impls = db.trait_impls_in_deps(env.krate); let self_impls = match self_ty.kind(Interner) { TyKind::Adt(id, _) => { - id.0.module(db.upcast()).containing_block().map(|it| db.trait_impls_in_block(it)) + id.0.module(db.upcast()).containing_block().and_then(|it| db.trait_impls_in_block(it)) } _ => None, }; @@ -1249,17 +1263,18 @@ fn iterate_inherent_methods( }; while let Some(block_id) = block { - let impls = db.inherent_impls_in_block(block_id); - impls_for_self_ty( - &impls, - self_ty, - table, - name, - receiver_ty, - receiver_adjustments.clone(), - module, - callback, - )?; + if let Some(impls) = db.inherent_impls_in_block(block_id) { + impls_for_self_ty( + &impls, + self_ty, + table, + name, + receiver_ty, + receiver_adjustments.clone(), + module, + callback, + )?; + } block = db.block_def_map(block_id).parent().and_then(|module| module.containing_block()); } From f8b130a6aa437a1e9626db89db1252c325c868d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 21:30:01 +0100 Subject: [PATCH 078/297] unreachable pub --- crates/hir-def/src/generics.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 26a836f25e92..6cb9b8448d14 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -144,9 +144,9 @@ pub enum WherePredicateTypeTarget { #[derive(Clone, Default)] pub(crate) struct GenericParamsCollector { - pub type_or_consts: Arena, - pub lifetimes: Arena, - pub where_predicates: Vec, + pub(crate) type_or_consts: Arena, + lifetimes: Arena, + where_predicates: Vec, } impl GenericParamsCollector { From beeaaf184ee1b896450ac98bad3aa9a62e3413bc Mon Sep 17 00:00:00 2001 From: Zach Date: Tue, 9 Jan 2024 17:09:50 -0600 Subject: [PATCH 079/297] Mark unresolved associated item diagnostic as experimental --- crates/ide-diagnostics/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index c7ad09e7ebdd..c4ced1e1211a 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -373,7 +373,7 @@ pub fn diagnostics( AnyDiagnostic::UndeclaredLabel(d) => handlers::undeclared_label::undeclared_label(&ctx, &d), AnyDiagnostic::UnimplementedBuiltinMacro(d) => handlers::unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d), AnyDiagnostic::UnreachableLabel(d) => handlers::unreachable_label::unreachable_label(&ctx, &d), - AnyDiagnostic::UnresolvedAssocItem(d) => handlers::unresolved_assoc_item::unresolved_assoc_item(&ctx, &d), + AnyDiagnostic::UnresolvedAssocItem(d) => handlers::unresolved_assoc_item::unresolved_assoc_item(&ctx, &d).experimental(), AnyDiagnostic::UnresolvedExternCrate(d) => handlers::unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), AnyDiagnostic::UnresolvedField(d) => handlers::unresolved_field::unresolved_field(&ctx, &d), AnyDiagnostic::UnresolvedImport(d) => handlers::unresolved_import::unresolved_import(&ctx, &d), From d5c39d0638221f07e7172b61e6c1e70cd2fee6bc Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 9 Jan 2024 20:30:53 -0800 Subject: [PATCH 080/297] Update compiler_builtins to 0.1.105 This provides the builtins for the hexagon architecture. --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75c7de4f405a..4d917ec6f916 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -704,9 +704,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "compiler_builtins" -version = "0.1.104" +version = "0.1.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741" +checksum = "3686cc48897ce1950aa70fd595bd2dc9f767a3c4cca4cd17b2cb52a2d37e6eb4" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5dbfe4aa2ac1..5b32bc5117c0 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.104" } +compiler_builtins = { version = "0.1.105" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } From bc54775c9d7026b1ca616ca43fd34ff6f53d668a Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 10 Jan 2024 15:00:35 +0800 Subject: [PATCH 081/297] Preserve comments for extracted block expr in 'extract_function' assist --- .../src/handlers/extract_function.rs | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 347a3e9ba074..3d91cb6a0f83 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -25,7 +25,7 @@ use syntax::{ edit::{AstNodeEdit, IndentLevel}, AstNode, HasGenericParams, }, - match_ast, ted, SyntaxElement, + match_ast, ted, AstToken, SyntaxElement, SyntaxKind::{self, COMMENT}, SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T, }; @@ -1733,8 +1733,23 @@ fn make_body( ast::Expr::BlockExpr(block) => { // If the extracted expression is itself a block, there is no need to wrap it inside another block. let block = block.dedent(old_indent); - // Recreate the block for formatting consistency with other extracted functions. - make::block_expr(block.statements(), block.tail_expr()) + let elements = block.stmt_list().map_or_else( + || Either::Left(iter::empty()), + |stmt_list| { + let elements = stmt_list.syntax().children_with_tokens().filter_map( + |node_or_token| match &node_or_token { + syntax::NodeOrToken::Node(node) => { + ast::Stmt::cast(node.clone()).map(|_| node_or_token) + } + syntax::NodeOrToken::Token(token) => { + ast::Comment::cast(token.clone()).map(|_| node_or_token) + } + }, + ); + Either::Right(elements) + }, + ); + make::hacky_block_expr(elements, block.tail_expr()) } _ => { let expr = expr.dedent(old_indent).indent(IndentLevel(1)); From d327f3036c2db0cffb91807c301d48f8e37165e2 Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 10 Jan 2024 15:00:58 +0800 Subject: [PATCH 082/297] Add test 'comments_in_block_expr' in in 'extract_function' --- .../src/handlers/extract_function.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 3d91cb6a0f83..1eb28626f75d 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -5976,6 +5976,37 @@ fn $0fun_name() -> ControlFlow<()> { ); } + #[test] + fn comments_in_block_expr() { + check_assist( + extract_function, + r#" +fn f() { + let c = $0{ + // comment 1 + let a = 2 + 3; + // comment 2 + let b = 5; + a + b + }$0; +} +"#, + r#" +fn f() { + let c = fun_name(); +} + +fn $0fun_name() -> i32 { + // comment 1 + let a = 2 + 3; + // comment 2 + let b = 5; + a + b +} +"#, + ); + } + #[test] fn in_left_curly_is_not_applicable() { cov_mark::check!(extract_function_in_braces_is_not_applicable); From 9c2d331e1696aba883a0d220c0dc445dc82ace0d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 10 Jan 2024 08:47:26 +0100 Subject: [PATCH 083/297] Bump salsa --- Cargo.lock | 23 +++++++++++++++++------ Cargo.toml | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1a1c8fb9fd1..15d06222eb42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1568,9 +1568,9 @@ dependencies = [ [[package]] name = "rust-analyzer-salsa" -version = "0.17.0-pre.4" +version = "0.17.0-pre.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c42b8737c320578b441a82daf7cdf8d897468de64e8a774fa54b53a50b6cc0" +checksum = "ca9d387a9801f4fb9b366789ad1bfc08448cafc49cf148d907cfcd88ab665d7f" dependencies = [ "indexmap", "lock_api", @@ -1580,13 +1580,14 @@ dependencies = [ "rust-analyzer-salsa-macros", "rustc-hash", "smallvec", + "triomphe", ] [[package]] name = "rust-analyzer-salsa-macros" -version = "0.17.0-pre.4" +version = "0.17.0-pre.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db72b0883f3592ade2be15a10583c75e0b269ec26e1190800fda2e2ce5ae6634" +checksum = "a2035f385d7fae31e9b086f40b272ee1d79c484472f31c9a10348a406e841eaf" dependencies = [ "heck", "proc-macro2", @@ -1742,6 +1743,12 @@ dependencies = [ "vfs", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -2019,9 +2026,13 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c5a71827ac326072b6405552093e2ad2accd25a32fd78d4edc82d98c7f2409" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +dependencies = [ + "serde", + "stable_deref_trait", +] [[package]] name = "tt" diff --git a/Cargo.toml b/Cargo.toml index a81c4659636e..35bef151196f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,7 +112,7 @@ itertools = "0.12.0" libc = "0.2.150" nohash-hasher = "0.2.0" rayon = "1.8.0" -rust-analyzer-salsa = "0.17.0-pre.4" +rust-analyzer-salsa = "0.17.0-pre.5" rustc-hash = "1.1.0" semver = "1.0.14" serde = { version = "1.0.192", features = ["derive"] } From 500d6f64791d4f9576c8588ef2cdeab4a3139a02 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 21:56:06 -0400 Subject: [PATCH 084/297] Stabilize `slice_first_last_chunk` This stabilizes all methods under `slice_first_last_chunk`. Additionally, it const stabilizes the non-mut functions and moves the `_mut` functions under `const_slice_first_last_chunk`. These are blocked on `const_mut_refs`. As part of this change, `slice_split_at_unchecked` was marked const-stable for internal use (but not fully stable). --- compiler/rustc_serialize/src/lib.rs | 1 - library/core/src/slice/mod.rs | 54 +++++++++++------------------ library/core/tests/lib.rs | 1 - 3 files changed, 20 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index cfa54072eb91..c149b659a4f7 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -16,7 +16,6 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(ptr_sub_ptr)] -#![feature(slice_first_last_chunk)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9512d45740fd..a425beb1c9ae 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -327,8 +327,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let u = [10, 40, 30]; /// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>()); /// @@ -338,9 +336,9 @@ impl [T] { /// let w: &[i32] = &[]; /// assert_eq!(Some(&[]), w.first_chunk::<0>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] pub const fn first_chunk(&self) -> Option<&[T; N]> { if self.len() < N { None @@ -358,8 +356,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some(first) = x.first_chunk_mut::<2>() { @@ -370,9 +366,9 @@ impl [T] { /// /// assert_eq!(None, x.first_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -391,8 +387,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &[0, 1, 2]; /// /// if let Some((first, elements)) = x.split_first_chunk::<2>() { @@ -402,9 +396,9 @@ impl [T] { /// /// assert_eq!(None, x.split_first_chunk::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] pub const fn split_first_chunk(&self) -> Option<(&[T; N], &[T])> { if self.len() < N { None @@ -426,8 +420,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() { @@ -439,9 +431,9 @@ impl [T] { /// /// assert_eq!(None, x.split_first_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { @@ -465,8 +457,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &[0, 1, 2]; /// /// if let Some((elements, last)) = x.split_last_chunk::<2>() { @@ -476,9 +466,9 @@ impl [T] { /// /// assert_eq!(None, x.split_last_chunk::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { if self.len() < N { None @@ -500,8 +490,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some((elements, last)) = x.split_last_chunk_mut::<2>() { @@ -513,9 +501,9 @@ impl [T] { /// /// assert_eq!(None, x.split_last_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_last_chunk_mut( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { @@ -539,8 +527,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let u = [10, 40, 30]; /// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>()); /// @@ -550,9 +536,9 @@ impl [T] { /// let w: &[i32] = &[]; /// assert_eq!(Some(&[]), w.last_chunk::<0>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk(&self) -> Option<&[T; N]> { if self.len() < N { None @@ -574,8 +560,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some(last) = x.last_chunk_mut::<2>() { @@ -586,9 +570,9 @@ impl [T] { /// /// assert_eq!(None, x.last_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -1885,7 +1869,6 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")] - #[rustc_allow_const_fn_unstable(slice_split_at_unchecked)] #[inline] #[track_caller] #[must_use] @@ -1972,7 +1955,10 @@ impl [T] { /// } /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] - #[rustc_const_unstable(feature = "slice_split_at_unchecked", issue = "76014")] + #[rustc_const_stable( + feature = "const_slice_split_at_unchecked", + since = "CURRENT_RUSTC_VERSION" + )] #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 15e58a4e53fb..df7b34ce73b4 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -46,7 +46,6 @@ #![feature(pattern)] #![feature(sort_internals)] #![feature(slice_take)] -#![feature(slice_first_last_chunk)] #![feature(slice_from_ptr_range)] #![feature(slice_split_once)] #![feature(split_as_slice)] From 4b7b602da9e11840aacd063d9485a0a8166d6960 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 5 Jan 2024 15:18:02 +0100 Subject: [PATCH 085/297] Remove sysroot-abi feature flag from proc-macro-test --- crates/proc-macro-srv/Cargo.toml | 2 +- .../proc-macro-srv/proc-macro-test/Cargo.toml | 3 -- .../proc-macro-srv/proc-macro-test/build.rs | 28 ++++++++++--------- .../proc-macro-test/imp/Cargo.toml | 3 -- .../proc-macro-test/imp/src/lib.rs | 3 -- 5 files changed, 16 insertions(+), 23 deletions(-) diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index 9c4375559c11..ba17ea6f7b43 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -37,7 +37,7 @@ expect-test = "1.4.0" proc-macro-test.path = "./proc-macro-test" [features] -sysroot-abi = ["proc-macro-test/sysroot-abi"] +sysroot-abi = [] in-rust-tree = ["mbe/in-rust-tree", "sysroot-abi"] [lints] diff --git a/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 90545bb5130c..7977afb1cbd2 100644 --- a/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -14,6 +14,3 @@ cargo_metadata = "0.18.1" # local deps toolchain.workspace = true - -[features] -sysroot-abi = [] diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs index 7299147686df..6cf2b5643e57 100644 --- a/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/crates/proc-macro-srv/proc-macro-test/build.rs @@ -17,11 +17,24 @@ use cargo_metadata::Message; fn main() { println!("cargo:rerun-if-changed=imp"); - println!("cargo:rerun-if-env-changed=PROC_MACRO_TEST_TOOLCHAIN"); + + let has_features = env::var_os("RUSTC_BOOTSTRAP").is_some() + || String::from_utf8( + Command::new(toolchain::cargo()).arg("--version").output().unwrap().stdout, + ) + .unwrap() + .contains("nightly"); let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); + if !has_features { + println!("proc-macro-test testing only works on nightly toolchains"); + let info_path = out_dir.join("proc_macro_test_location.txt"); + fs::File::create(info_path).unwrap(); + return; + } + let name = "proc-macro-test-impl"; let version = "0.0.0"; @@ -53,15 +66,7 @@ fn main() { let target_dir = out_dir.join("target"); - let mut cmd = if let Ok(toolchain) = std::env::var("PROC_MACRO_TEST_TOOLCHAIN") { - // leverage rustup to find user-specific toolchain - let mut cmd = Command::new("cargo"); - cmd.arg(format!("+{toolchain}")); - cmd - } else { - Command::new(toolchain::cargo()) - }; - + let mut cmd = Command::new(toolchain::cargo()); cmd.current_dir(&staging_dir) .args(["build", "-p", "proc-macro-test-impl", "--message-format", "json"]) // Explicit override the target directory to avoid using the same one which the parent @@ -70,9 +75,6 @@ fn main() { // instance to use the same target directory. .arg("--target-dir") .arg(&target_dir); - if cfg!(feature = "sysroot-abi") { - cmd.args(["--features", "sysroot-abi"]); - } if let Ok(target) = std::env::var("TARGET") { cmd.args(["--target", &target]); diff --git a/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml b/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml index dc94fcd61a4f..fa189752b76f 100644 --- a/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml +++ b/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml @@ -13,7 +13,4 @@ proc-macro = true # this crate should not have any dependencies, since it uses its own workspace, # and its own `Cargo.lock` -[features] -sysroot-abi = [] - [workspace] diff --git a/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs b/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs index b8aad4acefcf..d9018b1b87d3 100644 --- a/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs +++ b/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs @@ -1,8 +1,5 @@ //! Exports a few trivial procedural macros for testing. -#![allow(unexpected_cfgs)] -#![cfg(feature = "sysroot-abi")] -#![cfg(any(feature = "sysroot-abi", rust_analyzer))] #![warn(rust_2018_idioms, unused_lifetimes)] #![feature(proc_macro_span, proc_macro_def_site)] From 257870e09f0f56ce5e2588948b00e2bf04ce304c Mon Sep 17 00:00:00 2001 From: dfireBird Date: Wed, 10 Jan 2024 16:30:22 +0530 Subject: [PATCH 086/297] add tests to verify relevance of notable traits and some refactors --- crates/ide-completion/src/render.rs | 77 ++++++++++++++++++++ crates/ide-completion/src/render/function.rs | 16 ++-- 2 files changed, 84 insertions(+), 9 deletions(-) diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index f924c9aedb60..8c0e6694761e 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -2443,4 +2443,81 @@ impl S { "#, ) } + + #[test] + fn notable_traits_method_relevance() { + check_kinds( + r#" +#[doc(notable_trait)] +trait Write { + fn write(&self); + fn flush(&self); +} + +struct Writer; + +impl Write for Writer { + fn write(&self) {} + fn flush(&self) {} +} + +fn main() { + Writer.$0 +} +"#, + &[ + CompletionItemKind::Method, + CompletionItemKind::SymbolKind(SymbolKind::Field), + CompletionItemKind::SymbolKind(SymbolKind::Function), + ], + expect![[r#" + [ + CompletionItem { + label: "flush()", + source_range: 193..193, + delete: 193..193, + insert: "flush()$0", + kind: Method, + lookup: "flush", + detail: "fn(&self)", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + is_item_from_trait: false, + is_item_from_notable_trait: true, + is_name_already_imported: false, + requires_import: false, + is_op_method: false, + is_private_editable: false, + postfix_match: None, + is_definite: false, + }, + }, + CompletionItem { + label: "write()", + source_range: 193..193, + delete: 193..193, + insert: "write()$0", + kind: Method, + lookup: "write", + detail: "fn(&self)", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + is_item_from_trait: false, + is_item_from_notable_trait: true, + is_name_already_imported: false, + requires_import: false, + is_op_method: false, + is_private_editable: false, + postfix_match: None, + is_definite: false, + }, + }, + ] + "#]], + ); + } } diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index ccd312b03fb7..6ad84eba33be 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -74,15 +74,13 @@ fn render( ); let ret_type = func.ret_type(db); - let is_op_method = func - .as_assoc_item(ctx.db()) - .and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db())) - .map_or(false, |trait_| completion.is_ops_trait(trait_)); + let assoc_item = func.as_assoc_item(db); - let is_item_from_notable_trait = func - .as_assoc_item(ctx.db()) - .and_then(|trait_| trait_.containing_trait(ctx.db())) - .map_or(false, |trait_| completion.is_doc_notable_trait(trait_)); + let trait_ = assoc_item.and_then(|trait_| trait_.containing_trait_or_trait_impl(db)); + let is_op_method = trait_.map_or(false, |trait_| completion.is_ops_trait(trait_)); + + let is_item_from_notable_trait = + trait_.map_or(false, |trait_| completion.is_doc_notable_trait(trait_)); let (has_dot_receiver, has_call_parens, cap) = match func_kind { FuncKind::Function(&PathCompletionCtx { @@ -147,7 +145,7 @@ fn render( item.add_import(import_to_add); } None => { - if let Some(actm) = func.as_assoc_item(db) { + if let Some(actm) = assoc_item { if let Some(trt) = actm.containing_trait_or_trait_impl(db) { item.trait_name(trt.name(db).to_smol_str()); } From 1aff8157bcf9d9cf3d5358c60c28b0b896e18d19 Mon Sep 17 00:00:00 2001 From: Zach Date: Wed, 10 Jan 2024 05:58:25 -0600 Subject: [PATCH 087/297] Set experimental field at diagnostic new instead of lib --- crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs | 1 + crates/ide-diagnostics/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs b/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs index f1c95993c843..551021c55a98 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs @@ -13,6 +13,7 @@ pub(crate) fn unresolved_assoc_item( "no such associated item", d.expr_or_pat.clone().map(Into::into), ) + .experimental() } #[cfg(test)] diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index c4ced1e1211a..c7ad09e7ebdd 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -373,7 +373,7 @@ pub fn diagnostics( AnyDiagnostic::UndeclaredLabel(d) => handlers::undeclared_label::undeclared_label(&ctx, &d), AnyDiagnostic::UnimplementedBuiltinMacro(d) => handlers::unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d), AnyDiagnostic::UnreachableLabel(d) => handlers::unreachable_label::unreachable_label(&ctx, &d), - AnyDiagnostic::UnresolvedAssocItem(d) => handlers::unresolved_assoc_item::unresolved_assoc_item(&ctx, &d).experimental(), + AnyDiagnostic::UnresolvedAssocItem(d) => handlers::unresolved_assoc_item::unresolved_assoc_item(&ctx, &d), AnyDiagnostic::UnresolvedExternCrate(d) => handlers::unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), AnyDiagnostic::UnresolvedField(d) => handlers::unresolved_field::unresolved_field(&ctx, &d), AnyDiagnostic::UnresolvedImport(d) => handlers::unresolved_import::unresolved_import(&ctx, &d), From 4d3a0dc3291c527fc186c4e24babc6ad5b16ab35 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 10 Jan 2024 14:51:51 +0100 Subject: [PATCH 088/297] Replace SourceRootCrates hashset output with slice for deterministic order --- crates/base-db/src/lib.rs | 15 ++++++++------- crates/hir-def/src/test_db.rs | 3 +-- crates/hir-ty/src/test_db.rs | 3 +-- crates/hir/src/symbols.rs | 1 + crates/ide-db/src/lib.rs | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 28931676eedd..c2ab95064897 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -50,7 +50,7 @@ pub trait FileLoader { /// Text of the file. fn file_text(&self, file_id: FileId) -> Arc; fn resolve_path(&self, path: AnchoredPath<'_>) -> Option; - fn relevant_crates(&self, file_id: FileId) -> Arc>; + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>; } /// Database which stores all significant input facts: source code and project @@ -85,19 +85,20 @@ pub trait SourceDatabaseExt: SourceDatabase { #[salsa::input] fn source_root(&self, id: SourceRootId) -> Arc; - fn source_root_crates(&self, id: SourceRootId) -> Arc>; + fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; } -fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc> { +fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<[CrateId]> { let graph = db.crate_graph(); - let res = graph + graph .iter() .filter(|&krate| { let root_file = graph[krate].root_file_id; db.file_source_root(root_file) == id }) - .collect(); - Arc::new(res) + .collect::>() + .into_iter() + .collect() } /// Silly workaround for cyclic deps between the traits @@ -114,7 +115,7 @@ impl FileLoader for FileLoaderDelegate<&'_ T> { source_root.resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { let _p = profile::span("relevant_crates"); let source_root = self.0.file_source_root(file_id); self.0.source_root_crates(source_root) diff --git a/crates/hir-def/src/test_db.rs b/crates/hir-def/src/test_db.rs index f4a6b61f7af5..c992c3c92048 100644 --- a/crates/hir-def/src/test_db.rs +++ b/crates/hir-def/src/test_db.rs @@ -8,7 +8,6 @@ use base_db::{ Upcast, }; use hir_expand::{db::ExpandDatabase, InFile}; -use rustc_hash::FxHashSet; use syntax::{algo, ast, AstNode}; use triomphe::Arc; @@ -76,7 +75,7 @@ impl FileLoader for TestDB { fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { FileLoaderDelegate(self).resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { FileLoaderDelegate(self).relevant_crates(file_id) } } diff --git a/crates/hir-ty/src/test_db.rs b/crates/hir-ty/src/test_db.rs index 6f4aef22d2f7..d0a1fb1d5769 100644 --- a/crates/hir-ty/src/test_db.rs +++ b/crates/hir-ty/src/test_db.rs @@ -9,7 +9,6 @@ use base_db::{ use hir_def::{db::DefDatabase, ModuleId}; use hir_expand::db::ExpandDatabase; use nohash_hasher::IntMap; -use rustc_hash::FxHashSet; use syntax::TextRange; use test_utils::extract_annotations; use triomphe::Arc; @@ -81,7 +80,7 @@ impl FileLoader for TestDB { fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { FileLoaderDelegate(self).resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { FileLoaderDelegate(self).relevant_crates(file_id) } } diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 841ddfb9c437..9ae5bb26932d 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -165,6 +165,7 @@ impl<'a> SymbolCollector<'a> { // Record renamed imports. // FIXME: In case it imports multiple items under different namespaces we just pick one arbitrarily // for now. + // FIXME: This parses! for id in scope.imports() { let source = id.import.child_source(self.db.upcast()); let Some(use_tree_src) = source.value.get(id.idx) else { continue }; diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 79531936fde4..eae23e954824 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -124,7 +124,7 @@ impl FileLoader for RootDatabase { fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { FileLoaderDelegate(self).resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { FileLoaderDelegate(self).relevant_crates(file_id) } } From fcaeb4542173b364835aef7dd2526303191b2d2c Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 10 Jan 2024 17:12:01 +0200 Subject: [PATCH 089/297] deps: deduplicate the version of libloading used The changelog can be found here: https://docs.rs/libloading/latest/libloading/changelog/r0_8_0/index.html --- Cargo.lock | 16 +++------------- compiler/rustc_codegen_cranelift/Cargo.toml | 2 +- compiler/rustc_interface/Cargo.toml | 2 +- compiler/rustc_metadata/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75c7de4f405a..dc44041141b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2177,16 +2177,6 @@ dependencies = [ "cc", ] -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - [[package]] name = "libloading" version = "0.8.1" @@ -2469,7 +2459,7 @@ dependencies = [ "lazy_static", "libc", "libffi", - "libloading 0.8.1", + "libloading", "log", "measureme", "rand", @@ -3993,7 +3983,7 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "libloading 0.7.4", + "libloading", "rustc-rayon", "rustc-rayon-core", "rustc_ast", @@ -4123,7 +4113,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "bitflags 2.4.1", - "libloading 0.7.4", + "libloading", "odht", "rustc_ast", "rustc_attr", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index fdac789423c9..c57e964168f4 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -19,7 +19,7 @@ gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" -libloading = { version = "0.7.3", optional = true } +libloading = { version = "0.8.0", optional = true } smallvec = "1.8.1" [patch.crates-io] diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 319e81758094..a238eacda44b 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -libloading = "0.7.1" +libloading = "0.8.0" rustc-rayon = { version = "0.5.0", optional = true } rustc-rayon-core = { version = "0.5.0", optional = true } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 08cc8173eb04..79d3482472a8 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -libloading = "0.7.1" +libloading = "0.8.0" odht = { version = "0.3.1", features = ["nightly"] } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } From 1dc3ab02cdba905aa1cce73d938c8e825107a8e8 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 10 Jan 2024 17:13:03 +0200 Subject: [PATCH 090/297] Format sources into the error message when loading codegen backends cc https://github.com/rust-lang/rustc_codegen_cranelift/issues/1447 --- compiler/rustc_codegen_cranelift/Cargo.lock | 6 +++--- compiler/rustc_interface/src/lib.rs | 3 ++- compiler/rustc_interface/src/util.rs | 12 +++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 74e7afee7bcb..6d6a1200f502 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -246,12 +246,12 @@ checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys", ] [[package]] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index cfa46447845a..764306ce6ec6 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,9 +1,10 @@ #![feature(box_patterns)] #![feature(decl_macro)] +#![feature(error_iter)] #![feature(internal_output_capture)] -#![feature(thread_spawn_unchecked)] #![feature(lazy_cell)] #![feature(let_chains)] +#![feature(thread_spawn_unchecked)] #![feature(try_blocks)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 92a6445ed091..a09bb3c5fd0d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -162,15 +162,21 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( } fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn { + fn format_err(e: &(dyn std::error::Error + 'static)) -> String { + e.sources().map(|e| format!(": {e}")).collect() + } let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {path:?}: {err}"); + let err = format!("couldn't load codegen backend {path:?}{}", format_err(&err)); early_dcx.early_fatal(err); }); let backend_sym = unsafe { lib.get::(b"__rustc_codegen_backend") } .unwrap_or_else(|e| { - let err = format!("couldn't load codegen backend: {e}"); - early_dcx.early_fatal(err); + let e = format!( + "`__rustc_codegen_backend` symbol lookup in the codegen backend failed{}", + format_err(&e) + ); + early_dcx.early_fatal(e); }); // Intentionally leak the dynamic library. We can't ever unload it From 08fc5e8acd1bc41fbf5b8a4b5c96a42c16bab158 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:03:05 +0000 Subject: [PATCH 091/297] Define hidden types in confirmation --- .../src/traits/project.rs | 2 +- .../nested_inference_failure.rs | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/ui/type-alias-impl-trait/nested_inference_failure.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index dd4e69efe379..abbc2066eac1 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2466,7 +2466,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( debug!(?cache_projection, ?obligation_projection); match infcx.at(cause, param_env).eq( - DefineOpaqueTypes::No, + DefineOpaqueTypes::Yes, cache_projection, obligation_projection, ) { diff --git a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs new file mode 100644 index 000000000000..16b78f18aa34 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs @@ -0,0 +1,26 @@ +// check-pass + +//! This test checks that we can successfully infer +//! the hidden type of `FooImpl` to be `Foo` +//! and `ImplT` to be `i32`. This test used to fail, because +//! we were unable to make the connection that the closure +//! argument is the same as the first argument of `Foo`. + +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; +use std::marker::PhantomData; + +struct Foo { + f: F, + _phantom: PhantomData, +} + +type ImplT = impl Debug; +type FooImpl = Foo; + +fn bar() -> FooImpl { + Foo:: { f: |_| (), _phantom: PhantomData } +} + +fn main() {} From 0ae00444dc075c814dd061aa1cfdc5c461c1f608 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:05:24 +0000 Subject: [PATCH 092/297] Make sure the new solver agrees --- tests/ui/type-alias-impl-trait/nested_inference_failure.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs index 16b78f18aa34..d2091ca96ea0 100644 --- a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs +++ b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs @@ -1,4 +1,6 @@ // check-pass +// revisions: new old +//[new] compile-flags: -Znext-solver //! This test checks that we can successfully infer //! the hidden type of `FooImpl` to be `Foo` From 76aaf17794c37cb134fc968d04e1982958af12fd Mon Sep 17 00:00:00 2001 From: Patryk Wychowaniec Date: Fri, 5 Jan 2024 11:00:29 +0100 Subject: [PATCH 093/297] Suggest `pub(crate)` imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-analyzer has logic that discounts suggesting `use`s for private imports, but that logic is unnecessarily strict - for instance given this code: ```rust mod foo { pub struct Foo; } pub(crate) use self::foo::*; mod bar { fn main() { Foo$0; } } ``` ... RA will suggest to add `use crate::foo::Foo;`, which not only makes the code overly verbose (especially in larger code bases), but also is disjoint with what rustc itself suggests. This commit adjusts the logic, so that `pub(crate)` imports are taken into account when generating the suggestions; considering rustc's behavior, I think this change doesn't warrant any extra configuration flag. Note that this is my first commit to RA, so I guess the approach taken here might be suboptimal - certainly feels somewhat hacky, maybe there's some better way of finding out the optimal import path 😅 --- crates/hir-def/src/find_path.rs | 31 +++++++++++++++- crates/hir-def/src/item_scope.rs | 4 +-- crates/hir-def/src/nameres.rs | 3 +- crates/hir-def/src/nameres/path_resolution.rs | 13 ++++--- crates/hir-def/src/visibility.rs | 30 +++++++++++----- crates/hir-expand/src/mod_path.rs | 4 +++ crates/hir-ty/src/display.rs | 2 +- .../ide-assists/src/handlers/auto_import.rs | 35 +++++++++++++++++++ crates/ide-db/src/search.rs | 2 +- 9 files changed, 106 insertions(+), 18 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 4737b48703db..e8086be86f48 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -551,7 +551,18 @@ fn find_local_import_locations( if let Some((name, vis)) = data.scope.name_of(item) { if vis.is_visible_from(db, from) { let is_private = match vis { - Visibility::Module(private_to) => private_to.local_id == module.local_id, + Visibility::Module(private_mod, private_vis) => { + if private_mod == def_map.module_id(DefMap::ROOT) + && private_vis.is_explicit() + { + // Treat `pub(crate)` imports as non-private, so + // that we suggest adding `use crate::Foo;` instead + // of `use crate::foo::Foo;` etc. + false + } else { + private_mod.local_id == module.local_id + } + } Visibility::Public => false, }; let is_original_def = match item.as_module_def_id() { @@ -1021,6 +1032,24 @@ $0 ); } + #[test] + fn promote_pub_crate_imports() { + check_found_path( + r#" +//- /main.rs +mod foo; +pub mod bar { pub struct S; } +pub(crate) use bar::S; +//- /foo.rs +$0 + "#, + "crate::S", + "crate::S", + "crate::S", + "crate::S", + ); + } + #[test] fn import_cycle() { check_found_path( diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 4902f24e2e3a..0a6ba88065d5 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -628,14 +628,14 @@ impl ItemScope { .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis))) .map(|(_, v)| v) .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis)) - .for_each(|vis| *vis = Visibility::Module(this_module)); + .for_each(|vis| *vis = Visibility::Module(this_module, Default::default())); for (mac, vis, import) in self.macros.values_mut() { if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) { continue; } - *vis = Visibility::Module(this_module); + *vis = Visibility::Module(this_module, Default::default()); } } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 52a981fd19eb..a97f57f55313 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -332,7 +332,8 @@ impl DefMap { // NB: we use `None` as block here, which would be wrong for implicit // modules declared by blocks with items. At the moment, we don't use // this visibility for anything outside IDE, so that's probably OK. - let visibility = Visibility::Module(ModuleId { krate, local_id, block: None }); + let visibility = + Visibility::Module(ModuleId { krate, local_id, block: None }, Default::default()); let module_data = ModuleData::new( ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, visibility, diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index be3438e427db..700264839b94 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -21,7 +21,7 @@ use crate::{ nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, - visibility::{RawVisibility, Visibility}, + visibility::{RawVisibility, Visibility, VisibilityExplicity}, AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, }; @@ -94,8 +94,13 @@ impl DefMap { return None; } let types = result.take_types()?; + let mv = if path.is_pub_crate() { + VisibilityExplicity::Explicit + } else { + VisibilityExplicity::Implicit + }; match types { - ModuleDefId::ModuleId(m) => Visibility::Module(m), + ModuleDefId::ModuleId(m) => Visibility::Module(m, mv), // error: visibility needs to refer to module _ => { return None; @@ -108,11 +113,11 @@ impl DefMap { // In block expressions, `self` normally refers to the containing non-block module, and // `super` to its parent (etc.). However, visibilities must only refer to a module in the // DefMap they're written in, so we restrict them when that happens. - if let Visibility::Module(m) = vis { + if let Visibility::Module(m, mv) = vis { // ...unless we're resolving visibility for an associated item in an impl. if self.block_id() != m.block && !within_impl { cov_mark::hit!(adjust_vis_in_block_def_map); - vis = Visibility::Module(self.module_id(Self::ROOT)); + vis = Visibility::Module(self.module_id(Self::ROOT), mv); tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); } } diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 49688c5ee9c2..163484e241b3 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -94,7 +94,7 @@ impl RawVisibility { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Visibility { /// Visibility is restricted to a certain module. - Module(ModuleId), + Module(ModuleId, VisibilityExplicity), /// Visibility is unrestricted. Public, } @@ -102,7 +102,7 @@ pub enum Visibility { impl Visibility { pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool { let to_module = match self { - Visibility::Module(m) => m, + Visibility::Module(m, _) => m, Visibility::Public => return true, }; // if they're not in the same crate, it can't be visible @@ -124,7 +124,7 @@ impl Visibility { mut from_module: LocalModuleId, ) -> bool { let mut to_module = match self { - Visibility::Module(m) => m, + Visibility::Module(m, _) => m, Visibility::Public => return true, }; @@ -181,9 +181,9 @@ impl Visibility { /// visible in unrelated modules). pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option { match (self, other) { - (Visibility::Module(_) | Visibility::Public, Visibility::Public) - | (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public), - (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { + (Visibility::Module(_, _) | Visibility::Public, Visibility::Public) + | (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public), + (Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => { if mod_a.krate != mod_b.krate { return None; } @@ -199,12 +199,12 @@ impl Visibility { if a_ancestors.any(|m| m == mod_b.local_id) { // B is above A - return Some(Visibility::Module(mod_b)); + return Some(Visibility::Module(mod_b, vis_b)); } if b_ancestors.any(|m| m == mod_a.local_id) { // A is above B - return Some(Visibility::Module(mod_a)); + return Some(Visibility::Module(mod_a, vis_a)); } None @@ -213,6 +213,20 @@ impl Visibility { } } +/// Whether the item was imported through `pub(crate) use` or just `use`. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)] +pub enum VisibilityExplicity { + Explicit, + #[default] + Implicit, +} + +impl VisibilityExplicity { + pub fn is_explicit(&self) -> bool { + matches!(self, Self::Explicit) + } +} + /// Resolve visibility of all specific fields of a struct or union variant. pub(crate) fn field_visibilities_query( db: &dyn DefDatabase, diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 30b8c189f52d..4618dcec70b4 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -96,6 +96,10 @@ impl ModPath { self.kind == PathKind::Super(0) && self.segments.is_empty() } + pub fn is_pub_crate(&self) -> bool { + self.kind == PathKind::Crate && self.segments.is_empty() + } + #[allow(non_snake_case)] pub fn is_Self(&self) -> bool { self.kind == PathKind::Plain diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index d81926f7c976..b01f742c3d1c 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -1629,7 +1629,7 @@ pub fn write_visibility( ) -> Result<(), HirDisplayError> { match vis { Visibility::Public => write!(f, "pub "), - Visibility::Module(vis_id) => { + Visibility::Module(vis_id, _) => { let def_map = module_id.def_map(f.db.upcast()); let root_module_id = def_map.module_id(DefMap::ROOT); if vis_id == module_id { diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs index 1f785b5d0a81..43c2f8202744 100644 --- a/crates/ide-assists/src/handlers/auto_import.rs +++ b/crates/ide-assists/src/handlers/auto_import.rs @@ -1548,4 +1548,39 @@ use foo::Foo$0; ", ); } + + #[test] + fn considers_pub_crate() { + check_assist( + auto_import, + r#" +mod foo { + pub struct Foo; +} + +pub(crate) use self::foo::*; + +mod bar { + fn main() { + Foo$0; + } +} +"#, + r#" +mod foo { + pub struct Foo; +} + +pub(crate) use self::foo::*; + +mod bar { + use crate::Foo; + + fn main() { + Foo; + } +} +"#, + ); + } } diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index dbef36026822..6ea604740c61 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -356,7 +356,7 @@ impl Definition { if let Some(Visibility::Public) = vis { return SearchScope::reverse_dependencies(db, module.krate()); } - if let Some(Visibility::Module(module)) = vis { + if let Some(Visibility::Module(module, _)) = vis { return SearchScope::module_and_children(db, module.into()); } From 68a13bf7fd0e456969ea591fc216bf44eea9890d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:07:48 +0100 Subject: [PATCH 094/297] Explain never patterns in resolve --- compiler/rustc_resolve/src/late.rs | 32 +++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5c246893d87d..e100c9254786 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3196,6 +3196,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// consistent when encountering or-patterns and never patterns. /// This is done hygienically: this could arise for a macro that expands into an or-pattern /// where one 'x' was from the user and one 'x' came from the macro. + /// + /// A never pattern by definition indicates an unreachable case. For example, matching on + /// `Result` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn bar(_x: u32) {} + /// let foo: Result = Ok(0); + /// match foo { + /// Ok(x) => bar(x), + /// Err(&!), + /// } + /// ``` + /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to + /// have a binding here, and we tell the user to use `_` instead. fn compute_and_check_binding_map( &mut self, pat: &Pat, @@ -3247,6 +3262,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// have exactly the same set of bindings, with the same binding modes for each. /// Returns the computed binding map and a boolean indicating whether the pattern is a never /// pattern. + /// + /// A never pattern by definition indicates an unreachable case. For example, destructuring a + /// `Result` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn foo() -> Result { Ok(true) } + /// let (Ok(x) | Err(&!)) = foo(); + /// # let _ = x; + /// ``` + /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as + /// the other branches of the or-pattern. So we must ignore never pattern when checking the + /// bindings of an or-pattern. + /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the + /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable). fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P], @@ -3254,7 +3284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); - // 1) Compute the binding maps of all arms; never patterns don't participate in this. + // 1) Compute the binding maps of all arms; we must ignore never patterns here. let not_never_pats = pats .iter() .filter_map(|pat| { From 5ccd29d6f0c8e8f678bb05adfd8482de0ecde0c2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:08:53 +0100 Subject: [PATCH 095/297] Add more tests --- .../rfcs/rfc-0000-never_patterns/bindings.rs | 21 +++++++++++++++ .../rfc-0000-never_patterns/bindings.stderr | 26 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs index 756ead9e184e..f2e238ecb136 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -23,3 +23,24 @@ fn main() { //~| ERROR: never patterns cannot contain variable bindings } } + +fn void(void: Void) { + let (_a | !) = void; + let (! | _a) = void; + let ((_a, _) | (_a, _ | !)) = (true, void); + let (_a | (! | !,)) = (void,); + let ((_a,) | (!,)) = (void,); + + let (_a, (! | !)) = (true, void); + //~^ ERROR: never patterns cannot contain variable bindings + let (_a, (_b | !)) = (true, void); + + let _a @ ! = void; + //~^ ERROR: never patterns cannot contain variable bindings + let _a @ (_b | !) = void; + let (_a @ (), !) = ((), void); + //~^ ERROR: never patterns cannot contain variable bindings + let (_a | + (_b @ (_, !))) = (true, void); + //~^ ERROR: never patterns cannot contain variable bindings +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr index 4e83b843ae85..b69ba80af88e 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -22,5 +22,29 @@ error: never patterns cannot contain variable bindings LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead -error: aborting due to 4 previous errors +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:34:10 + | +LL | let (_a, (! | !)) = (true, void); + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:38:9 + | +LL | let _a @ ! = void; + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:41:10 + | +LL | let (_a @ (), !) = ((), void); + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:44:14 + | +LL | (_b @ (_, !))) = (true, void); + | ^^ help: use a wildcard `_` instead + +error: aborting due to 8 previous errors From fb44c848c3899ed4ece01e63070a45a532e357fc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:34:54 +0000 Subject: [PATCH 096/297] Keep error types around, even in obligations. These help silence follow up errors --- compiler/rustc_infer/src/infer/opaque_types.rs | 7 ------- tests/ui/async-await/issues/issue-65159.rs | 4 ++-- tests/ui/async-await/issues/issue-65159.stderr | 16 ++-------------- .../issue-82126-mismatched-subst-and-hir.rs | 1 - ...issue-82126-mismatched-subst-and-hir.stderr | 18 ++++-------------- tests/ui/impl-trait/issue-72911.rs | 1 + tests/ui/impl-trait/issue-72911.stderr | 13 +++++++++++-- tests/ui/impl-trait/issues/issue-92305.rs | 1 - tests/ui/impl-trait/issues/issue-92305.stderr | 16 ++-------------- 9 files changed, 22 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 11b5b437eff9..db46b39ce25f 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -631,13 +631,6 @@ impl<'tcx> InferCtxt<'tcx> { ct_op: |ct| ct, }); - if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() { - if projection.term.references_error() { - // No point on adding any obligations since there's a type error involved. - obligations.clear(); - return; - } - } // Require that the predicate holds for the concrete type. debug!(?predicate); obligations.push(traits::Obligation::new( diff --git a/tests/ui/async-await/issues/issue-65159.rs b/tests/ui/async-await/issues/issue-65159.rs index aed111e21442..7197a4fb91a0 100644 --- a/tests/ui/async-await/issues/issue-65159.rs +++ b/tests/ui/async-await/issues/issue-65159.rs @@ -5,7 +5,7 @@ async fn copy() -> Result<()> //~^ ERROR enum takes 2 generic arguments { - Ok(()) //~ ERROR: type annotations needed + Ok(()) } -fn main() { } +fn main() {} diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr index 77a0ea5027c1..19512116a66c 100644 --- a/tests/ui/async-await/issues/issue-65159.stderr +++ b/tests/ui/async-await/issues/issue-65159.stderr @@ -11,18 +11,6 @@ help: add missing generic argument LL | async fn copy() -> Result<(), E> | +++ -error[E0282]: type annotations needed - --> $DIR/issue-65159.rs:8:5 - | -LL | Ok(()) - | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` - | -help: consider specifying the generic arguments - | -LL | Ok::<(), E>(()) - | +++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs index c10246eec649..b52939ffc119 100644 --- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs +++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs @@ -17,7 +17,6 @@ async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_> { //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied //~^^ ERROR struct takes 1 generic argument but 0 generic arguments were supplied LockedMarket(coroutine.lock().unwrap().buy()) - //~^ ERROR: cannot return value referencing temporary value } struct LockedMarket(T); diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr index 2b10cf67d15b..516c1d065e67 100644 --- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr +++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr @@ -7,7 +7,7 @@ LL | async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_> | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket(T); | ^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_> | ^^^^^^^^^^^^ expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket(T); | ^^^^^^^^^^^^ - @@ -28,16 +28,6 @@ help: add missing generic argument LL | async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_, T> { | +++ -error[E0515]: cannot return value referencing temporary value - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5 - | -LL | LockedMarket(coroutine.lock().unwrap().buy()) - | ^^^^^^^^^^^^^-------------------------^^^^^^^ - | | | - | | temporary value created here - | returns a value referencing data owned by the current function +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0107, E0515. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/issue-72911.rs b/tests/ui/impl-trait/issue-72911.rs index 63f4898f4306..7ba8579e24fb 100644 --- a/tests/ui/impl-trait/issue-72911.rs +++ b/tests/ui/impl-trait/issue-72911.rs @@ -15,6 +15,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator fn lint_files() -> impl Iterator { //~^ ERROR: failed to resolve + //~| ERROR: `()` is not an iterator unimplemented!() } diff --git a/tests/ui/impl-trait/issue-72911.stderr b/tests/ui/impl-trait/issue-72911.stderr index 0e86561aa277..44c20a7be53d 100644 --- a/tests/ui/impl-trait/issue-72911.stderr +++ b/tests/ui/impl-trait/issue-72911.stderr @@ -1,3 +1,11 @@ +error[E0277]: `()` is not an iterator + --> $DIR/issue-72911.rs:16:20 + | +LL | fn lint_files() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + error[E0433]: failed to resolve: use of undeclared crate or module `foo` --> $DIR/issue-72911.rs:11:33 | @@ -10,6 +18,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | fn lint_files() -> impl Iterator { | ^^^ use of undeclared crate or module `foo` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0433`. +Some errors have detailed explanations: E0277, E0433. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issues/issue-92305.rs b/tests/ui/impl-trait/issues/issue-92305.rs index e16199caaaa2..4a89238d07e6 100644 --- a/tests/ui/impl-trait/issues/issue-92305.rs +++ b/tests/ui/impl-trait/issues/issue-92305.rs @@ -5,7 +5,6 @@ use std::iter; fn f(data: &[T]) -> impl Iterator { //~^ ERROR: missing generics for struct `Vec` [E0107] iter::empty() - //~^ ERROR: type annotations needed } fn g(data: &[T], target: T) -> impl Iterator> { diff --git a/tests/ui/impl-trait/issues/issue-92305.stderr b/tests/ui/impl-trait/issues/issue-92305.stderr index 55e966bd7bfd..88fb1fb27070 100644 --- a/tests/ui/impl-trait/issues/issue-92305.stderr +++ b/tests/ui/impl-trait/issues/issue-92305.stderr @@ -9,18 +9,6 @@ help: add missing generic argument LL | fn f(data: &[T]) -> impl Iterator> { | +++ -error[E0282]: type annotations needed - --> $DIR/issue-92305.rs:7:5 - | -LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` - | -help: consider specifying the generic argument - | -LL | iter::empty::() - | +++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. From 0aedd6e86fd11c146b1bf8f0c38415ca7e66f240 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Jan 2024 18:34:25 +0000 Subject: [PATCH 097/297] Sandwich MIR optimizations between DSE. --- .../src/dead_store_elimination.rs | 12 ++- compiler/rustc_mir_transform/src/lib.rs | 9 +- ...n.DataflowConstProp.32bit.panic-abort.diff | 15 ++-- ....DataflowConstProp.32bit.panic-unwind.diff | 15 ++-- ...n.DataflowConstProp.64bit.panic-abort.diff | 15 ++-- ....DataflowConstProp.64bit.panic-unwind.diff | 15 ++-- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 15 ++-- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 15 ++-- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 15 ++-- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 15 ++-- ...adStoreElimination-final.panic-abort.diff} | 4 +- ...dStoreElimination-final.panic-unwind.diff} | 4 +- ...adStoreElimination-final.panic-abort.diff} | 4 +- ...dStoreElimination-final.panic-unwind.diff} | 4 +- .../dead-store-elimination/call_arg_copy.rs | 12 ++- ...e.cycle.DeadStoreElimination-initial.diff} | 4 +- tests/mir-opt/dead-store-elimination/cycle.rs | 9 +- ...on.main.DeadStoreElimination-initial.diff} | 4 +- .../dead-store-elimination/place_mention.rs | 15 ++-- ..._to_int.DeadStoreElimination-initial.diff} | 4 +- ....retags.DeadStoreElimination-initial.diff} | 4 +- .../provenance_soundness.rs | 18 ++-- ...in.DestinationPropagation.panic-abort.diff | 10 ++- ...n.DestinationPropagation.panic-unwind.diff | 10 ++- ...to_exponential_common.GVN.panic-abort.diff | 34 +++++++- ...o_exponential_common.GVN.panic-unwind.diff | 34 +++++++- ...ine_coroutine.main.Inline.panic-abort.diff | 2 +- ...ne_coroutine.main.Inline.panic-unwind.diff | 2 +- ...inline_diverging.h.Inline.panic-abort.diff | 2 +- ...nline_diverging.h.Inline.panic-unwind.diff | 2 +- ...unchecked.PreCodegen.after.panic-abort.mir | 2 +- ...nchecked.PreCodegen.after.panic-unwind.mir | 2 +- .../issue_101973.inner.GVN.panic-abort.diff | 14 +++- .../issue_101973.inner.GVN.panic-unwind.diff | 14 +++- ...ng.identity.JumpThreading.panic-abort.diff | 4 +- ...g.identity.JumpThreading.panic-unwind.diff | 4 +- ...d_constant.main.GVN.32bit.panic-abort.diff | 16 +++- ..._constant.main.GVN.32bit.panic-unwind.diff | 16 +++- ...d_constant.main.GVN.64bit.panic-abort.diff | 16 +++- ..._constant.main.GVN.64bit.panic-unwind.diff | 16 +++- .../loops.filter_mapped.PreCodegen.after.mir | 2 +- .../loops.int_range.PreCodegen.after.mir | 2 +- .../loops.mapped.PreCodegen.after.mir | 2 +- ...m_replace.mem_replace.PreCodegen.after.mir | 19 +++-- ...o_variable.main.GVN.32bit.panic-abort.diff | 8 +- ..._variable.main.GVN.32bit.panic-unwind.diff | 8 +- ...o_variable.main.GVN.64bit.panic-abort.diff | 8 +- ..._variable.main.GVN.64bit.panic-unwind.diff | 8 +- ...ward_loop.PreCodegen.after.panic-abort.mir | 2 +- ...ard_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...sive_loop.PreCodegen.after.panic-abort.mir | 2 +- ...ive_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...mut_usize.PreCodegen.after.panic-abort.mir | 13 +-- ...ut_usize.PreCodegen.after.panic-unwind.mir | 13 +-- ...mut_range.PreCodegen.after.panic-abort.mir | 17 ++-- ...ut_range.PreCodegen.after.panic-unwind.mir | 17 ++-- ...ated_loop.PreCodegen.after.panic-abort.mir | 19 +++-- ...ted_loop.PreCodegen.after.panic-unwind.mir | 19 +++-- ...ward_loop.PreCodegen.after.panic-abort.mir | 17 ++-- ...ard_loop.PreCodegen.after.panic-unwind.mir | 17 ++-- ...ange_loop.PreCodegen.after.panic-abort.mir | 2 +- ...nge_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...erse_loop.PreCodegen.after.panic-abort.mir | 19 +++-- ...rse_loop.PreCodegen.after.panic-unwind.mir | 19 +++-- .../try_identity.new.PreCodegen.after.mir | 8 +- .../try_identity.old.PreCodegen.after.mir | 4 +- ...t_switch.identity.SeparateConstSwitch.diff | 82 ++++++++++--------- ...witch.too_complex.SeparateConstSwitch.diff | 41 +++++----- .../simplify_match.main.GVN.panic-abort.diff | 10 ++- .../simplify_match.main.GVN.panic-unwind.diff | 10 ++- 70 files changed, 539 insertions(+), 282 deletions(-) rename tests/mir-opt/dead-store-elimination/{call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff => call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff} (64%) rename tests/mir-opt/dead-store-elimination/{call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff => call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff} (64%) rename tests/mir-opt/dead-store-elimination/{call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff => call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff} (78%) rename tests/mir-opt/dead-store-elimination/{call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff => call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff} (78%) rename tests/mir-opt/dead-store-elimination/{cycle.cycle.DeadStoreElimination.diff => cycle.cycle.DeadStoreElimination-initial.diff} (81%) rename tests/mir-opt/dead-store-elimination/{place_mention.main.DeadStoreElimination.diff => place_mention.main.DeadStoreElimination-initial.diff} (73%) rename tests/mir-opt/dead-store-elimination/{provenance_soundness.pointer_to_int.DeadStoreElimination.diff => provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff} (84%) rename tests/mir-opt/dead-store-elimination/{provenance_soundness.retags.DeadStoreElimination.diff => provenance_soundness.retags.DeadStoreElimination-initial.diff} (61%) diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3d74ef7e3278..9dd5aa4c8bd8 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -127,9 +127,19 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { crate::simplify::simplify_locals(body, tcx) } -pub struct DeadStoreElimination; +pub enum DeadStoreElimination { + Initial, + Final, +} impl<'tcx> MirPass<'tcx> for DeadStoreElimination { + fn name(&self) -> &'static str { + match self { + DeadStoreElimination::Initial => "DeadStoreElimination-initial", + DeadStoreElimination::Final => "DeadStoreElimination-final", + } + } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ce9043ec2870..4e8afcd7d2fc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -595,24 +595,25 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &multiple_return_terminators::MultipleReturnTerminators, &instsimplify::InstSimplify, &simplify::SimplifyLocals::BeforeConstProp, - ©_prop::CopyProp, + &dead_store_elimination::DeadStoreElimination::Initial, + &gvn::GVN, + &simplify::SimplifyLocals::AfterGVN, // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may // destroy the SSA property. It should still happen before const-propagation, so the // latter pass will leverage the created opportunities. &separate_const_switch::SeparateConstSwitch, - &gvn::GVN, - &simplify::SimplifyLocals::AfterGVN, &dataflow_const_prop::DataflowConstProp, &const_debuginfo::ConstDebugInfo, &o1(simplify_branches::SimplifyConstCondition::AfterConstProp), &jump_threading::JumpThreading, &early_otherwise_branch::EarlyOtherwiseBranch, &simplify_comparison_integral::SimplifyComparisonIntegral, - &dead_store_elimination::DeadStoreElimination, &dest_prop::DestinationPropagation, &o1(simplify_branches::SimplifyConstCondition::Final), &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::Final), + ©_prop::CopyProp, + &dead_store_elimination::DeadStoreElimination::Final, &nrvo::RenameReturnPlace, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 6925fdb1e704..ffbd97bb5452 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 82ad842505c5..7b6dcf1972b2 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 6925fdb1e704..ffbd97bb5452 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 82ad842505c5..7b6dcf1972b2 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 13545aa464aa..df68ce496fd8 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index bf3269153814..e16ea22091ee 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 13545aa464aa..df68ce496fd8 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index bf3269153814..e16ea22091ee 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff similarity index 64% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff index dc0f9073416f..07fb8301b9a9 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `move_packed` before DeadStoreElimination -+ // MIR for `move_packed` after DeadStoreElimination +- // MIR for `move_packed` before DeadStoreElimination-final ++ // MIR for `move_packed` after DeadStoreElimination-final fn move_packed(_1: Packed) -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff similarity index 64% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff index 86ef026ec5c8..cac3badfa673 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `move_packed` before DeadStoreElimination -+ // MIR for `move_packed` after DeadStoreElimination +- // MIR for `move_packed` before DeadStoreElimination-final ++ // MIR for `move_packed` after DeadStoreElimination-final fn move_packed(_1: Packed) -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff similarity index 78% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff index 8f799b33f45d..268924b7c5dc 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `move_simple` before DeadStoreElimination -+ // MIR for `move_simple` after DeadStoreElimination +- // MIR for `move_simple` before DeadStoreElimination-final ++ // MIR for `move_simple` after DeadStoreElimination-final fn move_simple(_1: i32) -> () { debug x => _1; diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff similarity index 78% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff index 0551d663b50f..bd754f9ebd42 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `move_simple` before DeadStoreElimination -+ // MIR for `move_simple` after DeadStoreElimination +- // MIR for `move_simple` before DeadStoreElimination-final ++ // MIR for `move_simple` after DeadStoreElimination-final fn move_simple(_1: i32) -> () { debug x => _1; diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index 490a4aa502c3..37b3313f7d04 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -1,6 +1,5 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: DeadStoreElimination +// unit-test: DeadStoreElimination-final // compile-flags: -Zmir-enable-passes=+CopyProp #![feature(core_intrinsics)] @@ -12,8 +11,10 @@ use std::intrinsics::mir::*; #[inline(never)] fn use_both(_: i32, _: i32) {} -// EMIT_MIR call_arg_copy.move_simple.DeadStoreElimination.diff +// EMIT_MIR call_arg_copy.move_simple.DeadStoreElimination-final.diff fn move_simple(x: i32) { + // CHECK-LABEL: fn move_simple( + // CHECK: = use_both(_1, move _1) use_both(x, x); } @@ -23,11 +24,14 @@ struct Packed { y: i32, } -// EMIT_MIR call_arg_copy.move_packed.DeadStoreElimination.diff +// EMIT_MIR call_arg_copy.move_packed.DeadStoreElimination-final.diff #[custom_mir(dialect = "analysis")] fn move_packed(packed: Packed) { + // CHECK-LABEL: fn move_packed( + // CHECK: = use_both(const 0_i32, (_1.1: i32)) mir!( { + // We have a packed struct, verify that the copy is not turned into a move. Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue()) } ret = { diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff similarity index 81% rename from tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff index cf73358dc52e..f13588c3aa48 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `cycle` before DeadStoreElimination -+ // MIR for `cycle` after DeadStoreElimination +- // MIR for `cycle` before DeadStoreElimination-initial ++ // MIR for `cycle` after DeadStoreElimination-initial fn cycle(_1: i32, _2: i32, _3: i32) -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index 13e5411275da..e8f566b4aa7b 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -1,9 +1,8 @@ -// skip-filecheck // This example is interesting because the non-transitive version of `MaybeLiveLocals` would // report that *all* of these stores are live. // // needs-unwind -// unit-test: DeadStoreElimination +// unit-test: DeadStoreElimination-initial #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; @@ -13,9 +12,13 @@ fn cond() -> bool { false } -// EMIT_MIR cycle.cycle.DeadStoreElimination.diff +// EMIT_MIR cycle.cycle.DeadStoreElimination-initial.diff #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn cycle(mut x: i32, mut y: i32, mut z: i32) { + // CHECK-LABEL: fn cycle( + // CHECK-NOT: {{_.*}} = {{_.*}}; + // CHECK-NOT: {{_.*}} = move {{_.*}}; + // We use custom MIR to avoid generating debuginfo, that would force to preserve writes. mir!( let condition: bool; diff --git a/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff similarity index 73% rename from tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff index 2130518771a5..5a5502858712 100644 --- a/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before DeadStoreElimination -+ // MIR for `main` after DeadStoreElimination +- // MIR for `main` before DeadStoreElimination-initial ++ // MIR for `main` after DeadStoreElimination-initial fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/place_mention.rs b/tests/mir-opt/dead-store-elimination/place_mention.rs index 4813cf7ee2bd..ae75e622ff7f 100644 --- a/tests/mir-opt/dead-store-elimination/place_mention.rs +++ b/tests/mir-opt/dead-store-elimination/place_mention.rs @@ -1,10 +1,15 @@ -// skip-filecheck -// unit-test: DeadStoreElimination +// Verify that we account for the `PlaceMention` statement as a use of the tuple, +// and don't remove it as a dead store. +// +// unit-test: DeadStoreElimination-initial // compile-flags: -Zmir-keep-place-mention -// EMIT_MIR place_mention.main.DeadStoreElimination.diff +// EMIT_MIR place_mention.main.DeadStoreElimination-initial.diff fn main() { - // Verify that we account for the `PlaceMention` statement as a use of the tuple, - // and don't remove it as a dead store. + // CHECK-LABEL: fn main( + // CHECK-NOT: PlaceMention( + // CHECK: [[tmp:_.*]] = + // CHECK-NEXT: PlaceMention([[tmp:_.*]]); + let (_, _) = ("Hello", "World"); } diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff similarity index 84% rename from tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff index 31f727e5fb35..9b0dc6b6af67 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `pointer_to_int` before DeadStoreElimination -+ // MIR for `pointer_to_int` after DeadStoreElimination +- // MIR for `pointer_to_int` before DeadStoreElimination-initial ++ // MIR for `pointer_to_int` after DeadStoreElimination-initial fn pointer_to_int(_1: *mut i32) -> () { debug p => _1; diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff similarity index 61% rename from tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff index e1ebc39aacc4..ab74d2411bb1 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `retags` before DeadStoreElimination -+ // MIR for `retags` after DeadStoreElimination +- // MIR for `retags` before DeadStoreElimination-initial ++ // MIR for `retags` after DeadStoreElimination-initial fn retags(_1: &mut i32) -> () { debug _r => _1; diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs index 24ffbe980ebc..916c393b9de0 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs @@ -1,17 +1,21 @@ -// skip-filecheck -// unit-test: DeadStoreElimination +// Test that we don't remove pointer to int casts or retags +// unit-test: DeadStoreElimination-initial // compile-flags: -Zmir-emit-retag -// Test that we don't remove pointer to int casts or retags - -// EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination.diff +// EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff fn pointer_to_int(p: *mut i32) { + // CHECK-LABEL: fn pointer_to_int( + // CHECK: {{_.*}} = {{.*}} as usize (PointerExposeAddress); + // CHECK: {{_.*}} = {{.*}} as isize (PointerExposeAddress); let _x = p as usize; let _y = p as isize; } -// EMIT_MIR provenance_soundness.retags.DeadStoreElimination.diff -fn retags(_r: &mut i32) {} +// EMIT_MIR provenance_soundness.retags.DeadStoreElimination-initial.diff +fn retags(_r: &mut i32) { + // CHECK-LABEL: fn retags( + // CHECK: Retag([fn entry] _1); +} fn main() { pointer_to_int(&mut 5 as *mut _); diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 993e0f1d1a67..0af3faf28f07 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -5,12 +5,13 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; + let mut _3: u32; scope 1 { debug un => _1; scope 2 { } scope 4 (inlined std::mem::drop::) { - debug _x => _2; + debug _x => _3; } } scope 3 (inlined val) { @@ -18,10 +19,13 @@ bb0: { StorageLive(_1); - _1 = Un { us: const 1_u32 }; StorageLive(_2); - _2 = (_1.0: u32); + _2 = const 1_u32; + _1 = Un { us: const 1_u32 }; StorageDead(_2); + StorageLive(_3); + _3 = (_1.0: u32); + StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 993e0f1d1a67..0af3faf28f07 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -5,12 +5,13 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; + let mut _3: u32; scope 1 { debug un => _1; scope 2 { } scope 4 (inlined std::mem::drop::) { - debug _x => _2; + debug _x => _3; } } scope 3 (inlined val) { @@ -18,10 +19,13 @@ bb0: { StorageLive(_1); - _1 = Un { us: const 1_u32 }; StorageLive(_2); - _2 = (_1.0: u32); + _2 = const 1_u32; + _1 = Un { us: const 1_u32 }; StorageDead(_2); + StorageLive(_3); + _3 = (_1.0: u32); + StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 0ba1bac0a030..080478ea8841 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -73,31 +73,59 @@ } bb4: { +- StorageLive(_8); ++ nop; _8 = ((_6 as Some).0: usize); + StorageLive(_9); + _9 = _1; + StorageLive(_10); + _10 = _2; StorageLive(_11); _11 = _5; StorageLive(_12); StorageLive(_13); - _13 = _8 as u32 (IntToInt); + StorageLive(_14); + _14 = _8; +- _13 = move _14 as u32 (IntToInt); ++ _13 = _8 as u32 (IntToInt); + StorageDead(_14); _12 = Add(move _13, const 1_u32); StorageDead(_13); - _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; + StorageLive(_15); + _15 = _3; +- _0 = float_to_exponential_common_exact::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind unreachable]; ++ _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; } bb5: { + StorageDead(_15); StorageDead(_12); StorageDead(_11); + StorageDead(_10); + StorageDead(_9); +- StorageDead(_8); ++ nop; goto -> bb8; } bb6: { + StorageLive(_16); + _16 = _1; + StorageLive(_17); + _17 = _2; StorageLive(_18); _18 = _5; - _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; + StorageLive(_19); + _19 = _3; +- _0 = float_to_exponential_common_shortest::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind unreachable]; ++ _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; } bb7: { + StorageDead(_19); StorageDead(_18); + StorageDead(_17); + StorageDead(_16); goto -> bb8; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 27ea43ef12b7..ff8933fca8b2 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -73,31 +73,59 @@ } bb4: { +- StorageLive(_8); ++ nop; _8 = ((_6 as Some).0: usize); + StorageLive(_9); + _9 = _1; + StorageLive(_10); + _10 = _2; StorageLive(_11); _11 = _5; StorageLive(_12); StorageLive(_13); - _13 = _8 as u32 (IntToInt); + StorageLive(_14); + _14 = _8; +- _13 = move _14 as u32 (IntToInt); ++ _13 = _8 as u32 (IntToInt); + StorageDead(_14); _12 = Add(move _13, const 1_u32); StorageDead(_13); - _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; + StorageLive(_15); + _15 = _3; +- _0 = float_to_exponential_common_exact::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind continue]; ++ _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; } bb5: { + StorageDead(_15); StorageDead(_12); StorageDead(_11); + StorageDead(_10); + StorageDead(_9); +- StorageDead(_8); ++ nop; goto -> bb8; } bb6: { + StorageLive(_16); + _16 = _1; + StorageLive(_17); + _17 = _2; StorageLive(_18); _18 = _5; - _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; + StorageLive(_19); + _19 = _3; +- _0 = float_to_exponential_common_shortest::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind continue]; ++ _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; } bb7: { + StorageDead(_19); StorageDead(_18); + StorageDead(_17); + StorageDead(_16); goto -> bb8; } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 68c612314f6d..8e53427e7e06 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -36,7 +36,7 @@ - _4 = g() -> [return: bb1, unwind unreachable]; + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 1bf14e8c3b33..b06db41af9d4 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ - _4 = g() -> [return: bb1, unwind continue]; + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff index da45ebcb4d85..2bbb830fc779 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff @@ -40,7 +40,7 @@ + + bb2: { + StorageDead(_5); -+ _1 = (move _4, move _6); ++ _1 = (_4, _6); + drop(_2) -> [return: bb3, unwind unreachable]; + } + diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index d65c65e5fd03..bc4f2d24df0b 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -43,7 +43,7 @@ + StorageDead(_5); + StorageLive(_7); + _7 = move _4; -+ _1 = (move _7, move _6); ++ _1 = (move _7, _6); + StorageDead(_7); + StorageDead(_4); + drop(_2) -> [return: bb3, unwind continue]; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index aeb93bd334fe..d6a608476df9 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -31,7 +31,7 @@ fn unwrap_unchecked(_1: Option) -> T { _2 = discriminant(_1); _3 = Eq(_2, const 1_isize); assume(move _3); - _0 = move ((_1 as Some).0: T); + _0 = ((_1 as Some).0: T); StorageDead(_3); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index aeb93bd334fe..d6a608476df9 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -31,7 +31,7 @@ fn unwrap_unchecked(_1: Option) -> T { _2 = discriminant(_1); _3 = Eq(_2, const 1_isize); assume(move _3); - _0 = move ((_1 as Some).0: T); + _0 = ((_1 as Some).0: T); StorageDead(_3); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index d2db8f61916a..b04728a9b0f5 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -17,7 +17,7 @@ let mut _12: u32; let mut _13: bool; scope 1 (inlined imm8) { - debug x => _1; + debug x => _5; let mut _14: u32; let mut _15: u32; scope 2 { @@ -33,17 +33,23 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); + StorageLive(_5); + _5 = _1; _4 = const 0_u32; StorageLive(_15); StorageLive(_14); - _14 = Shr(_1, const 0_i32); +- _14 = Shr(_5, const 0_i32); ++ _14 = Shr(_1, const 0_i32); _15 = BitAnd(move _14, const 255_u32); StorageDead(_14); _4 = BitOr(const 0_u32, move _15); StorageDead(_15); + StorageDead(_5); StorageLive(_6); StorageLive(_7); StorageLive(_8); + StorageLive(_9); + _9 = _1; - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); - assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind unreachable]; @@ -53,7 +59,9 @@ } bb1: { - _8 = Shr(_1, const 8_i32); +- _8 = Shr(move _9, const 8_i32); ++ _8 = Shr(_1, const 8_i32); + StorageDead(_9); _7 = BitAnd(move _8, const 15_u32); StorageDead(_8); - _12 = const 1_i32 as u32 (IntToInt); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index 514183b3bc05..fcf99ac6918d 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -17,7 +17,7 @@ let mut _12: u32; let mut _13: bool; scope 1 (inlined imm8) { - debug x => _1; + debug x => _5; let mut _14: u32; let mut _15: u32; scope 2 { @@ -33,17 +33,23 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); + StorageLive(_5); + _5 = _1; _4 = const 0_u32; StorageLive(_15); StorageLive(_14); - _14 = Shr(_1, const 0_i32); +- _14 = Shr(_5, const 0_i32); ++ _14 = Shr(_1, const 0_i32); _15 = BitAnd(move _14, const 255_u32); StorageDead(_14); _4 = BitOr(const 0_u32, move _15); StorageDead(_15); + StorageDead(_5); StorageLive(_6); StorageLive(_7); StorageLive(_8); + StorageLive(_9); + _9 = _1; - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); - assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind continue]; @@ -53,7 +59,9 @@ } bb1: { - _8 = Shr(_1, const 8_i32); +- _8 = Shr(move _9, const 8_i32); ++ _8 = Shr(_1, const 8_i32); + StorageDead(_9); _7 = BitAnd(move _8, const 15_u32); StorageDead(_8); - _12 = const 1_i32 as u32 (IntToInt); diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index f04ca72dd6d9..9cc4385f60b8 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -110,7 +110,7 @@ bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); - _13 = Result::::Err(move _12); + _13 = Result::::Err(_12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; @@ -119,7 +119,7 @@ bb7: { _11 = move ((_4 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(move _11); + _3 = ControlFlow::, i32>::Continue(_11); goto -> bb5; + } + diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index f04ca72dd6d9..9cc4385f60b8 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -110,7 +110,7 @@ bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); - _13 = Result::::Err(move _12); + _13 = Result::::Err(_12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; @@ -119,7 +119,7 @@ bb7: { _11 = move ((_4 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(move _11); + _3 = ControlFlow::, i32>::Continue(_11); goto -> bb5; + } + diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 47e0d402347d..3cb440968816 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined #[track_caller] Result::, std::alloc::AllocError>::unwrap) { debug self => _6; @@ -51,6 +51,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -74,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_8); + StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); @@ -109,6 +119,8 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index dee57ce6c27b..06d5e615b144 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined NonNull::<[u8]>::as_ptr) { debug self => _5; @@ -36,6 +36,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -56,6 +58,8 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } @@ -72,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind continue]; } bb4: { + StorageDead(_8); + StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index a255b15920cb..eb54cc7da855 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined #[track_caller] Result::, std::alloc::AllocError>::unwrap) { debug self => _6; @@ -51,6 +51,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -74,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_8); + StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); @@ -109,6 +119,8 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index 192ffea25915..4200ce3087f3 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined NonNull::<[u8]>::as_ptr) { debug self => _5; @@ -36,6 +36,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -56,6 +58,8 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } @@ -72,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind continue]; } bb4: { + StorageDead(_8); + StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 8dbb688999a0..8d182069adc9 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -32,7 +32,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () bb1: { StorageLive(_4); - _4 = move _3; + _4 = _3; goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 42c7eb3c6aad..e27e417ed4ae 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -46,7 +46,7 @@ fn int_range(_1: usize, _2: usize) -> () { bb0: { _3 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_4); - _4 = move _3; + _4 = _3; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 30bdc1310908..b800a1be22ba 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -27,7 +27,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb1: { StorageLive(_4); - _4 = move _3; + _4 = _3; goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir index 713d6cc558ac..f0cb4ca31fec 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir @@ -19,22 +19,23 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } scope 4 (inlined std::ptr::read::) { debug src => _1; + let mut _3: *const u32; scope 5 { scope 6 (inlined std::ptr::read::runtime::) { - debug src => _1; + debug src => _3; scope 7 (inlined intrinsics::is_aligned_and_not_null::) { - debug ptr => _1; + debug ptr => _3; scope 8 (inlined std::ptr::const_ptr::::is_null) { - debug self => _1; - let mut _3: *const u8; + debug self => _3; + let mut _4: *const u8; scope 9 { scope 10 (inlined std::ptr::const_ptr::::is_null::runtime_impl) { - debug ptr => _3; + debug ptr => _4; scope 11 (inlined std::ptr::const_ptr::::addr) { - debug self => _3; + debug self => _4; scope 12 { scope 13 (inlined std::ptr::const_ptr::::cast::<()>) { - debug self => _3; + debug self => _4; } } } @@ -42,7 +43,7 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } } scope 14 (inlined std::ptr::const_ptr::::is_aligned) { - debug self => _1; + debug self => _3; scope 15 (inlined align_of::) { } } @@ -55,7 +56,9 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { bb0: { StorageLive(_3); + StorageLive(_4); _0 = (*_1); + StorageDead(_4); StorageDead(_3); (*_1) = _2; return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff index 4e34233a9798..0e7e1f971ec3 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff index 275f17e52aec..9071a3339c08 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff index 4e34233a9798..0e7e1f971ec3 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index 275f17e52aec..9071a3339c08 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index e5940bd82019..99805da56694 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -49,7 +49,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 87e7485cb360..f40f13071756 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -49,7 +49,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir index 1b23e421368b..0836600cb6e6 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir @@ -34,7 +34,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index a677e8b439fa..8c1794de5244 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -34,7 +34,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir index a12411a04137..cdbd8d89f28c 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir @@ -20,7 +20,8 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { debug self => _2; debug slice => _5; let mut _6: *mut u32; - let mut _9: &[&str]; + let mut _9: *mut [u32]; + let mut _10: &[&str]; scope 5 { scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { debug self => _5; @@ -33,16 +34,16 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _10: *const [u32]; + debug self => _9; + let mut _11: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _10; + debug ptr => _11; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _9; + debug pieces => _10; } } } @@ -70,10 +71,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { _5 = &raw mut (*_1); StorageLive(_9); StorageLive(_10); + StorageLive(_11); StorageLive(_6); _6 = _5 as *mut u32 (PtrToPtr); _7 = Offset(_6, _2); StorageDead(_6); + StorageDead(_11); StorageDead(_10); StorageDead(_9); StorageDead(_5); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index a12411a04137..cdbd8d89f28c 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -20,7 +20,8 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { debug self => _2; debug slice => _5; let mut _6: *mut u32; - let mut _9: &[&str]; + let mut _9: *mut [u32]; + let mut _10: &[&str]; scope 5 { scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { debug self => _5; @@ -33,16 +34,16 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _10: *const [u32]; + debug self => _9; + let mut _11: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _10; + debug ptr => _11; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _9; + debug pieces => _10; } } } @@ -70,10 +71,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { _5 = &raw mut (*_1); StorageLive(_9); StorageLive(_10); + StorageLive(_11); StorageLive(_6); _6 = _5 as *mut u32 (PtrToPtr); _7 = Offset(_6, _2); StorageDead(_6); + StorageDead(_11); StorageDead(_10); StorageDead(_9); StorageDead(_5); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 0d95f81c37c5..36329f8fc684 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -19,7 +19,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; - let mut _14: &[&str]; + let mut _14: *mut [u32]; + let mut _15: &[&str]; scope 4 { let _6: usize; scope 5 { @@ -53,16 +54,16 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _15: *const [u32]; + debug self => _14; + let mut _16: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _15; + debug ptr => _16; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _14; + debug pieces => _15; } } } @@ -74,8 +75,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); - StorageLive(_6); StorageLive(_15); + StorageLive(_6); + StorageLive(_16); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -96,8 +98,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_15); + StorageDead(_16); StorageDead(_6); + StorageDead(_15); StorageDead(_14); StorageDead(_5); _0 = &mut (*_13); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 0d95f81c37c5..36329f8fc684 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -19,7 +19,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; - let mut _14: &[&str]; + let mut _14: *mut [u32]; + let mut _15: &[&str]; scope 4 { let _6: usize; scope 5 { @@ -53,16 +54,16 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _15: *const [u32]; + debug self => _14; + let mut _16: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _15; + debug ptr => _16; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _14; + debug pieces => _15; } } } @@ -74,8 +75,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); - StorageLive(_6); StorageLive(_15); + StorageLive(_6); + StorageLive(_16); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -96,8 +98,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_15); + StorageDead(_16); StorageDead(_6); + StorageDead(_15); StorageDead(_14); StorageDead(_5); _0 = &mut (*_13); diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index c58b630a0c36..26b2663fa358 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -42,20 +42,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -131,8 +132,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -143,10 +146,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Enumerate::> { iter: move _13, count: const 0_usize }; + _14 = Enumerate::> { iter: _13, count: const 0_usize }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 1a805f0fd8dc..a055612bd5fe 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -42,20 +42,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -131,8 +132,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -143,10 +146,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Enumerate::> { iter: move _13, count: const 0_usize }; + _14 = Enumerate::> { iter: _13, count: const 0_usize }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 09075eed6a9c..471491108e0b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -39,20 +39,21 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _22: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _22; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _22: *mut u8; + debug self => _22; + let mut _23: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _22; + debug ptr => _23; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _22; + debug self => _23; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _22; + debug self => _23; } } } @@ -121,8 +122,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_22); + StorageLive(_23); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_23); StorageDead(_22); StorageDead(_10); StorageDead(_9); @@ -134,7 +137,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_7); StorageDead(_4); StorageLive(_14); - _14 = move _13; + _14 = _13; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 47b84746468a..bbf38aba91f0 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -39,20 +39,21 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _22: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _22; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _22: *mut u8; + debug self => _22; + let mut _23: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _22; + debug ptr => _23; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _22; + debug self => _23; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _22; + debug self => _23; } } } @@ -121,8 +122,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_22); + StorageLive(_23); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_23); StorageDead(_22); StorageDead(_10); StorageDead(_9); @@ -134,7 +137,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_7); StorageDead(_4); StorageLive(_14); - _14 = move _13; + _14 = _13; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index 6a99f15774ff..83915d3c4493 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -58,7 +58,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _4 = std::ops::Range:: { start: const 0_usize, end: move _3 }; StorageDead(_3); StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 4f028fa0a646..0a005a460e84 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -58,7 +58,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _4 = std::ops::Range:: { start: const 0_usize, end: move _3 }; StorageDead(_3); StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 5ed7ca5e2b86..f9c8ab4db60b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -44,20 +44,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -133,8 +134,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -145,10 +148,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Rev::> { iter: move _13 }; + _14 = Rev::> { iter: _13 }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index bbb979d23b36..65f423ac326b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -44,20 +44,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -133,8 +134,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -145,10 +148,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Rev::> { iter: move _13 }; + _14 = Rev::> { iter: _13 }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir index 0bf4a2670020..c1d4d4871d02 100644 --- a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir @@ -31,13 +31,13 @@ fn new(_1: Result) -> Result { bb1: { _3 = move ((_1 as Ok).0: T); - _4 = ControlFlow::::Continue(move _3); + _4 = ControlFlow::::Continue(_3); goto -> bb3; } bb2: { _5 = move ((_1 as Err).0: E); - _4 = ControlFlow::::Break(move _5); + _4 = ControlFlow::::Break(_5); goto -> bb3; } @@ -48,14 +48,14 @@ fn new(_1: Result) -> Result { bb4: { _7 = move ((_4 as Continue).0: T); - _0 = Result::::Ok(move _7); + _0 = Result::::Ok(_7); StorageDead(_4); goto -> bb6; } bb5: { _8 = move ((_4 as Break).0: E); - _0 = Result::::Err(move _8); + _0 = Result::::Err(_8); StorageDead(_4); goto -> bb6; } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index 7ccb8b0430de..d6883ac9fda0 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -20,13 +20,13 @@ fn old(_1: Result) -> Result { bb1: { _3 = move ((_1 as Ok).0: T); - _0 = Result::::Ok(move _3); + _0 = Result::::Ok(_3); goto -> bb3; } bb2: { _4 = move ((_1 as Err).0: E); - _0 = Result::::Err(move _4); + _0 = Result::::Err(_4); goto -> bb3; } diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index a12db0a730c5..e7280f148377 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -4,92 +4,96 @@ fn identity(_1: Result) -> Result { debug x => _1; let mut _0: std::result::Result; - let mut _2: i32; - let mut _3: std::ops::ControlFlow, i32>; - let mut _4: std::result::Result; - let mut _5: isize; - let _6: std::result::Result; - let mut _7: std::result::Result; - let _8: i32; + let mut _2: std::ops::ControlFlow, i32>; + let mut _3: std::result::Result; + let mut _4: isize; + let _5: std::result::Result; + let mut _6: std::result::Result; + let _7: i32; scope 1 { - debug residual => _6; + debug residual => _5; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { debug residual => _6; - let _13: i32; - let mut _14: i32; + let _12: i32; scope 9 { - debug e => _13; + debug e => _12; scope 10 (inlined >::from) { - debug t => _13; + debug t => _12; } } } } } scope 3 { - debug val => _8; + debug val => _7; scope 4 { } } scope 5 (inlined as Try>::branch) { - debug self => _1; - let mut _9: isize; + debug self => _3; + let mut _8: isize; + let _9: i32; let _10: i32; - let _11: i32; - let mut _12: std::result::Result; + let mut _11: std::result::Result; scope 6 { - debug v => _10; + debug v => _9; } scope 7 { - debug e => _11; + debug e => _10; } } bb0: { + StorageLive(_2); StorageLive(_3); + _3 = _1; + StorageLive(_8); StorageLive(_9); StorageLive(_10); - StorageLive(_11); - _9 = discriminant(_1); - switchInt(move _9) -> [0: bb5, 1: bb4, otherwise: bb6]; + _8 = discriminant(_1); + switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb6]; } bb1: { - _8 = ((_3 as Continue).0: i32); - _0 = Result::::Ok(_8); - StorageDead(_3); + _7 = ((_2 as Continue).0: i32); + _0 = Result::::Ok(_7); + StorageDead(_2); return; } bb2: { - _6 = ((_3 as Break).0: std::result::Result); - _13 = ((_6 as Err).0: i32); - _0 = Result::::Err(move _13); - StorageDead(_3); + _5 = ((_2 as Break).0: std::result::Result); + StorageLive(_6); + _6 = _5; + _12 = move ((_5 as Err).0: i32); + _0 = Result::::Err(_12); + StorageDead(_6); + StorageDead(_2); return; } bb3: { - StorageDead(_11); StorageDead(_10); StorageDead(_9); - _5 = discriminant(_3); - switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb6]; + StorageDead(_8); + StorageDead(_3); + _4 = discriminant(_2); + switchInt(move _4) -> [0: bb1, 1: bb2, otherwise: bb6]; } bb4: { - _11 = ((_1 as Err).0: i32); - StorageLive(_12); - _12 = Result::::Err(move _11); - _3 = ControlFlow::, i32>::Break(move _12); - StorageDead(_12); + _10 = move ((_1 as Err).0: i32); + StorageLive(_11); + _11 = Result::::Err(_10); + _2 = ControlFlow::, i32>::Break(move _11); + StorageDead(_11); goto -> bb3; } bb5: { - _10 = ((_1 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(move _10); + _9 = move ((_1 as Ok).0: i32); + _2 = ControlFlow::, i32>::Continue(_9); goto -> bb3; } diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff index 80f40b86919e..294bfa661cfa 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff @@ -7,24 +7,21 @@ let mut _2: std::ops::ControlFlow; let mut _3: isize; let _4: i32; - let mut _5: i32; - let _6: usize; - let mut _7: usize; - let mut _8: isize; - let _9: i32; - let mut _10: i32; - let _11: usize; + let _5: usize; + let mut _6: isize; + let _7: i32; + let _8: usize; scope 1 { debug v => _4; } scope 2 { - debug r => _6; + debug r => _5; } scope 3 { - debug v => _9; + debug v => _7; } scope 4 { - debug r => _11; + debug r => _8; } bb0: { @@ -34,8 +31,8 @@ } bb1: { - _6 = ((_1 as Err).0: usize); - _2 = ControlFlow::::Break(_6); + _5 = ((_1 as Err).0: usize); + _2 = ControlFlow::::Break(_5); goto -> bb3; } @@ -46,21 +43,21 @@ } bb3: { - _8 = discriminant(_2); - switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb7]; + _6 = discriminant(_2); + switchInt(move _6) -> [0: bb5, 1: bb4, otherwise: bb7]; } bb4: { - StorageLive(_11); - _11 = ((_2 as Break).0: usize); - _0 = Option::::None; - StorageDead(_11); + StorageLive(_8); + _8 = ((_2 as Break).0: usize); + _0 = const Option::::None; + StorageDead(_8); goto -> bb6; } bb5: { - _9 = ((_2 as Continue).0: i32); - _0 = Option::::Some(_9); + _7 = ((_2 as Continue).0: i32); + _0 = Option::::Some(_7); goto -> bb6; } @@ -74,3 +71,7 @@ } } + ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ + } + diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff index d7ade041e4cc..33b36f660cb3 100644 --- a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff @@ -10,8 +10,15 @@ } bb0: { + StorageLive(_1); +- StorageLive(_2); ++ nop; _2 = const false; -- switchInt(_2) -> [0: bb2, otherwise: bb1]; +- _1 = _2; +- StorageDead(_2); +- switchInt(_1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; ++ nop; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } @@ -20,6 +27,7 @@ } bb2: { + StorageDead(_1); return; } } diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff index 931c5c43c4c6..e5c3adff6236 100644 --- a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff @@ -10,8 +10,15 @@ } bb0: { + StorageLive(_1); +- StorageLive(_2); ++ nop; _2 = const false; -- switchInt(_2) -> [0: bb2, otherwise: bb1]; +- _1 = _2; +- StorageDead(_2); +- switchInt(_1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; ++ nop; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } @@ -20,6 +27,7 @@ } bb2: { + StorageDead(_1); return; } } From 974b727874b18a161c17fd0eaa4ca883d05bf19a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Jan 2024 20:01:52 +0000 Subject: [PATCH 098/297] Bless ui-fulldeps. --- tests/ui-fulldeps/stable-mir/check_allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 7ce3597206b6..93def93127c8 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -111,7 +111,7 @@ fn check_other_consts(item: CrateItem) { // Instance body will force constant evaluation. let body = Instance::try_from(item).unwrap().body().unwrap(); let assigns = collect_consts(&body); - assert_eq!(assigns.len(), 9); + assert_eq!(assigns.len(), 8); for (name, alloc) in assigns { match name.as_str() { "_max_u128" => { From bc35ee41fa6751a85a528656953b581fb02ddd25 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Jan 2024 12:22:33 +0000 Subject: [PATCH 099/297] Do not run simplify_locals inside DSE. The full pass is run short after. --- compiler/rustc_mir_transform/src/dead_store_elimination.rs | 2 -- ....move_simple.DeadStoreElimination-final.panic-abort.diff | 4 ++-- ...move_simple.DeadStoreElimination-final.panic-unwind.diff | 4 ++-- .../cycle.cycle.DeadStoreElimination-initial.diff | 6 +++++- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 9dd5aa4c8bd8..c27718d7bdac 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -123,8 +123,6 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let Operand::Copy(place) = *arg else { bug!() }; *arg = Operand::Move(place); } - - crate::simplify::simplify_locals(body, tcx) } pub enum DeadStoreElimination { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff index 268924b7c5dc..f9bc9405d6a4 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff @@ -5,8 +5,8 @@ debug x => _1; let mut _0: (); let _2: (); -- let mut _3: i32; -- let mut _4: i32; + let mut _3: i32; + let mut _4: i32; bb0: { StorageLive(_2); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff index bd754f9ebd42..efe165422d94 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff @@ -5,8 +5,8 @@ debug x => _1; let mut _0: (); let _2: (); -- let mut _3: i32; -- let mut _4: i32; + let mut _3: i32; + let mut _4: i32; bb0: { StorageLive(_2); diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff index f13588c3aa48..2766b6ce6a9f 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff @@ -4,7 +4,7 @@ fn cycle(_1: i32, _2: i32, _3: i32) -> () { let mut _0: (); let mut _4: bool; -- let mut _5: i32; + let mut _5: i32; bb0: { _4 = cond() -> [return: bb1, unwind continue]; @@ -19,6 +19,10 @@ - _3 = _2; - _2 = _1; - _1 = _5; ++ nop; ++ nop; ++ nop; ++ nop; _4 = cond() -> [return: bb1, unwind continue]; } From b6e6d5d3af99aa771b2f34fb8fcbca03679e0320 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 11 Jan 2024 11:36:10 +0100 Subject: [PATCH 100/297] internal: Consider all kinds of explicit private imports in find_path --- crates/base-db/src/lib.rs | 10 +- crates/hir-def/src/body/lower.rs | 5 +- crates/hir-def/src/child_by_source.rs | 2 +- crates/hir-def/src/find_path.rs | 197 +++++++++--------- crates/hir-def/src/item_scope.rs | 89 ++++---- crates/hir-def/src/item_tree.rs | 37 ++-- crates/hir-def/src/item_tree/pretty.rs | 4 +- crates/hir-def/src/nameres.rs | 8 +- crates/hir-def/src/nameres/path_resolution.rs | 11 +- crates/hir-def/src/resolver.rs | 2 +- crates/hir-def/src/visibility.rs | 26 +-- crates/hir-expand/src/mod_path.rs | 4 - crates/hir-ty/src/method_resolution.rs | 35 +--- crates/hir/src/lib.rs | 2 +- crates/hir/src/symbols.rs | 2 +- 15 files changed, 211 insertions(+), 223 deletions(-) diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index c2ab95064897..92d2b9c3f57c 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -7,7 +7,6 @@ mod change; use std::panic; -use rustc_hash::FxHashSet; use syntax::{ast, Parse, SourceFile}; use triomphe::Arc; @@ -90,15 +89,16 @@ pub trait SourceDatabaseExt: SourceDatabase { fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<[CrateId]> { let graph = db.crate_graph(); - graph + let mut crates = graph .iter() .filter(|&krate| { let root_file = graph[krate].root_file_id; db.file_source_root(root_file) == id }) - .collect::>() - .into_iter() - .collect() + .collect::>(); + crates.sort(); + crates.dedup(); + crates.into_iter().collect() } /// Silly workaround for cyclic deps between the traits diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index c728570d9866..fc0a4eb43dc2 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -965,11 +965,10 @@ impl ExprCollector<'_> { let res = match self.def_map.modules[module] .scope - .macro_invocations - .get(&InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr))) + .macro_invoc(InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr))) { // fast path, macro call is in a block module - Some(&call) => Ok(self.expander.enter_expand_id(self.db, call)), + Some(call) => Ok(self.expander.enter_expand_id(self.db, call)), None => self.expander.enter_expand(self.db, mcall, |path| { self.def_map .resolve_path( diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index c82d2347de5c..32c53cb95031 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -92,7 +92,7 @@ impl ChildBySource for ItemScope { self.impls().for_each(|imp| add_impl(db, res, file_id, imp)); self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext)); self.use_decls().for_each(|ext| add_use(db, res, file_id, ext)); - self.unnamed_consts().for_each(|konst| { + self.unnamed_consts(db).for_each(|konst| { let loc = konst.lookup(db); if loc.id.file_id() == file_id { res[keys::CONST].insert(loc.source(db).value, konst); diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index e8086be86f48..67e43f15cd3f 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -10,7 +10,7 @@ use crate::{ item_scope::ItemInNs, nameres::DefMap, path::{ModPath, PathKind}, - visibility::Visibility, + visibility::{Visibility, VisibilityExplicity}, CrateRootModuleId, ModuleDefId, ModuleId, }; @@ -24,7 +24,7 @@ pub fn find_path( prefer_prelude: bool, ) -> Option { let _p = profile::span("find_path"); - find_path_inner(db, item, from, None, prefer_no_std, prefer_prelude) + find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from) } pub fn find_path_prefixed( @@ -36,7 +36,11 @@ pub fn find_path_prefixed( prefer_prelude: bool, ) -> Option { let _p = profile::span("find_path_prefixed"); - find_path_inner(db, item, from, Some(prefix_kind), prefer_no_std, prefer_prelude) + find_path_inner( + FindPathCtx { db, prefixed: Some(prefix_kind), prefer_no_std, prefer_prelude }, + item, + from, + ) } #[derive(Copy, Clone, Debug)] @@ -83,64 +87,60 @@ impl PrefixKind { } } -/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId -fn find_path_inner( - db: &dyn DefDatabase, - item: ItemInNs, - from: ModuleId, +#[derive(Copy, Clone)] +struct FindPathCtx<'db> { + db: &'db dyn DefDatabase, prefixed: Option, prefer_no_std: bool, prefer_prelude: bool, -) -> Option { +} + +/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId +fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Option { // - if the item is a builtin, it's in scope if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item { return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name()))); } - let def_map = from.def_map(db); + let def_map = from.def_map(ctx.db); let crate_root = def_map.crate_root(); // - if the item is a module, jump straight to module search if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item { let mut visited_modules = FxHashSet::default(); return find_path_for_module( - db, + FindPathCtx { + prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate), + ..ctx + }, &def_map, &mut visited_modules, crate_root, from, module_id, MAX_PATH_LEN, - prefixed, - prefer_no_std || db.crate_supports_no_std(crate_root.krate), - prefer_prelude, ) .map(|(item, _)| item); } // - if the item is already in scope, return the name under which it is - let scope_name = find_in_scope(db, &def_map, from, item); - if prefixed.is_none() { + let scope_name = find_in_scope(ctx.db, &def_map, from, item); + if ctx.prefixed.is_none() { if let Some(scope_name) = scope_name { return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name))); } } // - if the item is in the prelude, return the name from there - if let value @ Some(_) = find_in_prelude(db, &crate_root.def_map(db), &def_map, item, from) { + if let value @ Some(_) = + find_in_prelude(ctx.db, &crate_root.def_map(ctx.db), &def_map, item, from) + { return value; } if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { // - if the item is an enum variant, refer to it via the enum - if let Some(mut path) = find_path_inner( - db, - ItemInNs::Types(variant.parent.into()), - from, - prefixed, - prefer_no_std, - prefer_prelude, - ) { - let data = db.enum_data(variant.parent); + if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(variant.parent.into()), from) { + let data = ctx.db.enum_data(variant.parent); path.push_segment(data.variants[variant.local_id].name.clone()); return Some(path); } @@ -152,32 +152,29 @@ fn find_path_inner( let mut visited_modules = FxHashSet::default(); calculate_best_path( - db, + FindPathCtx { + prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate), + ..ctx + }, &def_map, &mut visited_modules, crate_root, MAX_PATH_LEN, item, from, - prefixed, - prefer_no_std || db.crate_supports_no_std(crate_root.krate), - prefer_prelude, scope_name, ) .map(|(item, _)| item) } fn find_path_for_module( - db: &dyn DefDatabase, + ctx: FindPathCtx<'_>, def_map: &DefMap, visited_modules: &mut FxHashSet, crate_root: CrateRootModuleId, from: ModuleId, module_id: ModuleId, max_len: usize, - prefixed: Option, - prefer_no_std: bool, - prefer_prelude: bool, ) -> Option<(ModPath, Stability)> { if max_len == 0 { return None; @@ -185,8 +182,8 @@ fn find_path_for_module( // Base cases: // - if the item is already in scope, return the name under which it is - let scope_name = find_in_scope(db, def_map, from, ItemInNs::Types(module_id.into())); - if prefixed.is_none() { + let scope_name = find_in_scope(ctx.db, def_map, from, ItemInNs::Types(module_id.into())); + if ctx.prefixed.is_none() { if let Some(scope_name) = scope_name { return Some((ModPath::from_segments(PathKind::Plain, Some(scope_name)), Stable)); } @@ -198,20 +195,20 @@ fn find_path_for_module( } // - if relative paths are fine, check if we are searching for a parent - if prefixed.filter(PrefixKind::is_absolute).is_none() { + if ctx.prefixed.filter(PrefixKind::is_absolute).is_none() { if let modpath @ Some(_) = find_self_super(def_map, module_id, from) { return modpath.zip(Some(Stable)); } } // - if the item is the crate root of a dependency crate, return the name from the extern prelude - let root_def_map = crate_root.def_map(db); + let root_def_map = crate_root.def_map(ctx.db); for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() { if module_id == def_id { let name = scope_name.unwrap_or_else(|| name.clone()); let name_already_occupied_in_type_ns = def_map - .with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { + .with_ancestor_maps(ctx.db, from.local_id, &mut |def_map, local_id| { def_map[local_id] .scope .type_(&name) @@ -229,21 +226,18 @@ fn find_path_for_module( } if let value @ Some(_) = - find_in_prelude(db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from) + find_in_prelude(ctx.db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from) { return value.zip(Some(Stable)); } calculate_best_path( - db, + ctx, def_map, visited_modules, crate_root, max_len, ItemInNs::Types(module_id.into()), from, - prefixed, - prefer_no_std, - prefer_prelude, scope_name, ) } @@ -256,7 +250,7 @@ fn find_in_scope( item: ItemInNs, ) -> Option { def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { - def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone()) + def_map[local_id].scope.name_of(item).map(|(name, _, _)| name.clone()) }) } @@ -273,7 +267,7 @@ fn find_in_prelude( // Preludes in block DefMaps are ignored, only the crate DefMap is searched let prelude_def_map = prelude_module.def_map(db); let prelude_scope = &prelude_def_map[prelude_module.local_id].scope; - let (name, vis) = prelude_scope.name_of(item)?; + let (name, vis, _declared) = prelude_scope.name_of(item)?; if !vis.is_visible_from(db, from) { return None; } @@ -315,16 +309,13 @@ fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option, def_map: &DefMap, visited_modules: &mut FxHashSet, crate_root: CrateRootModuleId, max_len: usize, item: ItemInNs, from: ModuleId, - mut prefixed: Option, - prefer_no_std: bool, - prefer_prelude: bool, scope_name: Option, ) -> Option<(ModPath, Stability)> { if max_len <= 1 { @@ -341,32 +332,29 @@ fn calculate_best_path( }; // Recursive case: // - otherwise, look for modules containing (reexporting) it and import it from one of those - if item.krate(db) == Some(from.krate) { + if item.krate(ctx.db) == Some(from.krate) { let mut best_path_len = max_len; // Item was defined in the same crate that wants to import it. It cannot be found in any // dependency in this case. - for (module_id, name) in find_local_import_locations(db, item, from) { + for (module_id, name) in find_local_import_locations(ctx.db, item, from) { if !visited_modules.insert(module_id) { cov_mark::hit!(recursive_imports); continue; } if let Some(mut path) = find_path_for_module( - db, + ctx, def_map, visited_modules, crate_root, from, module_id, best_path_len - 1, - prefixed, - prefer_no_std, - prefer_prelude, ) { path.0.push_segment(name); let new_path = match best_path.take() { Some(best_path) => { - select_best_path(best_path, path, prefer_no_std, prefer_prelude) + select_best_path(best_path, path, ctx.prefer_no_std, ctx.prefer_prelude) } None => path, }; @@ -379,8 +367,8 @@ fn calculate_best_path( // too (unless we can't name it at all). It could *also* be (re)exported by the same crate // that wants to import it here, but we always prefer to use the external path here. - for dep in &db.crate_graph()[from.krate].dependencies { - let import_map = db.import_map(dep.crate_id); + for dep in &ctx.db.crate_graph()[from.krate].dependencies { + let import_map = ctx.db.import_map(dep.crate_id); let Some(import_info_for) = import_map.import_info_for(item) else { continue }; for info in import_info_for { if info.is_doc_hidden { @@ -391,16 +379,13 @@ fn calculate_best_path( // Determine best path for containing module and append last segment from `info`. // FIXME: we should guide this to look up the path locally, or from the same crate again? let Some((mut path, path_stability)) = find_path_for_module( - db, + ctx, def_map, visited_modules, crate_root, from, info.container, max_len - 1, - prefixed, - prefer_no_std, - prefer_prelude, ) else { continue; }; @@ -413,17 +398,21 @@ fn calculate_best_path( ); let new_path_with_stab = match best_path.take() { - Some(best_path) => { - select_best_path(best_path, path_with_stab, prefer_no_std, prefer_prelude) - } + Some(best_path) => select_best_path( + best_path, + path_with_stab, + ctx.prefer_no_std, + ctx.prefer_prelude, + ), None => path_with_stab, }; update_best_path(&mut best_path, new_path_with_stab); } } } - if let Some(module) = item.module(db) { - if module.containing_block().is_some() && prefixed.is_some() { + let mut prefixed = ctx.prefixed; + if let Some(module) = item.module(ctx.db) { + if module.containing_block().is_some() && ctx.prefixed.is_some() { cov_mark::hit!(prefixed_in_block_expression); prefixed = Some(PrefixKind::Plain); } @@ -548,45 +537,35 @@ fn find_local_import_locations( &ext_def_map[module.local_id] }; - if let Some((name, vis)) = data.scope.name_of(item) { + if let Some((name, vis, declared)) = data.scope.name_of(item) { if vis.is_visible_from(db, from) { - let is_private = match vis { - Visibility::Module(private_mod, private_vis) => { - if private_mod == def_map.module_id(DefMap::ROOT) - && private_vis.is_explicit() - { - // Treat `pub(crate)` imports as non-private, so - // that we suggest adding `use crate::Foo;` instead - // of `use crate::foo::Foo;` etc. - false - } else { - private_mod.local_id == module.local_id - } + let is_pub_or_explicit = match vis { + Visibility::Module(_, VisibilityExplicity::Explicit) => { + cov_mark::hit!(explicit_private_imports); + true } - Visibility::Public => false, - }; - let is_original_def = match item.as_module_def_id() { - Some(module_def_id) => data.scope.declarations().any(|it| it == module_def_id), - None => false, + Visibility::Module(_, VisibilityExplicity::Implicit) => { + cov_mark::hit!(discount_private_imports); + false + } + Visibility::Public => true, }; - // Ignore private imports. these could be used if we are + // Ignore private imports unless they are explicit. these could be used if we are // in a submodule of this module, but that's usually not // what the user wants; and if this module can import // the item and we're a submodule of it, so can we. // Also this keeps the cached data smaller. - if !is_private || is_original_def { + if is_pub_or_explicit || declared { locations.push((module, name.clone())); } } } // Descend into all modules visible from `from`. - for (ty, vis) in data.scope.types() { - if let ModuleDefId::ModuleId(module) = ty { - if vis.is_visible_from(db, from) { - worklist.push(module); - } + for (module, vis) in data.scope.modules_in_scope() { + if vis.is_visible_from(db, from) { + worklist.push(module); } } } @@ -636,16 +615,14 @@ mod tests { .expect("path does not resolve to a type"); let found_path = find_path_inner( - &db, + FindPathCtx { prefer_no_std: false, db: &db, prefixed: prefix_kind, prefer_prelude }, ItemInNs::Types(resolved), module, - prefix_kind, - false, - prefer_prelude, ); assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?}"); } + #[track_caller] fn check_found_path( ra_fixture: &str, unprefixed: &str, @@ -1015,6 +992,7 @@ pub use crate::foo::bar::S; #[test] fn discount_private_imports() { + cov_mark::check!(discount_private_imports); check_found_path( r#" //- /main.rs @@ -1033,7 +1011,8 @@ $0 } #[test] - fn promote_pub_crate_imports() { + fn explicit_private_imports_crate() { + cov_mark::check!(explicit_private_imports); check_found_path( r#" //- /main.rs @@ -1050,6 +1029,28 @@ $0 ); } + #[test] + fn explicit_private_imports() { + cov_mark::check!(explicit_private_imports); + check_found_path( + r#" +//- /main.rs +pub mod bar { + mod foo; + pub mod baz { pub struct S; } + pub(self) use baz::S; +} + +//- /bar/foo.rs +$0 + "#, + "super::S", + "super::S", + "crate::bar::S", + "super::S", + ); + } + #[test] fn import_cycle() { check_found_path( diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 0a6ba88065d5..168ee4acffbe 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -15,9 +15,11 @@ use stdx::format_to; use syntax::ast; use crate::{ - db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, - ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, - TraitId, UseId, + db::DefDatabase, + per_ns::PerNs, + visibility::{Visibility, VisibilityExplicity}, + AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] @@ -105,7 +107,7 @@ pub struct ItemScope { /// The attribute macro invocations in this scope. attr_macros: FxHashMap, MacroCallId>, /// The macro invocations in this scope. - pub macro_invocations: FxHashMap, MacroCallId>, + macro_invocations: FxHashMap, MacroCallId>, /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes /// paired with the derive macro invocations for the specific attribute. derive_macros: FxHashMap, SmallVec<[DeriveMacroInvocation; 1]>>, @@ -145,8 +147,8 @@ impl ItemScope { .chain(self.values.keys()) .chain(self.macros.keys()) .chain(self.unresolved.iter()) - .unique() .sorted() + .dedup() .map(move |name| (name, self.get(name))) } @@ -157,8 +159,8 @@ impl ItemScope { .filter_map(ImportOrExternCrate::into_import) .chain(self.use_imports_values.keys().copied()) .chain(self.use_imports_macros.keys().copied()) - .unique() .sorted() + .dedup() } pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs { @@ -234,20 +236,37 @@ impl ItemScope { self.impls.iter().copied() } - pub fn values( - &self, - ) -> impl Iterator + ExactSizeIterator + '_ { - self.values.values().copied().map(|(a, b, _)| (a, b)) + pub(crate) fn modules_in_scope(&self) -> impl Iterator + '_ { + self.types.values().copied().filter_map(|(def, vis, _)| match def { + ModuleDefId::ModuleId(module) => Some((module, vis)), + _ => None, + }) } - pub(crate) fn types( - &self, - ) -> impl Iterator + ExactSizeIterator + '_ { - self.types.values().copied().map(|(def, vis, _)| (def, vis)) - } + pub fn unnamed_consts<'a>( + &'a self, + db: &'a dyn DefDatabase, + ) -> impl Iterator + 'a { + // FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those. + // Should be removed once synstructure stops doing that. + let synstructure_hack_consts = self.values.values().filter_map(|(item, _, _)| match item { + &ModuleDefId::ConstId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + if item_tree[loc.id.value] + .name + .as_ref() + .map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_")) + { + Some(id) + } else { + None + } + } + _ => None, + }); - pub fn unnamed_consts(&self) -> impl Iterator + '_ { - self.unnamed_consts.iter().copied() + self.unnamed_consts.iter().copied().chain(synstructure_hack_consts) } /// Iterate over all module scoped macros @@ -274,21 +293,18 @@ impl ItemScope { } /// XXX: this is O(N) rather than O(1), try to not introduce new usages. - pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { + pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility, /*declared*/ bool)> { match item { - ItemInNs::Macros(def) => self - .macros - .iter() - .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), - ItemInNs::Types(def) => self - .types - .iter() - .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + ItemInNs::Macros(def) => self.macros.iter().find_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }), + ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }), - ItemInNs::Values(def) => self - .values - .iter() - .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }), } } @@ -316,6 +332,10 @@ impl ItemScope { }), ) } + + pub(crate) fn macro_invoc(&self, call: AstId) -> Option { + self.macro_invocations.get(&call).copied() + } } impl ItemScope { @@ -624,18 +644,17 @@ impl ItemScope { pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) { self.types .values_mut() - .map(|(def, vis, _)| (def, vis)) - .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis))) - .map(|(_, v)| v) + .map(|(_, vis, _)| vis) + .chain(self.values.values_mut().map(|(_, vis, _)| vis)) .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis)) - .for_each(|vis| *vis = Visibility::Module(this_module, Default::default())); + .for_each(|vis| *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit)); for (mac, vis, import) in self.macros.values_mut() { if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) { continue; } - *vis = Visibility::Module(this_module, Default::default()); + *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit); } } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 20e4e44339e9..82ea5ffeba17 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -69,7 +69,7 @@ use crate::{ generics::{GenericParams, LifetimeParamData, TypeOrConstParamData}, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, - visibility::RawVisibility, + visibility::{RawVisibility, VisibilityExplicity}, BlockId, Lookup, }; @@ -78,8 +78,9 @@ pub struct RawVisibilityId(u32); impl RawVisibilityId { pub const PUB: Self = RawVisibilityId(u32::max_value()); - pub const PRIV: Self = RawVisibilityId(u32::max_value() - 1); - pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 2); + pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::max_value() - 1); + pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::max_value() - 2); + pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 3); } impl fmt::Debug for RawVisibilityId { @@ -87,7 +88,7 @@ impl fmt::Debug for RawVisibilityId { let mut f = f.debug_tuple("RawVisibilityId"); match *self { Self::PUB => f.field(&"pub"), - Self::PRIV => f.field(&"pub(self)"), + Self::PRIV_IMPLICIT | Self::PRIV_EXPLICIT => f.field(&"pub(self)"), Self::PUB_CRATE => f.field(&"pub(crate)"), _ => f.field(&self.0), }; @@ -249,19 +250,30 @@ impl ItemVisibilities { fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { match &vis { RawVisibility::Public => RawVisibilityId::PUB, - RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind { - PathKind::Super(0) => RawVisibilityId::PRIV, - PathKind::Crate => RawVisibilityId::PUB_CRATE, - _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), - }, + RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => { + match (&path.kind, explicitiy) { + (PathKind::Super(0), VisibilityExplicity::Explicit) => { + RawVisibilityId::PRIV_EXPLICIT + } + (PathKind::Super(0), VisibilityExplicity::Implicit) => { + RawVisibilityId::PRIV_IMPLICIT + } + (PathKind::Crate, _) => RawVisibilityId::PUB_CRATE, + _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), + } + } _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), } } } static VIS_PUB: RawVisibility = RawVisibility::Public; -static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))); -static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); +static VIS_PRIV_IMPLICIT: RawVisibility = + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit); +static VIS_PRIV_EXPLICIT: RawVisibility = + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Explicit); +static VIS_PUB_CRATE: RawVisibility = + RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicity::Explicit); #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { @@ -540,7 +552,8 @@ impl Index for ItemTree { type Output = RawVisibility; fn index(&self, index: RawVisibilityId) -> &Self::Output { match index { - RawVisibilityId::PRIV => &VIS_PRIV, + RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT, + RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT, RawVisibilityId::PUB => &VIS_PUB, RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE, _ => &self.data().vis.arena[Idx::from_raw(index.0.into())], diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 6d92fce07272..8693b9a98c9d 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -104,7 +104,9 @@ impl Printer<'_> { fn print_visibility(&mut self, vis: RawVisibilityId) { match &self.tree[vis] { - RawVisibility::Module(path) => w!(self, "pub({}) ", path.display(self.db.upcast())), + RawVisibility::Module(path, _expl) => { + w!(self, "pub({}) ", path.display(self.db.upcast())) + } RawVisibility::Public => w!(self, "pub "), }; } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index a97f57f55313..53644f58efc4 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -79,7 +79,7 @@ use crate::{ nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - visibility::Visibility, + visibility::{Visibility, VisibilityExplicity}, AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; @@ -332,8 +332,10 @@ impl DefMap { // NB: we use `None` as block here, which would be wrong for implicit // modules declared by blocks with items. At the moment, we don't use // this visibility for anything outside IDE, so that's probably OK. - let visibility = - Visibility::Module(ModuleId { krate, local_id, block: None }, Default::default()); + let visibility = Visibility::Module( + ModuleId { krate, local_id, block: None }, + VisibilityExplicity::Implicit, + ); let module_data = ModuleData::new( ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, visibility, diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 700264839b94..389dabdbc867 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -21,7 +21,7 @@ use crate::{ nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, - visibility::{RawVisibility, Visibility, VisibilityExplicity}, + visibility::{RawVisibility, Visibility}, AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, }; @@ -87,20 +87,15 @@ impl DefMap { within_impl: bool, ) -> Option { let mut vis = match visibility { - RawVisibility::Module(path) => { + RawVisibility::Module(path, explicity) => { let (result, remaining) = self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None); if remaining.is_some() { return None; } let types = result.take_types()?; - let mv = if path.is_pub_crate() { - VisibilityExplicity::Explicit - } else { - VisibilityExplicity::Implicit - }; match types { - ModuleDefId::ModuleId(m) => Visibility::Module(m, mv), + ModuleDefId::ModuleId(m) => Visibility::Module(m, *explicity), // error: visibility needs to refer to module _ => { return None; diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 301391516d64..1d850f721c1f 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -242,7 +242,7 @@ impl Resolver { let within_impl = self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some(); match visibility { - RawVisibility::Module(_) => { + RawVisibility::Module(_, _) => { let (item_map, module) = self.item_scope(); item_map.resolve_visibility(db, module, visibility, within_impl) } diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 163484e241b3..cd8023f5d7d7 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -20,14 +20,14 @@ use crate::{ pub enum RawVisibility { /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// equivalent to `pub(self)`. - Module(ModPath), + Module(ModPath, VisibilityExplicity), /// `pub`. Public, } impl RawVisibility { pub(crate) const fn private() -> RawVisibility { - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit) } pub(crate) fn from_ast( @@ -41,18 +41,9 @@ impl RawVisibility { db: &dyn DefDatabase, node: Option, span_map: SpanMapRef<'_>, - ) -> RawVisibility { - Self::from_ast_with_span_map_and_default(db, node, RawVisibility::private(), span_map) - } - - pub(crate) fn from_ast_with_span_map_and_default( - db: &dyn DefDatabase, - node: Option, - default: RawVisibility, - span_map: SpanMapRef<'_>, ) -> RawVisibility { let node = match node { - None => return default, + None => return RawVisibility::private(), Some(node) => node, }; match node.kind() { @@ -62,19 +53,19 @@ impl RawVisibility { None => return RawVisibility::private(), Some(path) => path, }; - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::PubCrate => { let path = ModPath::from_kind(PathKind::Crate); - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::PubSuper => { let path = ModPath::from_kind(PathKind::Super(1)); - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::PubSelf => { let path = ModPath::from_kind(PathKind::Super(0)); - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::Pub => RawVisibility::Public, } @@ -214,10 +205,9 @@ impl Visibility { } /// Whether the item was imported through `pub(crate) use` or just `use`. -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum VisibilityExplicity { Explicit, - #[default] Implicit, } diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 4618dcec70b4..30b8c189f52d 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -96,10 +96,6 @@ impl ModPath { self.kind == PathKind::Super(0) && self.segments.is_empty() } - pub fn is_pub_crate(&self) -> bool { - self.kind == PathKind::Crate && self.segments.is_empty() - } - #[allow(non_snake_case)] pub fn is_Self(&self) -> bool { self.kind == PathKind::Plain diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 06df30582aa7..03ed8d36a1dd 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -8,10 +8,9 @@ use base_db::{CrateId, Edition}; use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause}; use hir_def::{ data::{adt::StructFlags, ImplData}, - item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, - ModuleDefId, ModuleId, TraitId, + ModuleId, TraitId, }; use hir_expand::name::Name; use rustc_hash::{FxHashMap, FxHashSet}; @@ -212,7 +211,7 @@ impl TraitImpls { // To better support custom derives, collect impls in all unnamed const items. // const _: () = { ... }; - for konst in collect_unnamed_consts(db, &module_data.scope) { + for konst in module_data.scope.unnamed_consts(db.upcast()) { let body = db.body(konst.into()); for (_, block_def_map) in body.blocks(db.upcast()) { Self::collect_def_map(db, map, &block_def_map); @@ -330,7 +329,7 @@ impl InherentImpls { // To better support custom derives, collect impls in all unnamed const items. // const _: () = { ... }; - for konst in collect_unnamed_consts(db, &module_data.scope) { + for konst in module_data.scope.unnamed_consts(db.upcast()) { let body = db.body(konst.into()); for (_, block_def_map) in body.blocks(db.upcast()) { self.collect_def_map(db, &block_def_map); @@ -376,34 +375,6 @@ pub(crate) fn incoherent_inherent_impl_crates( res } -fn collect_unnamed_consts<'a>( - db: &'a dyn HirDatabase, - scope: &'a ItemScope, -) -> impl Iterator + 'a { - let unnamed_consts = scope.unnamed_consts(); - - // FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those. - // Should be removed once synstructure stops doing that. - let synstructure_hack_consts = scope.values().filter_map(|(item, _)| match item { - ModuleDefId::ConstId(id) => { - let loc = id.lookup(db.upcast()); - let item_tree = loc.id.item_tree(db.upcast()); - if item_tree[loc.id.value] - .name - .as_ref() - .map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_")) - { - Some(id) - } else { - None - } - } - _ => None, - }); - - unnamed_consts.chain(synstructure_hack_consts) -} - pub fn def_crates( db: &dyn HirDatabase, ty: &Ty, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0266915c39b6..3180a2b713a8 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -754,7 +754,7 @@ impl Module { scope .declarations() .map(ModuleDef::from) - .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id)))) + .chain(scope.unnamed_consts(db.upcast()).map(|id| ModuleDef::Const(Const::from(id)))) .collect() } diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 9ae5bb26932d..e1101dd8236e 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -196,7 +196,7 @@ impl<'a> SymbolCollector<'a> { }); } - for const_id in scope.unnamed_consts() { + for const_id in scope.unnamed_consts(self.db.upcast()) { self.collect_from_body(const_id); } From 215ede84979971e0d4dbae41c7be4c3f46d2728a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 11 Jan 2024 12:41:47 +0100 Subject: [PATCH 101/297] fix: Fix nested includes resolving from the wrong base file --- crates/hir-def/src/nameres/tests/macros.rs | 48 ++++++++++++++++++++++ crates/hir-expand/src/builtin_fn_macro.rs | 4 +- crates/hir-expand/src/lib.rs | 4 ++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs index 48fe43450a71..0f6e64016f18 100644 --- a/crates/hir-def/src/nameres/tests/macros.rs +++ b/crates/hir-def/src/nameres/tests/macros.rs @@ -1264,6 +1264,54 @@ struct A; ); } +#[test] +fn nested_include() { + check( + r#" +//- minicore: include +//- /lib.rs +include!("out_dir/includes.rs"); + +//- /out_dir/includes.rs +pub mod company_name { + pub mod network { + pub mod v1 { + include!("company_name.network.v1.rs"); + } + } +} +//- /out_dir/company_name.network.v1.rs +pub struct IpAddress { + pub ip_type: &'static str, +} +/// Nested message and enum types in `IpAddress`. +pub mod ip_address { + pub enum IpType { + IpV4(u32), + } +} + +"#, + expect![[r#" + crate + company_name: t + + crate::company_name + network: t + + crate::company_name::network + v1: t + + crate::company_name::network::v1 + IpAddress: t + ip_address: t + + crate::company_name::network::v1::ip_address + IpType: t + "#]], + ); +} + #[test] fn macro_use_imports_all_macro_types() { let db = TestDB::with_files( diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs index 65a55f8b5b89..c892f462d2c7 100644 --- a/crates/hir-expand/src/builtin_fn_macro.rs +++ b/crates/hir-expand/src/builtin_fn_macro.rs @@ -15,7 +15,7 @@ use crate::{ quote, quote::dollar_crate, tt::{self, DelimSpan}, - ExpandError, ExpandResult, HirFileIdExt, MacroCallId, + ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroFileIdExt, }; macro_rules! register_builtin { @@ -609,7 +609,7 @@ fn relative_file( path_str: &str, allow_recursion: bool, ) -> Result { - let call_site = call_id.as_file().original_file(db); + let call_site = call_id.as_macro_file().parent(db).original_file_respecting_includes(db); let path = AnchoredPath { anchor: call_site, path: path_str }; let res = db .resolve_path(path) diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 6a122e0859cc..ae7d17e49a90 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -318,6 +318,7 @@ pub trait MacroFileIdExt { fn expansion_level(self, db: &dyn ExpandDatabase) -> u32; /// If this is a macro call, returns the syntax node of the call. fn call_node(self, db: &dyn ExpandDatabase) -> InFile; + fn parent(self, db: &dyn ExpandDatabase) -> HirFileId; fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo; @@ -353,6 +354,9 @@ impl MacroFileIdExt for MacroFileId { }; } } + fn parent(self, db: &dyn ExpandDatabase) -> HirFileId { + self.macro_call_id.lookup(db).kind.file_id() + } /// Return expansion information if it is a macro-expansion file fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo { From adce3fd99ba2ad3f3b03136473c29256513213fb Mon Sep 17 00:00:00 2001 From: Nathan Reller Date: Thu, 11 Jan 2024 15:26:16 +0000 Subject: [PATCH 102/297] Enable Static Builds for FreeBSD Enable crt-static for FreeBSD to enable statically compiled binaries. --- compiler/rustc_target/src/spec/base/freebsd.rs | 1 + library/unwind/src/lib.rs | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/base/freebsd.rs b/compiler/rustc_target/src/spec/base/freebsd.rs index 8c141aaaec34..80b3da8a752d 100644 --- a/compiler/rustc_target/src/spec/base/freebsd.rs +++ b/compiler/rustc_target/src/spec/base/freebsd.rs @@ -6,6 +6,7 @@ pub fn opts() -> TargetOptions { dynamic_linking: true, families: cvs!["unix"], has_rpath: true, + crt_static_respected: true, position_independent_executables: true, relro_level: RelroLevel::Full, abi_return_struct_as_int: true, diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index eeee98f754e0..f5988a4df136 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -121,10 +121,16 @@ extern "C" {} #[link(name = "unwind", kind = "static", modifiers = "-bundle")] extern "C" {} -#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] +#[cfg(target_os = "netbsd")] #[link(name = "gcc_s")] extern "C" {} +#[cfg(target_os = "freebsd")] +#[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] +#[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] +#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] +extern "C" {} + #[cfg(all(target_os = "openbsd", target_arch = "sparc64"))] #[link(name = "gcc")] extern "C" {} From 9018d2c455df78d3f2900b4ced3ed63962e4f11e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 7 Dec 2023 09:53:08 +1100 Subject: [PATCH 103/297] Detect `NulInCStr` error earlier. By making it an `EscapeError` instead of a `LitError`. This makes it like the other errors produced when checking string literals contents, e.g. for invalid escape sequences or bare CR chars. NOTE: this means these errors are issued earlier, before expansion, which changes behaviour. It will be possible to move the check back to the later point if desired. If that happens, it's likely that all the string literal contents checks will be delayed together. One nice thing about this: the old approach had some code in `report_lit_error` to calculate the span of the nul char from a range. This code used a hardwired `+2` to account for the `c"` at the start of a C string literal, but this should have changed to a `+3` for raw C string literals to account for the `cr"`, which meant that the caret in `cr"` nul error messages was one short of where it should have been. The new approach doesn't need any of this and avoids the off-by-one error. --- compiler/rustc_ast/src/util/literal.rs | 12 ++---------- compiler/rustc_lexer/src/unescape.rs | 17 +++++++++++++++-- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 5 +++++ .../src/lexer/unescape_error_reporting.rs | 3 +++ compiler/rustc_session/messages.ftl | 2 -- compiler/rustc_session/src/errors.rs | 15 +-------------- .../crates/parser/src/lexed_str.rs | 1 + .../crates/syntax/src/validation.rs | 3 +++ .../rfcs/rfc-3348-c-string-literals/no-nuls.rs | Bin 738 -> 1906 bytes .../rfc-3348-c-string-literals/no-nuls.stderr | Bin 674 -> 2028 bytes 11 files changed, 32 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 92b9adf1db75..fbae49645881 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -8,7 +8,6 @@ use rustc_lexer::unescape::{ }; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::ops::Range; use std::{ascii, fmt, str}; // Escapes a string, represented as a symbol. Reuses the original symbol, @@ -39,7 +38,6 @@ pub enum LitError { InvalidFloatSuffix, NonDecimalFloat(u32), IntTooLarge(u32), - NulInCStr(Range), } impl LitKind { @@ -156,10 +154,7 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_c_string(s, Mode::CStr, &mut |span, c| match c { - Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { - error = Err(LitError::NulInCStr(span)); - } + unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { Ok(CStrUnit::Byte(b)) => buf.push(b), Ok(CStrUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) @@ -179,10 +174,7 @@ impl LitKind { // can convert the symbol directly to a `Lrc` on success. let s = symbol.as_str(); let mut error = Ok(()); - unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c { - Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { - error = Err(LitError::NulInCStr(span)); - } + unescape_c_string(s, Mode::RawCStr, &mut |_, c| match c { Ok(_) => {} Err(err) => { if err.is_fatal() { diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index abec12f52a6e..0a632c4d12ad 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -59,6 +59,9 @@ pub enum EscapeError { /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. NonAsciiCharInByte, + // `\0` in a C string literal. + NulInCStr, + /// After a line ending with '\', the next line contains whitespace /// characters that are not skipped. UnskippedWhitespaceWarning, @@ -122,10 +125,20 @@ where { match mode { CStr => { - unescape_non_raw_common(src, mode, callback); + unescape_non_raw_common(src, mode, &mut |r, mut result| { + if let Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result) + }); } RawCStr => { - check_raw_common(src, mode, &mut |r, result| callback(r, result.map(CStrUnit::Char))); + check_raw_common(src, mode, &mut |r, mut result| { + if let Ok('\0') = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result.map(CStrUnit::Char)) + }); } Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(), } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index c11a6fab7e5d..3c2fb53b2940 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -613,6 +613,8 @@ parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||` +parse_nul_in_c_str = null characters in C string literals are not supported + parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings parse_out_of_range_hex_escape = out of range hex escape diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0de252707bd3..ef8e9d0a2483 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2144,6 +2144,11 @@ pub enum UnescapeError { #[subdiagnostic] suggestion: MoreThanOneCharSugg, }, + #[diag(parse_nul_in_c_str)] + NulInCStr { + #[primary_span] + span: Span, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index fbc77f287808..3238f8e23bb0 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -262,6 +262,9 @@ pub(crate) fn emit_unescape_error( EscapeError::LoneSlash => { dcx.emit_err(UnescapeError::LoneSlash(err_span)); } + EscapeError::NulInCStr => { + dcx.emit_err(UnescapeError::NulInCStr { span: err_span }); + } EscapeError::UnskippedWhitespaceWarning => { let (c, char_span) = last_char(); dcx.emit_warn(UnescapeError::UnskippedWhitespace { diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index f2e646c70f57..4f824f9f62e2 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -72,8 +72,6 @@ session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be u session_not_supported = not supported -session_nul_in_c_str = null characters in C string literals are not supported - session_octal_float_literal_not_supported = octal float literal is not supported session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index b672e760feb3..b0a397de3eb1 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -7,7 +7,7 @@ use rustc_errors::{ error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, }; use rustc_macros::Diagnostic; -use rustc_span::{BytePos, Span, Symbol}; +use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; pub struct FeatureGateError { @@ -327,13 +327,6 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } -#[derive(Diagnostic)] -#[diag(session_nul_in_c_str)] -pub(crate) struct NulInCStr { - #[primary_span] - pub span: Span, -} - pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { @@ -413,12 +406,6 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: }; dcx.emit_err(IntLiteralTooLarge { span, limit }); } - LitError::NulInCStr(range) => { - let lo = BytePos(span.lo().0 + range.start as u32 + 2); - let hi = BytePos(span.lo().0 + range.end as u32 + 2); - let span = span.with_lo(lo).with_hi(hi); - dcx.emit_err(NulInCStr { span }); - } } } diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index b9e7566fdf9b..3753a1beb7a8 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -371,6 +371,7 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { "non-ASCII character in byte string literal" } EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", + EscapeError::NulInCStr => "null character in C string literal", EscapeError::UnskippedWhitespaceWarning => "", EscapeError::MultipleSkippedLinesWarning => "", } diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index eabbda2c3983..0504f67c9dc7 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -106,6 +106,9 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, EE::NonAsciiCharInByte => { "Byte literals must not contain non-ASCII characters" } + EE::NulInCStr => { + "C strings literals must not contain null characters" + } EE::UnskippedWhitespaceWarning => "Whitespace after this escape is not skipped", EE::MultipleSkippedLinesWarning => "Multiple lines are skipped by this escape", diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index e20ca50b88f905d5a0332a71f64d02c061f21711..2f9ca09f3a5defe1f650efb73f2e7b98dbeef929 100644 GIT binary patch literal 1906 zcmdPbS4d6CEXmBzvr;fJFf!!g($`lA$w*bmE6vGKNX|$sQb^87P0m(G%P&%JRwynh z%FIhw$jK~8ElSKORwz#_R>&{POwY_q%*m-#$jmLsNzF~oD@jdJNK7k9EdrUAT2YXg zSDcxjr=w7wk(r#KkeiyASE5jok*biESyWu2kd|4N3N^V{Au~^*BqOs}AuTf}RiUIP zGd(@EC^bbPwWuh+s8|PNUSeJfSaVToZenI0$T=mcc?v0+DGGV{C3*@@r6992ixo19 z6;d+O(o&03LAK>9BJqpgbrgzAlQR?& ziy;9~3=WCRyt2fc%oK&x;^f4F)MA*kk`jwj6`X^>;a04t5S$OT5Ntj;sB-hmKz>Oq z%E?SE(gTMxL^3%sPa!E)0W1$PEGaQLTcIQ$5{L@$5L8GkQAkwCNi0b%QbpkEGx{i0x}BWmXdshoYV@i+RWTk zxP1ypmSyH)Sch4C8HpiBoghs2BnDq>(x0cAe08KjmPwOjzV CJ8ZH5 literal 738 zcmdPbS4d6CEXmBzvr;fJFf!!gO3PEoP0Y;G&{U}AQczG(NLGq5P_hOy_4VuG6kLOX z{DTzoN^^1)k~0#E5|c|(i;5L8^AwyFic5+z^U@V^GD}j65_5{Vz?zbkVoIwG3~DJe zgMl*bF%<@sd7?;(To=@Gapfi^7v;wnmFA=tD=MVs7L-&%!&XB@L#3p|s-#3yOH;wt zPNBNinyZ$JOJ83hBqLQJIW1iwIX|zsG&i+ap(G;}9;g#a8@WTDay=CSIEgMNi9muDON}#|q zFHtBiEhxw@DoIV@Qc%#%h$~-%_-I^Dz-8-u`=gUP*AAh^6^oqQ2>Et zr5FPxYp@`QtDv9|7stg#6U$ApSzcOgU{H(hfVeoCIl>H!BN))^r;-27u~;2bVSo|* zH1oTKl?6DWkz&6{3C;5gG>UyA3v9l}@H=gS-pCT0<#bMZ#s*j%ffo8S3VdTjELPJq z=@}ahVA3--w=y(AOZcg|1tpb=8sO4T6Q%g0aVcnQfzL6JB#Fa8v?~>jE%7*tK?%Ei zXp>b<4DdJwoMf@PhGsQ}iJ_IDDUQ?wDm}3}2dNZIOv*1R0oB$irKt)f`3i=n3I#=} QWtsV<#R}kRwwQ|x07EBJS^xk5 delta 77 zcmaFEzle202&2j5i%ivw=94cniA;Q6z-Tb}B9rjsY{qm(W026~=Zra%!x@Dqr!fgm gu43exe1cs-*i@mQD77pzzqD8(wWuh+sF;fj03I|NCIA2c From f37a919e9668dbbdc999bb727eafc2bd46e505a6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 16:16:17 +0000 Subject: [PATCH 104/297] Remove redundant Code from FulfillmentErrorCode variants --- .../rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 4 +- .../src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_infer/src/traits/mod.rs | 13 +++--- .../src/traits/structural_impls.rs | 15 ++++--- .../src/solve/fulfill.rs | 16 +++---- .../error_reporting/type_err_ctxt_ext.rs | 18 ++++---- .../src/traits/fulfill.rs | 43 +++++++++---------- compiler/rustc_traits/src/codegen.rs | 2 +- .../src/normalize_projection_ty.rs | 2 +- 11 files changed, 59 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index b31325485db9..8cad36611783 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1213,7 +1213,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MaybeIncorrect, ); for error in errors { - if let FulfillmentErrorCode::CodeSelectionError( + if let FulfillmentErrorCode::SelectionError( SelectionError::Unimplemented, ) = error.code && let ty::PredicateKind::Clause(ty::ClauseKind::Trait( diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3b3d440df97b..9fc0a973054d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1288,7 +1288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } // The type doesn't implement Clone because of unmet obligations. for error in errors { - if let traits::FulfillmentErrorCode::CodeSelectionError( + if let traits::FulfillmentErrorCode::SelectionError( traits::SelectionError::Unimplemented, ) = error.code && let ty::PredicateKind::Clause(ty::ClauseKind::Trait( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 76360239c454..d7459bf4f687 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Finally, for ambiguity-related errors, we actually want to look // for a parameter that is the source of the inference type left // over in this predicate. - if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code { + if let traits::FulfillmentErrorCode::Ambiguity { .. } = error.code { fallback_param_to_point_at = None; self_param_to_point_at = None; param_to_point_at = @@ -361,7 +361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: &traits::FulfillmentError<'tcx>, span: Span, ) -> bool { - if let traits::FulfillmentErrorCode::CodeSelectionError( + if let traits::FulfillmentErrorCode::SelectionError( traits::SelectionError::OutputTypeParameterMismatch( box traits::SelectionOutputTypeParameterMismatch { expected_trait_ref, .. }, ), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b542132d71ce..4fabe0ff8180 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1648,7 +1648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } for error in errors { - if let traits::FulfillmentErrorCode::CodeSelectionError( + if let traits::FulfillmentErrorCode::SelectionError( traits::SelectionError::Unimplemented, ) = error.code && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index b9be178916cf..fdae093aac8b 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; -pub use self::FulfillmentErrorCode::*; pub use self::ImplSource::*; pub use self::SelectionError::*; @@ -129,12 +128,12 @@ pub struct FulfillmentError<'tcx> { #[derive(Clone)] pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented. - CodeCycle(Vec>), - CodeSelectionError(SelectionError<'tcx>), - CodeProjectionError(MismatchedProjectionTypes<'tcx>), - CodeSubtypeError(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate - CodeConstEquateError(ExpectedFound>, TypeError<'tcx>), - CodeAmbiguity { + Cycle(Vec>), + SelectionError(SelectionError<'tcx>), + ProjectionError(MismatchedProjectionTypes<'tcx>), + SubtypeError(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate + ConstEquateError(ExpectedFound>, TypeError<'tcx>), + Ambiguity { /// Overflow reported from the new solver `-Znext-solver`, which will /// be reported as an regular error as opposed to a fatal error. overflow: bool, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 51c06c8970b1..3b4050fcd27e 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -37,18 +37,19 @@ impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> { impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use traits::FulfillmentErrorCode::*; match *self { - super::CodeSelectionError(ref e) => write!(f, "{e:?}"), - super::CodeProjectionError(ref e) => write!(f, "{e:?}"), - super::CodeSubtypeError(ref a, ref b) => { + SelectionError(ref e) => write!(f, "{e:?}"), + ProjectionError(ref e) => write!(f, "{e:?}"), + SubtypeError(ref a, ref b) => { write!(f, "CodeSubtypeError({a:?}, {b:?})") } - super::CodeConstEquateError(ref a, ref b) => { + ConstEquateError(ref a, ref b) => { write!(f, "CodeConstEquateError({a:?}, {b:?})") } - super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"), - super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"), - super::CodeCycle(ref cycle) => write!(f, "Cycle({cycle:?})"), + Ambiguity { overflow: false } => write!(f, "Ambiguity"), + Ambiguity { overflow: true } => write!(f, "Overflow"), + Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"), } } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 2139210b8736..23d08d380c29 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -61,10 +61,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .0 { Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => { - FulfillmentErrorCode::CodeAmbiguity { overflow: false } + FulfillmentErrorCode::Ambiguity { overflow: false } } Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => { - FulfillmentErrorCode::CodeAmbiguity { overflow: true } + FulfillmentErrorCode::Ambiguity { overflow: true } } Ok((_, Certainty::Yes, _)) => { bug!("did not expect successful goal when collecting ambiguity errors") @@ -103,18 +103,18 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { obligation: obligation.clone(), code: match goal.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { - FulfillmentErrorCode::CodeProjectionError( + FulfillmentErrorCode::ProjectionError( // FIXME: This could be a `Sorts` if the term is a type MismatchedProjectionTypes { err: TypeError::Mismatch }, ) } ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::CodeProjectionError( + FulfillmentErrorCode::ProjectionError( MismatchedProjectionTypes { err: TypeError::Mismatch }, ) } ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::CodeProjectionError( + FulfillmentErrorCode::ProjectionError( MismatchedProjectionTypes { err: TypeError::Mismatch }, ) } @@ -123,7 +123,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(true, a, b); - FulfillmentErrorCode::CodeSubtypeError( + FulfillmentErrorCode::SubtypeError( expected_found, TypeError::Sorts(expected_found), ) @@ -133,7 +133,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(false, a, b); - FulfillmentErrorCode::CodeSubtypeError( + FulfillmentErrorCode::SubtypeError( expected_found, TypeError::Sorts(expected_found), ) @@ -141,7 +141,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ty::PredicateKind::Clause(_) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::Ambiguous => { - FulfillmentErrorCode::CodeSelectionError( + FulfillmentErrorCode::SelectionError( SelectionError::Unimplemented, ) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 47a700805fa5..659ac74ee8dc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -785,14 +785,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Subtype(predicate) => { // Errors for Subtype predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, + // `FulfillmentErrorCode::SubtypeError`, // not selection error. span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) } ty::PredicateKind::Coerce(predicate) => { // Errors for Coerce predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, + // `FulfillmentErrorCode::SubtypeError`, // not selection error. span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate) } @@ -1575,23 +1575,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } match error.code { - FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { + FulfillmentErrorCode::SelectionError(ref selection_error) => { self.report_selection_error( error.obligation.clone(), &error.root_obligation, selection_error, ); } - FulfillmentErrorCode::CodeProjectionError(ref e) => { + FulfillmentErrorCode::ProjectionError(ref e) => { self.report_projection_error(&error.obligation, e); } - FulfillmentErrorCode::CodeAmbiguity { overflow: false } => { + FulfillmentErrorCode::Ambiguity { overflow: false } => { self.maybe_report_ambiguity(&error.obligation); } - FulfillmentErrorCode::CodeAmbiguity { overflow: true } => { + FulfillmentErrorCode::Ambiguity { overflow: true } => { self.report_overflow_no_abort(error.obligation.clone()); } - FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { + FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => { self.report_mismatched_types( &error.obligation.cause, expected_found.expected, @@ -1600,7 +1600,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) .emit(); } - FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => { + FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => { let mut diag = self.report_mismatched_consts( &error.obligation.cause, expected_found.expected, @@ -1625,7 +1625,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } diag.emit(); } - FulfillmentErrorCode::CodeCycle(ref cycle) => { + FulfillmentErrorCode::Cycle(ref cycle) => { self.report_overflow_obligation_cycle(cycle); } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 045d7e444b6e..f27fe80f0289 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -18,9 +18,6 @@ use super::const_evaluatable; use super::project::{self, ProjectAndUnifyResult}; use super::select::SelectionContext; use super::wf; -use super::CodeAmbiguity; -use super::CodeProjectionError; -use super::CodeSelectionError; use super::EvaluationResult; use super::PredicateObligation; use super::Unimplemented; @@ -135,7 +132,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { _infcx: &InferCtxt<'tcx>, ) -> Vec> { self.predicates - .to_errors(CodeAmbiguity { overflow: false }) + .to_errors(FulfillmentErrorCode::Ambiguity { overflow: false }) .into_iter() .map(to_fulfillment_error) .collect() @@ -409,7 +406,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::ObjectSafe(trait_def_id) => { if !self.selcx.tcx().check_is_object_safe(trait_def_id) { - ProcessResult::Error(CodeSelectionError(Unimplemented)) + ProcessResult::Error(FulfillmentErrorCode::SelectionError(Unimplemented)) } else { ProcessResult::Changed(vec![]) } @@ -480,7 +477,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(Err(err)) => { let expected_found = ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b); - ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( + ProcessResult::Error(FulfillmentErrorCode::SubtypeError( expected_found, err, )) @@ -503,7 +500,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)), Ok(Err(err)) => { let expected_found = ExpectedFound::new(false, coerce.a, coerce.b); - ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( + ProcessResult::Error(FulfillmentErrorCode::SubtypeError( expected_found, err, )) @@ -529,7 +526,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Err( e @ NotConstEvaluatable::MentionsParam | e @ NotConstEvaluatable::Error(_), - ) => ProcessResult::Error(CodeSelectionError( + ) => ProcessResult::Error(FulfillmentErrorCode::SelectionError( SelectionError::NotConstEvaluatable(e), )), } @@ -618,20 +615,22 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(inf_ok) => { ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) } - Err(err) => ProcessResult::Error( - FulfillmentErrorCode::CodeConstEquateError( + Err(err) => { + ProcessResult::Error(FulfillmentErrorCode::ConstEquateError( ExpectedFound::new(true, c1, c2), err, - ), - ), + )) + } } } (Err(ErrorHandled::Reported(reported, _)), _) - | (_, Err(ErrorHandled::Reported(reported, _))) => ProcessResult::Error( - CodeSelectionError(SelectionError::NotConstEvaluatable( - NotConstEvaluatable::Error(reported.into()), - )), - ), + | (_, Err(ErrorHandled::Reported(reported, _))) => { + ProcessResult::Error(FulfillmentErrorCode::SelectionError( + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error( + reported.into(), + )), + )) + } (Err(ErrorHandled::TooGeneric(_)), _) | (_, Err(ErrorHandled::TooGeneric(_))) => { if c1.has_non_region_infer() || c2.has_non_region_infer() { @@ -639,7 +638,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } else { // Two different constants using generic parameters ~> error. let expected_found = ExpectedFound::new(true, c1, c2); - ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError( + ProcessResult::Error(FulfillmentErrorCode::ConstEquateError( expected_found, TypeError::ConstMismatch(expected_found), )) @@ -654,7 +653,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty, ) { Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), - Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( + Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError( SelectionError::Unimplemented, )), } @@ -677,7 +676,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(()) } else { let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); - Err(FulfillmentErrorCode::CodeCycle(cycle)) + Err(FulfillmentErrorCode::Cycle(cycle)) } } } @@ -732,7 +731,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { Err(selection_err) => { debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth); - ProcessResult::Error(CodeSelectionError(selection_err)) + ProcessResult::Error(FulfillmentErrorCode::SelectionError(selection_err)) } } } @@ -784,7 +783,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { project_obligation.with(tcx, project_obligation.predicate), ])), ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { - ProcessResult::Error(CodeProjectionError(e)) + ProcessResult::Error(FulfillmentErrorCode::ProjectionError(e)) } } } diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 2cd1c3b502ae..f3fae63ecc7b 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -63,7 +63,7 @@ pub fn codegen_select_candidate<'tcx>( // Cycle errors are the only post-monomorphization errors possible; emit them now so // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. for err in errors { - if let FulfillmentErrorCode::CodeCycle(cycle) = err.code { + if let FulfillmentErrorCode::Cycle(cycle) = err.code { infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); } } diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index b8c71bc96f88..21a016e29d69 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -54,7 +54,7 @@ fn normalize_projection_ty<'tcx>( // that impl vars are constrained by the signature, for example). if !tcx.sess.opts.actually_rustdoc { for error in &errors { - if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code { + if let FulfillmentErrorCode::Cycle(cycle) = &error.code { ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle); } } From fbdc116e6ea4051d25847cdd2d12919f8ca8aebc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 16:20:12 +0000 Subject: [PATCH 105/297] OutputTypeParameterMismatch -> SignatureMismatch --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 7 ++--- compiler/rustc_middle/src/traits/mod.rs | 4 +-- .../error_reporting/type_err_ctxt_ext.rs | 27 +++++++++---------- .../src/traits/select/confirmation.rs | 10 +++---- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index d7459bf4f687..1ad79cb78c4b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -362,9 +362,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, ) -> bool { if let traits::FulfillmentErrorCode::SelectionError( - traits::SelectionError::OutputTypeParameterMismatch( - box traits::SelectionOutputTypeParameterMismatch { expected_trait_ref, .. }, - ), + traits::SelectionError::SignatureMismatch(box traits::SignatureMismatchData { + expected_trait_ref, + .. + }), ) = error.code && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) = expected_trait_ref.skip_binder().self_ty().kind() diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index af601a0d702e..fb74d6610f25 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -604,7 +604,7 @@ pub enum SelectionError<'tcx> { /// After a closure impl has selected, its "outputs" were evaluated /// (which for closures includes the "input" type params) and they /// didn't resolve. See `confirm_poly_trait_refs` for more. - OutputTypeParameterMismatch(Box>), + SignatureMismatch(Box>), /// The trait pointed by `DefId` is not object safe. TraitNotObjectSafe(DefId), /// A given constant couldn't be evaluated. @@ -621,7 +621,7 @@ pub enum SelectionError<'tcx> { } #[derive(Clone, Debug, TypeVisitable)] -pub struct SelectionOutputTypeParameterMismatch<'tcx> { +pub struct SignatureMismatchData<'tcx> { pub found_trait_ref: ty::PolyTraitRef<'tcx>, pub expected_trait_ref: ty::PolyTraitRef<'tcx>, pub terr: ty::error::TypeError<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 659ac74ee8dc..64ce1746c16a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -14,8 +14,8 @@ use crate::traits::specialize::to_pretty_impl_header; use crate::traits::NormalizeExt; use crate::traits::{ elaborate, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, - ObligationCause, ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionError, TraitNotObjectSafe, + ObligationCause, ObligationCauseCode, ObligationCtxt, Overflow, PredicateObligation, + SelectionError, SignatureMismatch, TraitNotObjectSafe, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ @@ -30,7 +30,7 @@ use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; -use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch}; +use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData}; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; @@ -891,22 +891,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + SignatureMismatch(box SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: terr @ TypeError::CyclicTy(_), - }) => self.report_type_parameter_mismatch_cyclic_type_error( + }) => self.report_cyclic_signature_error( &obligation, found_trait_ref, expected_trait_ref, terr, ), - OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + SignatureMismatch(box SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: _, }) => { - match self.report_type_parameter_mismatch_error( + match self.report_signature_mismatch_error( &obligation, span, found_trait_ref, @@ -1495,7 +1495,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { kind: ty::ClosureKind, ) -> DiagnosticBuilder<'tcx>; - fn report_type_parameter_mismatch_cyclic_type_error( + fn report_cyclic_signature_error( &self, obligation: &PredicateObligation<'tcx>, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, @@ -1509,7 +1509,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { def_id: DefId, ) -> DiagnosticBuilder<'tcx>; - fn report_type_parameter_mismatch_error( + fn report_signature_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, @@ -3369,7 +3369,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.dcx().create_err(err) } - fn report_type_parameter_mismatch_cyclic_type_error( + fn report_cyclic_signature_error( &self, obligation: &PredicateObligation<'tcx>, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, @@ -3430,7 +3430,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err } - fn report_type_parameter_mismatch_error( + fn report_signature_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, @@ -3449,10 +3449,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; let found_did = match *found_trait_ty.kind() { - ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => { - Some(did) - } - ty::Adt(def, _) => Some(def.did()), + ty::Closure(did, _) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => Some(did), _ => None, }; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e20bb06d7770..74f388e53a3c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; -use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch}; +use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate, TraitPredicate, Ty, TyCtxt, TypeVisitableExt, @@ -26,9 +26,9 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, - OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection, - SelectionError, TraitNotObjectSafe, Unimplemented, + ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation, + PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe, + Unimplemented, }; use super::BuiltinImplConditions; @@ -922,7 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations }) .map_err(|terr| { - OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch { + SignatureMismatch(Box::new(SignatureMismatchData { expected_trait_ref: obligation_trait_ref, found_trait_ref: expected_trait_ref, terr, From 50e1580cd0ba57e183ff766781a2408f8ba983c7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 17:50:43 +0000 Subject: [PATCH 106/297] Inline check_closure --- compiler/rustc_hir_typeck/src/closure.rs | 33 ++++++------------------ 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 7edb5912dd53..b7ca070a4787 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -49,7 +49,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_span: Span, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - trace!("decl = {:#?}", closure.fn_decl); + let tcx = self.tcx; + let body = tcx.hir().body(closure.body); + let expr_def_id = closure.def_id; // It's always helpful for inference if we know the kind of // closure sooner rather than later, so first examine the expected @@ -61,24 +63,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => (None, None), }; - self.check_closure(closure, expr_span, expected_kind, expected_sig) - } - - #[instrument(skip(self, closure), level = "debug", ret)] - fn check_closure( - &self, - closure: &hir::Closure<'tcx>, - expr_span: Span, - opt_kind: Option, - expected_sig: Option>, - ) -> Ty<'tcx> { - let tcx = self.tcx; - let body = tcx.hir().body(closure.body); - - trace!("decl = {:#?}", closure.fn_decl); - let expr_def_id = closure.def_id; - debug!(?expr_def_id); - let ClosureSignatures { bound_sig, liberated_sig } = self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig); @@ -139,9 +123,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id); check_fn( - &mut fcx, + &mut FnCtxt::new(self, self.param_env, closure.def_id), liberated_sig, coroutine_types, closure.fn_decl, @@ -174,9 +157,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }); - debug!(?sig, ?opt_kind); + debug!(?sig, ?expected_kind); - let closure_kind_ty = match opt_kind { + let closure_kind_ty = match expected_kind { Some(kind) => Ty::from_closure_kind(tcx, kind), // Create a type variable (for now) to represent the closure kind. @@ -204,11 +187,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else { bug!("expected coroutine to have yield/resume types"); }; - let interior = fcx.next_ty_var(TypeVariableOrigin { + let interior = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: body.value.span, }); - fcx.deferred_coroutine_interiors.borrow_mut().push(( + self.deferred_coroutine_interiors.borrow_mut().push(( expr_def_id, body.id(), interior, From db36304102fd86305b0319d5a3d8f440aa4b139d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 3 Jan 2024 01:34:38 +0100 Subject: [PATCH 107/297] rustc_pattern_analysis no longer needs to be passed an arena --- Cargo.lock | 7 ------- compiler/rustc_pattern_analysis/Cargo.toml | 6 ------ .../rustc_pattern_analysis/src/constructor.rs | 6 +++--- compiler/rustc_pattern_analysis/src/lib.rs | 15 ++------------- compiler/rustc_pattern_analysis/src/pat.rs | 2 +- compiler/rustc_pattern_analysis/src/rustc.rs | 6 ++++-- .../rustc_pattern_analysis/src/usefulness.rs | 18 +++++++++--------- src/tools/tidy/src/deps.rs | 1 - 8 files changed, 19 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 440def727685..f23a18d38778 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4366,7 +4366,6 @@ dependencies = [ "rustc_target", "smallvec", "tracing", - "typed-arena", ] [[package]] @@ -5705,12 +5704,6 @@ dependencies = [ "rustc-hash", ] -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - [[package]] name = "typenum" version = "1.16.0" diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index 2152f9fda007..7cc585bea3af 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -20,13 +20,10 @@ rustc_span = { path = "../rustc_span", optional = true } rustc_target = { path = "../rustc_target", optional = true } smallvec = { version = "1.8.1", features = ["union"] } tracing = "0.1" -typed-arena = { version = "2.0.2", optional = true } # tidy-alphabetical-end [features] default = ["rustc"] -# It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so -# we use another feature instead. The crate won't compile if one of these isn't enabled. rustc = [ "dep:rustc_arena", "dep:rustc_data_structures", @@ -41,6 +38,3 @@ rustc = [ "smallvec/may_dangle", "rustc_index/nightly", ] -stable = [ - "dep:typed-arena", -] diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 15ff4ceb5b3a..c1042d5b66ec 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -718,7 +718,7 @@ impl Constructor { /// The number of fields for this constructor. This must be kept in sync with /// `Fields::wildcards`. - pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, '_, Cx>) -> usize { + pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize { pcx.ctor_arity(self) } @@ -727,7 +727,7 @@ impl Constructor { /// this checks for inclusion. // We inline because this has a single call site in `Matrix::specialize_constructor`. #[inline] - pub(crate) fn is_covered_by<'p>(&self, pcx: &PlaceCtxt<'_, 'p, Cx>, other: &Self) -> bool { + pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool { match (self, other) { (Wildcard, _) => pcx .mcx @@ -861,7 +861,7 @@ impl ConstructorSet { #[instrument(level = "debug", skip(self, pcx, ctors), ret)] pub(crate) fn split<'a>( &self, - pcx: &PlaceCtxt<'a, '_, Cx>, + pcx: &PlaceCtxt<'a, Cx>, ctors: impl Iterator> + Clone, ) -> SplitConstructorSet { let mut present: SmallVec<[_; 1]> = SmallVec::new(); diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 374914055d8f..ed10a5155084 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -38,13 +38,6 @@ use crate::rustc::RustcMatchCheckCtxt; #[cfg(feature = "rustc")] use crate::usefulness::{compute_match_usefulness, ValidityConstraint}; -// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so -// we use another feature instead. The crate won't compile if one of these isn't enabled. -#[cfg(feature = "rustc")] -pub(crate) use rustc_arena::TypedArena; -#[cfg(feature = "stable")] -pub(crate) use typed_arena::Arena as TypedArena; - pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} @@ -89,11 +82,9 @@ pub trait TypeCx: Sized + fmt::Debug { /// Context that provides information global to a match. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Copy(bound = ""))] -pub struct MatchCtxt<'a, 'p, Cx: TypeCx> { +pub struct MatchCtxt<'a, Cx: TypeCx> { /// The context for type information. pub tycx: &'a Cx, - /// An arena to store the wildcards we produce during analysis. - pub wildcard_arena: &'p TypedArena>, } /// The arm of a match expression. @@ -114,11 +105,9 @@ pub fn analyze_match<'p, 'tcx>( arms: &[rustc::MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> Result, ErrorGuaranteed> { - // Arena to store the extra wildcards we construct during analysis. - let wildcard_arena = tycx.pattern_arena; let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); - let cx = MatchCtxt { tycx, wildcard_arena }; + let cx = MatchCtxt { tycx }; let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?; diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 2f5dc241cb7f..75fe59edf88f 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -240,7 +240,7 @@ impl WitnessPat { /// Construct a pattern that matches everything that starts with this constructor. /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. - pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, '_, Cx>, ctor: Constructor) -> Self { + pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor) -> Self { let field_tys = pcx.ctor_sub_tys(&ctor); let fields = field_tys.iter().map(|ty| Self::wildcard(*ty)).collect(); Self::new(ctor, fields, pcx.ty) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a17cd2c81b94..e82d6666b1af 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -33,11 +33,11 @@ pub type ConstructorSet<'p, 'tcx> = pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; pub type OverlappingRanges<'p, 'tcx> = crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type PlaceCtxt<'a, 'p, 'tcx> = - crate::usefulness::PlaceCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>; + crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type SplitConstructorSet<'p, 'tcx> = crate::constructor::SplitConstructorSet>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; @@ -80,7 +80,9 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { /// outside its module and should not be matchable with an empty match statement. pub module: DefId, pub param_env: ty::ParamEnv<'tcx>, + /// To allocate lowered patterns pub pattern_arena: &'p TypedArena>, + /// To allocate the result of `self.ctor_sub_tys()` pub dropless_arena: &'p DroplessArena, /// Lint level at the match. pub match_lint_level: HirId, diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 85b6a6a3b6c7..6244cf0ff7d7 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -732,19 +732,19 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { /// Context that provides information local to a place under investigation. #[derive(derivative::Derivative)] #[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))] -pub(crate) struct PlaceCtxt<'a, 'p, Cx: TypeCx> { +pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { #[derivative(Debug = "ignore")] - pub(crate) mcx: MatchCtxt<'a, 'p, Cx>, + pub(crate) mcx: MatchCtxt<'a, Cx>, /// Type of the place under investigation. pub(crate) ty: Cx::Ty, /// Whether the place is the original scrutinee place, as opposed to a subplace of it. pub(crate) is_scrutinee: bool, } -impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> { +impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { /// A `PlaceCtxt` when code other than `is_useful` needs one. #[cfg_attr(not(feature = "rustc"), allow(dead_code))] - pub(crate) fn new_dummy(mcx: MatchCtxt<'a, 'p, Cx>, ty: Cx::Ty) -> Self { + pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: Cx::Ty) -> Self { PlaceCtxt { mcx, ty, is_scrutinee: false } } @@ -1067,7 +1067,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { /// This computes `specialize(ctor, self)`. See top of the file for explanations. fn specialize_constructor( &self, - pcx: &PlaceCtxt<'_, 'p, Cx>, + pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor, ctor_is_relevant: bool, ) -> Matrix<'p, Cx> { @@ -1226,7 +1226,7 @@ impl WitnessStack { /// pats: [(false, "foo"), _, true] /// result: [Enum::Variant { a: (false, "foo"), b: _ }, true] /// ``` - fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, '_, Cx>, ctor: &Constructor) { + fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor) { let len = self.0.len(); let arity = ctor.arity(pcx); let fields = self.0.drain((len - arity)..).rev().collect(); @@ -1277,7 +1277,7 @@ impl WitnessMatrix { /// Reverses specialization by `ctor`. See the section on `unspecialize` at the top of the file. fn apply_constructor( &mut self, - pcx: &PlaceCtxt<'_, '_, Cx>, + pcx: &PlaceCtxt<'_, Cx>, missing_ctors: &[Constructor], ctor: &Constructor, report_individual_missing_ctors: bool, @@ -1421,7 +1421,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx, is_top_level), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( - mcx: MatchCtxt<'a, 'p, Cx>, + mcx: MatchCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, overlapping_range_endpoints: &mut Vec>, is_top_level: bool, @@ -1591,7 +1591,7 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { /// Computes whether a match is exhaustive and which of its arms are useful. #[instrument(skip(cx, arms), level = "debug")] pub fn compute_match_usefulness<'p, Cx: TypeCx>( - cx: MatchCtxt<'_, 'p, Cx>, + cx: MatchCtxt<'_, Cx>, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c198c116282b..b03811e5efda 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -359,7 +359,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "tracing-tree", "twox-hash", "type-map", - "typed-arena", "typenum", "unic-langid", "unic-langid-impl", From 6a6318342a953f0ad83de003c080d19bd4b911aa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 17:52:26 +0000 Subject: [PATCH 108/297] Signature deduction is only done for Fn traits --- compiler/rustc_hir_typeck/src/closure.rs | 34 +++++------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index b7ca070a4787..1bc750a7e121 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::ArgKind; @@ -347,36 +347,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let trait_def_id = projection.trait_def_id(tcx); - - let is_fn = tcx.is_fn_trait(trait_def_id); - - let coroutine_trait = tcx.lang_items().coroutine_trait(); - let is_gen = coroutine_trait == Some(trait_def_id); - - if !is_fn && !is_gen { - debug!("not fn or coroutine"); + // For now, we only do signature deduction based off of the `Fn` traits. + if !tcx.is_fn_trait(trait_def_id) { return None; } - // Check that we deduce the signature from the `<_ as std::ops::Coroutine>::Return` - // associated item and not yield. - if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return { - debug!("not `Return` assoc item of `Coroutine`"); - return None; - } + let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1); + let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); + debug!(?arg_param_ty); - let input_tys = if is_fn { - let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1); - let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); - debug!(?arg_param_ty); - - match arg_param_ty.kind() { - &ty::Tuple(tys) => tys, - _ => return None, - } - } else { - // Coroutines with a `()` resume type may be defined with 0 or 1 explicit arguments, - // else they must have exactly 1 argument. For now though, just give up in this case. + let ty::Tuple(input_tys) = *arg_param_ty.kind() else { return None; }; From b858c591dd85f51bb515f492cfa8a0252339ddb9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 11 Jan 2024 21:20:15 -0800 Subject: [PATCH 109/297] Tune the inlinability of `Result::unwrap` --- library/core/src/result.rs | 2 +- tests/codegen/infallible-unwrap-in-opt-z.rs | 26 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/infallible-unwrap-in-opt-z.rs diff --git a/library/core/src/result.rs b/library/core/src/result.rs index eff1b9b59b14..1f448984e531 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1061,7 +1061,7 @@ impl Result { /// let x: Result = Err("emergency failure"); /// x.unwrap(); // panics with `emergency failure` /// ``` - #[inline] + #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap(self) -> T diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs new file mode 100644 index 000000000000..5c57b41532fb --- /dev/null +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -0,0 +1,26 @@ +// compile-flags: -C opt-level=z --edition=2021 +// ignore-debug + +#![crate_type = "lib"] + +// From + +// CHECK-LABEL: @read_up_to_8( +#[no_mangle] +pub fn read_up_to_8(buf: &[u8]) -> u64 { + // CHECK-NOT: unwrap_failed + if buf.len() < 4 { + // actual instance has more code. + return 0; + } + let lo = u32::from_le_bytes(buf[..4].try_into().unwrap()) as u64; + let hi = u32::from_le_bytes(buf[buf.len() - 4..][..4].try_into().unwrap()) as u64; + lo | (hi << 8 * (buf.len() as u64 - 4)) +} + +// CHECK-LABEL: @checking_unwrap_expectation( +#[no_mangle] +pub fn checking_unwrap_expectation(buf: &[u8]) -> &[u8; 4] { + // CHECK: call void @_ZN4core6result13unwrap_failed17h + buf.try_into().unwrap() +} From aa8ecd0652afbecd6549d2f6e53c0a5f6aa76d8f Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 26 Dec 2023 18:34:44 -0800 Subject: [PATCH 110/297] Suggest quoting unquoted idents in attrs --- compiler/rustc_parse/messages.ftl | 3 ++ compiler/rustc_parse/src/errors.rs | 19 +++++++++++++ compiler/rustc_parse/src/parser/attr.rs | 28 ++++++++++++++++--- ...-66340-deprecated-attr-non-meta-grammar.rs | 2 +- ...40-deprecated-attr-non-meta-grammar.stderr | 7 ++++- .../attribute/attr-unquoted-ident.fixed | 15 ++++++++++ .../parser/attribute/attr-unquoted-ident.rs | 15 ++++++++++ .../attribute/attr-unquoted-ident.stderr | 24 ++++++++++++++++ 8 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 tests/ui/parser/attribute/attr-unquoted-ident.fixed create mode 100644 tests/ui/parser/attribute/attr-unquoted-ident.rs create mode 100644 tests/ui/parser/attribute/attr-unquoted-ident.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index c11a6fab7e5d..d515e86a1829 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -407,6 +407,9 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}` +parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}` + .suggestion = surround the identifier with quotation marks to parse it as a string + parse_invalid_offset_of = offset_of expects dot-separated field and variant names parse_invalid_unicode_escape = invalid unicode character escape diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0de252707bd3..34b34a1bad6c 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -973,6 +973,25 @@ pub(crate) struct InvalidMetaItem { pub token: Token, } +#[derive(Diagnostic)] +#[diag(parse_invalid_meta_item_unquoted_ident)] +pub(crate) struct InvalidMetaItemUnquotedIdent { + #[primary_span] + pub span: Span, + pub token: Token, + #[subdiagnostic] + pub sugg: InvalidMetaItemSuggQuoteIdent, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct InvalidMetaItemSuggQuoteIdent { + #[suggestion_part(code = "\"")] + pub before: Span, + #[suggestion_part(code = "\"")] + pub after: Span, +} + #[derive(Subdiagnostic)] #[suggestion( parse_sugg_escape_identifier, diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 02dab95233a3..a92609c2c2f8 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,4 +1,7 @@ -use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute}; +use crate::errors::{ + InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent, + SuffixedLiteralInAttribute, +}; use crate::fluent_generated as fluent; use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; @@ -417,9 +420,26 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - Err(self - .dcx() - .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) + let token = self.token.clone(); + + // Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)] + // `from_expansion()` ensures we don't suggest for cases such as + // `#[cfg(feature = $expr)]` in macros + if self.prev_token == token::Eq && !self.token.span.from_expansion() { + let before = self.token.span.shrink_to_lo(); + while matches!(self.token.kind, token::Ident(..)) { + self.bump(); + } + let after = self.prev_token.span.shrink_to_hi(); + let sugg = InvalidMetaItemSuggQuoteIdent { before, after }; + return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent { + span: token.span, + token, + sugg, + })); + } + + Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token })) } } diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs index c0cde75d4cae..6653bd15ddd2 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -7,5 +7,5 @@ fn main() { } #[deprecated(note = test)] -//~^ ERROR expected unsuffixed literal or identifier, found `test` +//~^ ERROR expected unsuffixed literal, found `test` fn foo() {} diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr index 48c763c50e3b..078c766deedd 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -1,8 +1,13 @@ -error: expected unsuffixed literal or identifier, found `test` +error: expected unsuffixed literal, found `test` --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 | LL | #[deprecated(note = test)] | ^^^^ + | +help: surround the identifier with quotation marks to parse it as a string + | +LL | #[deprecated(note = "test")] + | + + error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.fixed b/tests/ui/parser/attribute/attr-unquoted-ident.fixed new file mode 100644 index 000000000000..6cdf22f7ec0e --- /dev/null +++ b/tests/ui/parser/attribute/attr-unquoted-ident.fixed @@ -0,0 +1,15 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes +// run-rustfix + +fn main() { + #[cfg(key="foo")] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); + #[cfg(key="bar")] + println!(); + #[cfg(key="foo bar baz")] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); +} diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs new file mode 100644 index 000000000000..75af015c9fee --- /dev/null +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes +// run-rustfix + +fn main() { + #[cfg(key=foo)] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); + #[cfg(key="bar")] + println!(); + #[cfg(key=foo bar baz)] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); +} diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr new file mode 100644 index 000000000000..bc028f39be61 --- /dev/null +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -0,0 +1,24 @@ +error: expected unsuffixed literal, found `foo` + --> $DIR/attr-unquoted-ident.rs:5:15 + | +LL | #[cfg(key=foo)] + | ^^^ + | +help: surround the identifier with quotation marks to parse it as a string + | +LL | #[cfg(key="foo")] + | + + + +error: expected unsuffixed literal, found `foo` + --> $DIR/attr-unquoted-ident.rs:11:15 + | +LL | #[cfg(key=foo bar baz)] + | ^^^ + | +help: surround the identifier with quotation marks to parse it as a string + | +LL | #[cfg(key="foo bar baz")] + | + + + +error: aborting due to 2 previous errors + From 46ad13136c96acfa05c2249796913b3280ae0fc3 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:09:38 +0000 Subject: [PATCH 111/297] update fn pointer trait impl docs --- library/core/src/primitive_docs.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bd2851a26fb8..5025b77d6982 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1634,9 +1634,8 @@ mod prim_ref {} /// function pointers of varying length. Note that this is a convenience notation to avoid /// repetitive documentation, not valid Rust syntax. /// -/// Due to a temporary restriction in Rust's type system, these traits are only implemented on -/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this -/// may change: +/// The following traits are implemented for function pointers with any number of arguments and +/// any ABI. /// /// * [`PartialEq`] /// * [`Eq`] @@ -1645,11 +1644,6 @@ mod prim_ref {} /// * [`Hash`] /// * [`Pointer`] /// * [`Debug`] -/// -/// The following traits are implemented for function pointers with any number of arguments and -/// any ABI. These traits have implementations that are automatically generated by the compiler, -/// so are not limited by missing language features: -/// /// * [`Clone`] /// * [`Copy`] /// * [`Send`] From c36b5d535363917503c04943a8254a1bd3ed4296 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:48:33 -0800 Subject: [PATCH 112/297] Fix ICE when suggesting dereferencing binop operands --- compiler/rustc_hir/src/lang_items.rs | 27 +++++++++++++++++++ .../src/traits/error_reporting/suggestions.rs | 8 ++++++ tests/ui/binop/binary-op-suggest-deref.rs | 8 ++++++ tests/ui/binop/binary-op-suggest-deref.stderr | 23 +++++++++++++++- 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 3f3b57ba94f9..1cc1f11b3c85 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -374,3 +374,30 @@ pub static OPERATORS: &'static [LangItem] = &[ LangItem::PartialEq, LangItem::PartialOrd, ]; + +pub static BINARY_OPERATORS: &'static [LangItem] = &[ + LangItem::Add, + LangItem::Sub, + LangItem::Mul, + LangItem::Div, + LangItem::Rem, + LangItem::BitXor, + LangItem::BitAnd, + LangItem::BitOr, + LangItem::Shl, + LangItem::Shr, + LangItem::AddAssign, + LangItem::SubAssign, + LangItem::MulAssign, + LangItem::DivAssign, + LangItem::RemAssign, + LangItem::BitXorAssign, + LangItem::BitAndAssign, + LangItem::BitOrAssign, + LangItem::ShlAssign, + LangItem::ShrAssign, + LangItem::Index, + LangItem::IndexMut, + LangItem::PartialEq, + LangItem::PartialOrd, +]; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6c0909d28539..0e33e9cd790d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -859,6 +859,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let hir::Node::Expr(lhs) = self.tcx.hir_node(*lhs_hir_id) && let hir::Node::Expr(rhs) = self.tcx.hir_node(*rhs_hir_id) && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) + && let trait_pred = predicate.unwrap_or(trait_pred) + // Only run this code on binary operators + && hir::lang_items::BINARY_OPERATORS + .iter() + .filter_map(|&op| self.tcx.lang_items().get(op)) + .any(|op| { + op == trait_pred.skip_binder().trait_ref.def_id + }) { // Suggest dereferencing the LHS, RHS, or both terms of a binop if possible diff --git a/tests/ui/binop/binary-op-suggest-deref.rs b/tests/ui/binop/binary-op-suggest-deref.rs index 57f24a4c28ed..ae442a0d0b48 100644 --- a/tests/ui/binop/binary-op-suggest-deref.rs +++ b/tests/ui/binop/binary-op-suggest-deref.rs @@ -72,4 +72,12 @@ fn baz() { //~^ERROR can't compare `str` with `&String` [E0277] } +fn qux() { + // Issue #119352 + const FOO: i32 = 42; + let _ = FOO & (*"Sized".to_string().into_boxed_str()); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| ERROR no implementation for `i32 & str` [E0277] +} + fn main() {} diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr index 68b5a24bf974..a98a2ab07066 100644 --- a/tests/ui/binop/binary-op-suggest-deref.stderr +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -295,7 +295,28 @@ help: consider dereferencing here LL | _ = partial[..3] == *string_ref; | + -error: aborting due to 22 previous errors +error[E0277]: no implementation for `i32 & str` + --> $DIR/binary-op-suggest-deref.rs:78:17 + | +LL | let _ = FOO & (*"Sized".to_string().into_boxed_str()); + | ^ no implementation for `i32 & str` + | + = help: the trait `BitAnd` is not implemented for `i32` + = help: the following other types implement trait `BitAnd`: + + > + <&'a i32 as BitAnd> + <&i32 as BitAnd<&i32>> + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/binary-op-suggest-deref.rs:78:17 + | +LL | let _ = FOO & (*"Sized".to_string().into_boxed_str()); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + +error: aborting due to 24 previous errors Some errors have detailed explanations: E0277, E0308, E0369. For more information about an error, try `rustc --explain E0277`. From ac58f9ae034eaba1ae2efd27d43d5e2328260461 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Sat, 13 Jan 2024 16:32:03 +0100 Subject: [PATCH 113/297] Update measureme crate to version 11 --- Cargo.lock | 4 ++-- compiler/rustc_codegen_llvm/Cargo.toml | 2 +- compiler/rustc_data_structures/Cargo.toml | 2 +- compiler/rustc_middle/Cargo.toml | 2 +- compiler/rustc_query_impl/Cargo.toml | 2 +- src/tools/miri/Cargo.toml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 440def727685..697e8c81bda8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2366,9 +2366,9 @@ dependencies = [ [[package]] name = "measureme" -version = "10.1.2" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe" +checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" dependencies = [ "log", "memmap2", diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index c12142e302d3..3948a49ee2aa 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,7 @@ test = false bitflags = "2.4.1" itertools = "0.11" libc = "0.2" -measureme = "10.0.0" +measureme = "11" object = { version = "0.32.0", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 23949deaade8..9d598c32e6fc 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -13,7 +13,7 @@ indexmap = { version = "2.0.0" } itertools = "0.11" jobserver_crate = { version = "0.1.27", package = "jobserver" } libc = "0.2" -measureme = "10.0.0" +measureme = "11" rustc-hash = "1.1.0" rustc-rayon = { version = "0.5.0", optional = true } rustc-rayon-core = { version = "0.5.0", optional = true } diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 8e6ca645f80c..82e56c9cbe20 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -10,7 +10,7 @@ derive_more = "0.99.17" either = "1.5.0" field-offset = "0.3.5" gsgdt = "0.1.2" -measureme = "10.0.0" +measureme = "11" polonius-engine = "0.13.0" rustc-rayon = { version = "0.5.0", optional = true } rustc-rayon-core = { version = "0.5.0", optional = true } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 88eb46030697..c57f22a0da2b 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start field-offset = "0.3.5" -measureme = "10.0.0" +measureme = "11" rustc-rayon-core = { version = "0.5.0", optional = true } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 3da751c69a9f..a65010b055b6 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -24,7 +24,7 @@ log = "0.4" rand = "0.8" smallvec = "1.7" aes = { version = "0.8.3", features = ["hazmat"] } -measureme = "10.0.0" +measureme = "11" ctrlc = "3.2.5" # Copied from `compiler/rustc/Cargo.toml`. From 41b69aae912aa9a1a8d5ed9518e73d136b42e7ca Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 13 Jan 2024 12:18:51 +0100 Subject: [PATCH 114/297] Add way to express no-values with check-cfg --- compiler/rustc_interface/src/interface.rs | 4 ++- .../rustc_lint/src/context/diagnostics.rs | 11 ++++++++ .../src/compiler-flags/check-cfg.md | 25 ++++++++++--------- tests/ui/check-cfg/cargo-feature.none.stderr | 20 ++++++++------- tests/ui/check-cfg/cargo-feature.rs | 9 +++---- tests/ui/check-cfg/cargo-feature.some.stderr | 7 +++--- tests/ui/check-cfg/concat-values.rs | 4 +++ tests/ui/check-cfg/concat-values.stderr | 4 +-- tests/ui/check-cfg/empty-values.rs | 14 +++++++++++ tests/ui/check-cfg/empty-values.stderr | 23 +++++++++++++++++ 10 files changed, 89 insertions(+), 32 deletions(-) create mode 100644 tests/ui/check-cfg/empty-values.rs create mode 100644 tests/ui/check-cfg/empty-values.stderr diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 32fba6ade88d..5ca880909967 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -218,7 +218,9 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { } } - if values.is_empty() && !values_any_specified && !any_specified { + if !values_specified && !any_specified { + // `cfg(name)` is equivalent to `cfg(name, values(none()))` so add + // an implicit `none()` values.insert(None); } else if !values.is_empty() && values_any_specified { error!( diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 9e6a6f70eac0..312874db3f54 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -354,6 +354,15 @@ pub(super) fn builtin( Applicability::MaybeIncorrect, ); } + } else { + db.note(format!("no expected values for `{name}`")); + + let sp = if let Some((_value, value_span)) = value { + name_span.to(value_span) + } else { + name_span + }; + db.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect); } // We don't want to suggest adding values to well known names @@ -373,6 +382,8 @@ pub(super) fn builtin( if name == sym::feature { if let Some((value, _value_span)) = value { db.help(format!("consider adding `{value}` as a feature in `Cargo.toml`")); + } else { + db.help("consider defining some features in `Cargo.toml`"); } } else if !is_cfg_a_well_know_name { db.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`")); diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 78bc8dceb782..bf83f6ad7c5f 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -44,15 +44,20 @@ To enable checking of values, but to provide an *none*/empty set of expected val ```bash rustc --check-cfg 'cfg(name)' -rustc --check-cfg 'cfg(name, values())' rustc --check-cfg 'cfg(name, values(none()))' ``` -To enable checking of name but not values (i.e. unknown expected values), use this form: +To enable checking of name but not values, use one of these forms: -```bash -rustc --check-cfg 'cfg(name, values(any()))' -``` + - No expected values (_will lint on every value_): + ```bash + rustc --check-cfg 'cfg(name, values())' + ``` + + - Unknown expected values (_will never lint_): + ```bash + rustc --check-cfg 'cfg(name, values(any()))' + ``` To avoid repeating the same set of values, use this form: @@ -114,18 +119,14 @@ as argument to `--check-cfg`. This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument. | `--cfg` | `--check-cfg` | -|-----------------------------|----------------------------------------------------------| +|-------------------------------|------------------------------------------------------------| | *nothing* | *nothing* or `--check-cfg=cfg()` (to enable the checking) | -| `--cfg foo` | `--check-cfg=cfg(foo), --check-cfg=cfg(foo, values())` or `--check-cfg=cfg(foo, values(none()))` | +| `--cfg foo` | `--check-cfg=cfg(foo)` or `--check-cfg=cfg(foo, values(none()))` | | `--cfg foo=""` | `--check-cfg=cfg(foo, values(""))` | | `--cfg foo="bar"` | `--check-cfg=cfg(foo, values("bar"))` | | `--cfg foo="1" --cfg foo="2"` | `--check-cfg=cfg(foo, values("1", "2"))` | | `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` | -| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar"))` | - -NOTE: There is (currently) no way to express that a condition name is expected but no (!= none) -values are expected. Passing an empty `values()` means *(none)* in the sense of `#[cfg(foo)]` -with no value. Users are expected to NOT pass a `--check-cfg` with that condition name. +| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo, values(none(), "bar"))` | ### Example: Cargo-like `feature` example diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index 9a3084294847..aed4fd2a8c0e 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -1,34 +1,36 @@ -warning: unexpected `cfg` condition name: `feature` - --> $DIR/cargo-feature.rs:13:7 +warning: unexpected `cfg` condition value: `serde` + --> $DIR/cargo-feature.rs:14:7 | LL | #[cfg(feature = "serde")] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ help: remove the condition | - = help: consider defining some features in `Cargo.toml` + = note: no expected values for `feature` + = help: consider adding `serde` as a feature in `Cargo.toml` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default -warning: unexpected `cfg` condition name: `feature` +warning: unexpected `cfg` condition value: (none) --> $DIR/cargo-feature.rs:18:7 | LL | #[cfg(feature)] - | ^^^^^^^ + | ^^^^^^^ help: remove the condition | + = note: no expected values for `feature` = help: consider defining some features in `Cargo.toml` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:23:7 + --> $DIR/cargo-feature.rs:22:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `CONFIG_NVME` - --> $DIR/cargo-feature.rs:27:7 + --> $DIR/cargo-feature.rs:26:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs index f2fd0fd6420f..8542174d0c09 100644 --- a/tests/ui/check-cfg/cargo-feature.rs +++ b/tests/ui/check-cfg/cargo-feature.rs @@ -5,19 +5,18 @@ // check-pass // revisions: some none // rustc-env:CARGO=/usr/bin/cargo -// compile-flags: --check-cfg=cfg() -Z unstable-options +// compile-flags: -Z unstable-options +// [none]compile-flags: --check-cfg=cfg(feature,values()) // [some]compile-flags: --check-cfg=cfg(feature,values("bitcode")) // [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y")) // [none]error-pattern:Cargo.toml #[cfg(feature = "serde")] -//[none]~^ WARNING unexpected `cfg` condition name -//[some]~^^ WARNING unexpected `cfg` condition value +//~^ WARNING unexpected `cfg` condition value fn ser() {} #[cfg(feature)] -//[none]~^ WARNING unexpected `cfg` condition name -//[some]~^^ WARNING unexpected `cfg` condition value +//~^ WARNING unexpected `cfg` condition value fn feat() {} #[cfg(tokio_unstable)] diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index fc6951b56174..74d65e550bbe 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `serde` - --> $DIR/cargo-feature.rs:13:7 + --> $DIR/cargo-feature.rs:14:7 | LL | #[cfg(feature = "serde")] | ^^^^^^^^^^^^^^^^^ @@ -16,10 +16,11 @@ LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "bitcode"` | = note: expected values for `feature` are: `bitcode` + = help: consider defining some features in `Cargo.toml` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:23:7 + --> $DIR/cargo-feature.rs:22:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ @@ -29,7 +30,7 @@ LL | #[cfg(tokio_unstable)] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `m` - --> $DIR/cargo-feature.rs:27:7 + --> $DIR/cargo-feature.rs:26:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^--- diff --git a/tests/ui/check-cfg/concat-values.rs b/tests/ui/check-cfg/concat-values.rs index 0f9178ce6a57..ad922f8c9088 100644 --- a/tests/ui/check-cfg/concat-values.rs +++ b/tests/ui/check-cfg/concat-values.rs @@ -1,6 +1,7 @@ // check-pass // compile-flags: -Z unstable-options // compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar")) +// compile-flags: --check-cfg=cfg(my_cfg,values()) #[cfg(my_cfg)] //~^ WARNING unexpected `cfg` condition value @@ -10,4 +11,7 @@ fn my_cfg() {} //~^ WARNING unexpected `cfg` condition value fn my_cfg() {} +#[cfg(any(my_cfg = "foo", my_cfg = "bar"))] +fn foo_and_bar() {} + fn main() {} diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr index dec43f5bda3b..6fe9f2baa09f 100644 --- a/tests/ui/check-cfg/concat-values.stderr +++ b/tests/ui/check-cfg/concat-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: (none) - --> $DIR/concat-values.rs:5:7 + --> $DIR/concat-values.rs:6:7 | LL | #[cfg(my_cfg)] | ^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(my_cfg)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `unk` - --> $DIR/concat-values.rs:9:7 + --> $DIR/concat-values.rs:10:7 | LL | #[cfg(my_cfg = "unk")] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs new file mode 100644 index 000000000000..7e6ba6ae84a8 --- /dev/null +++ b/tests/ui/check-cfg/empty-values.rs @@ -0,0 +1,14 @@ +// Check that we detect unexpected value when none are allowed +// +// check-pass +// compile-flags: --check-cfg=cfg(foo,values()) -Zunstable-options + +#[cfg(foo = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +#[cfg(foo)] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +fn main() {} diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/empty-values.stderr new file mode 100644 index 000000000000..e7b0b05d5616 --- /dev/null +++ b/tests/ui/check-cfg/empty-values.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/empty-values.rs:6:7 + | +LL | #[cfg(foo = "foo")] + | ^^^^^^^^^^^ help: remove the condition + | + = note: no expected values for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo, values("foo"))` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: (none) + --> $DIR/empty-values.rs:10:7 + | +LL | #[cfg(foo)] + | ^^^ help: remove the condition + | + = note: no expected values for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo)` + = note: see for more information about checking conditional configuration + +warning: 2 warnings emitted + From 0b45ff5dac44aa8cb65c800eb8f1ad32d2a2ded7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 20:55:50 +0000 Subject: [PATCH 115/297] Don't ICE when noting GAT bounds in report_no_match_method_error --- .../rustc_hir_typeck/src/method/suggest.rs | 17 +++--- ...ied-gat-bound-during-assoc-ty-selection.rs | 33 ++++++++++++ ...gat-bound-during-assoc-ty-selection.stderr | 52 +++++++++++++++++++ 3 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs create mode 100644 tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1f01c6b7406b..3bf1e1312b31 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -825,11 +825,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "auto trait is invoked with no method error, but no error reported?", ); } - Some(Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), - .. - })) => { + Some( + Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), + .. + }) + // We may also encounter unsatisfied GAT or method bounds + | Node::TraitItem(hir::TraitItem { ident, .. }) + | Node::ImplItem(hir::ImplItem { ident, .. }), + ) => { skip_list.insert(p); let entry = spanned_predicates.entry(ident.span); let entry = entry.or_insert_with(|| { @@ -840,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); entry.2.push(p); } - Some(node) => unreachable!("encountered `{node:?}`"), + Some(node) => unreachable!("encountered `{node:?}` due to `{cause:#?}`"), None => (), } } diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs new file mode 100644 index 000000000000..252dc7d751e6 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +trait PointerFamily { + type Pointer: Deref; +} + +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer = dyn Deref; + //~^ ERROR the size for values of type `(dyn Deref + 'static)` cannot be known at compilation time +} + +enum Node { + Cons(T, P::Pointer>), + Nil, +} + +type RcNode = Node; + +impl Node +where + P::Pointer>: Sized, +{ + fn new() -> P::Pointer { + todo!() + } +} + +fn main() { + let mut list = RcNode::::new(); + //~^ ERROR the size for values of type `Node` cannot be known at compilation time +} diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr new file mode 100644 index 000000000000..3a973d356dc9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr @@ -0,0 +1,52 @@ +error[E0277]: the size for values of type `(dyn Deref + 'static)` cannot be known at compilation time + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:10:23 + | +LL | type Pointer = dyn Deref; + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Deref + 'static)` +note: required by a bound in `PointerFamily::Pointer` + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:5 + | +LL | type Pointer: Deref; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `PointerFamily::Pointer` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Pointer: Deref + ?Sized; + | ++++++++ + +error[E0599]: the size for values of type `Node` cannot be known at compilation time + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35 + | +LL | enum Node { + | ------------------------------ + | | + | variant or associated item `new` not found for this enum + | doesn't satisfy `Node: Sized` +... +LL | let mut list = RcNode::::new(); + | ^^^ doesn't have a size known at compile-time + --> $SRC_DIR/core/src/ops/deref.rs:LL:COL + | + = note: doesn't satisfy `_: Sized` + | +note: trait bound `Node: Sized` was not satisfied + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18 + | +LL | type Pointer: Deref; + | ------- ^ unsatisfied trait bound introduced here +note: trait bound `(dyn Deref> + 'static): Sized` was not satisfied + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:23:29 + | +LL | impl Node + | ---------- +LL | where +LL | P::Pointer>: Sized, + | ^^^^^ unsatisfied trait bound introduced here +note: the trait `Sized` must be implemented + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. From 04a6fd241bc18391b3f1f6ece1b109acd19842f1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 17:09:33 +0000 Subject: [PATCH 116/297] Make InferCtxtExt::could_impl_trait less messed up --- .../rustc_borrowck/src/diagnostics/mod.rs | 8 +- .../src/diagnostics/mutability_errors.rs | 23 +++-- .../src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 91 +++++++------------ .../issue-119915-bad-clone-suggestion.rs | 28 ++++++ .../issue-119915-bad-clone-suggestion.stderr | 17 ++++ tests/ui/borrowck/issue-85765-closure.rs | 1 - tests/ui/borrowck/issue-85765-closure.stderr | 13 +-- tests/ui/borrowck/issue-85765.rs | 1 - tests/ui/borrowck/issue-85765.stderr | 13 +-- tests/ui/borrowck/issue-91206.rs | 1 - tests/ui/borrowck/issue-91206.stderr | 7 +- tests/ui/moves/move-fn-self-receiver.stderr | 14 ++- 13 files changed, 118 insertions(+), 101 deletions(-) create mode 100644 tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs create mode 100644 tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index b31325485db9..bb802c4eb461 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1178,9 +1178,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { vec![(move_span.shrink_to_hi(), ".clone()".to_string())] }; - if let Some(errors) = - self.infcx.could_impl_trait(clone_trait, ty, self.param_env) - && !has_sugg + if let Some(errors) = self.infcx.type_implements_trait_shallow( + clone_trait, + ty, + self.param_env, + ) && !has_sugg { let msg = match &errors[..] { [] => "you can `clone` the value and consume it, but this \ diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3b3d440df97b..60164e84d546 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1217,19 +1217,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { match self .infcx - .could_impl_trait(clone_trait, ty.peel_refs(), self.param_env) + .type_implements_trait_shallow( + clone_trait, + ty.peel_refs(), + self.param_env, + ) .as_deref() { Some([]) => { - // The type implements Clone. - err.span_help( - expr.span, - format!( - "you can `clone` the `{}` value and consume it, but this \ - might not be your desired behavior", - ty.peel_refs(), - ), - ); + // FIXME: This error message isn't useful, since we're just + // vaguely suggesting to clone a value that already + // implements `Clone`. + // + // A correct suggestion here would take into account the fact + // that inference may be affected by missing types on bindings, + // etc., to improve "tests/ui/borrowck/issue-91206.stderr", for + // example. } None => { if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) = diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b542132d71ce..6944b5eb176b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1623,7 +1623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { if let Some(errors) = - self.could_impl_trait(clone_trait_did, expected_ty, self.param_env) + self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { match &errors[..] { [] => {} diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 251f0628a713..ef4a0f52f9ea 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,13 +1,14 @@ -use crate::solve::FulfillmentCtxt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, DefiningAnchor, ObligationCtxt}; +use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext}; +use crate::traits::TraitEngineExt as _; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; +use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt as _}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, ToPredicate}; use rustc_span::DUMMY_SP; @@ -21,7 +22,8 @@ pub trait InferCtxtExt<'tcx> { fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - /// Check whether a `ty` implements given trait(trait_def_id). + /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. + /// /// The inputs are: /// /// - the def-id of the trait @@ -29,8 +31,8 @@ pub trait InferCtxtExt<'tcx> { /// - the parameter environment /// /// Invokes `evaluate_obligation`, so in the event that evaluating - /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent (or EvaluatedToAmbigStackDependent) - /// will be returned. + /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent + /// (or EvaluatedToAmbigStackDependent) will be returned. fn type_implements_trait( &self, trait_def_id: DefId, @@ -38,7 +40,18 @@ pub trait InferCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult; - fn could_impl_trait( + /// Returns `Some` if a type implements a trait shallowly, without side-effects, + /// along with any errors that would have been reported upon further obligation + /// processing. + /// + /// - If this returns `Some([])`, then the trait holds modulo regions. + /// - If this returns `Some([errors..])`, then the trait has an impl for + /// the self type, but some nested obligations do not hold. + /// - If this returns `None`, no implementation that applies could be found. + /// + /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, + /// this will probably only ever return `Some([])` or `None`. + fn type_implements_trait_shallow( &self, trait_def_id: DefId, ty: Ty<'tcx>, @@ -86,64 +99,26 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } - fn could_impl_trait( + fn type_implements_trait_shallow( &self, trait_def_id: DefId, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option>> { self.probe(|_snapshot| { - if let ty::Adt(def, args) = ty.kind() - && let Some((impl_def_id, _)) = self - .tcx - .all_impls(trait_def_id) - .filter_map(|impl_def_id| { - self.tcx.impl_trait_ref(impl_def_id).map(|r| (impl_def_id, r)) - }) - .map(|(impl_def_id, imp)| (impl_def_id, imp.skip_binder())) - .find(|(_, imp)| match imp.self_ty().peel_refs().kind() { - ty::Adt(i_def, _) if i_def.did() == def.did() => true, - _ => false, - }) - { - let mut fulfill_cx = FulfillmentCtxt::new(self); - // We get all obligations from the impl to talk about specific - // trait bounds. - let obligations = self - .tcx - .predicates_of(impl_def_id) - .instantiate(self.tcx, args) - .into_iter() - .map(|(clause, span)| { - traits::Obligation::new( - self.tcx, - traits::ObligationCause::dummy_with_span(span), - param_env, - clause, - ) - }) - .collect::>(); - fulfill_cx.register_predicate_obligations(self, obligations); - let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty]); - let obligation = traits::Obligation::new( - self.tcx, - traits::ObligationCause::dummy(), - param_env, - trait_ref, - ); - fulfill_cx.register_predicate_obligation(self, obligation); - let mut errors = fulfill_cx.select_all_or_error(self); - // We remove the last predicate failure, which corresponds to - // the top-level obligation, because most of the type we only - // care about the other ones, *except* when it is the only one. - // This seems to only be relevant for arbitrary self-types. - // Look at `tests/ui/moves/move-fn-self-receiver.rs`. - if errors.len() > 1 { - errors.truncate(errors.len() - 1); + let mut selcx = SelectionContext::new(self); + match selcx.select(&Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty::TraitRef::new(self.tcx, trait_def_id, [ty]), + )) { + Ok(Some(selection)) => { + let mut fulfill_cx = >::new(self); + fulfill_cx.register_predicate_obligations(self, selection.nested_obligations()); + Some(fulfill_cx.select_all_or_error(self)) } - Some(errors) - } else { - None + Ok(None) | Err(_) => None, } }) } diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs new file mode 100644 index 000000000000..0b0ac9448dbd --- /dev/null +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs @@ -0,0 +1,28 @@ +use std::marker::PhantomData; + +struct Example(PhantomData<(fn(E), fn(FakeParam))>); + +struct NoLifetime; +struct Immutable<'a>(PhantomData<&'a ()>); + +impl<'a, E: 'a> Copy for Example> {} +impl<'a, E: 'a> Clone for Example> { + fn clone(&self) -> Self { + *self + } +} + +impl Example { + unsafe fn change(self) -> Example { + Example(PhantomData) + } +} + +impl Example { + fn the_ice(&mut self) -> Example> { + unsafe { self.change() } + //~^ ERROR cannot move out of `*self` which is behind a mutable reference + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr new file mode 100644 index 000000000000..ab42205d510f --- /dev/null +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of `*self` which is behind a mutable reference + --> $DIR/issue-119915-bad-clone-suggestion.rs:23:18 + | +LL | unsafe { self.change() } + | ^^^^ -------- `*self` moved due to this method call + | | + | move occurs because `*self` has type `Example`, which does not implement the `Copy` trait + | +note: `Example::::change` takes ownership of the receiver `self`, which moves `*self` + --> $DIR/issue-119915-bad-clone-suggestion.rs:16:36 + | +LL | unsafe fn change(self) -> Example { + | ^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-85765-closure.rs b/tests/ui/borrowck/issue-85765-closure.rs index edc9eeaffb5a..f2d1dd0fbc3f 100644 --- a/tests/ui/borrowck/issue-85765-closure.rs +++ b/tests/ui/borrowck/issue-85765-closure.rs @@ -3,7 +3,6 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; //~^ HELP consider changing this binding's type - //~| HELP you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-85765-closure.stderr b/tests/ui/borrowck/issue-85765-closure.stderr index 4a6a0e94becd..936ddd67bcd8 100644 --- a/tests/ui/borrowck/issue-85765-closure.stderr +++ b/tests/ui/borrowck/issue-85765-closure.stderr @@ -1,21 +1,16 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference - --> $DIR/issue-85765-closure.rs:7:9 + --> $DIR/issue-85765-closure.rs:6:9 | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -help: you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior - --> $DIR/issue-85765-closure.rs:4:36 - | -LL | let rofl: &Vec> = &mut test; - | ^^^^^^^^^ help: consider changing this binding's type | LL | let rofl: &mut Vec> = &mut test; | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:14:9 + --> $DIR/issue-85765-closure.rs:13:9 | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written @@ -26,7 +21,7 @@ LL | let r = &mut mutvar; | +++ error[E0594]: cannot assign to `*x`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:21:9 + --> $DIR/issue-85765-closure.rs:20:9 | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written @@ -37,7 +32,7 @@ LL | let x: &mut usize = &mut{0}; | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:28:9 + --> $DIR/issue-85765-closure.rs:27:9 | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs index ce5740bc0e7c..76e0b5173541 100644 --- a/tests/ui/borrowck/issue-85765.rs +++ b/tests/ui/borrowck/issue-85765.rs @@ -2,7 +2,6 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; //~^ HELP consider changing this binding's type - //~| HELP you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr index 4889f774afa8..57900bfb612e 100644 --- a/tests/ui/borrowck/issue-85765.stderr +++ b/tests/ui/borrowck/issue-85765.stderr @@ -1,21 +1,16 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference - --> $DIR/issue-85765.rs:6:5 + --> $DIR/issue-85765.rs:5:5 | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -help: you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior - --> $DIR/issue-85765.rs:3:32 - | -LL | let rofl: &Vec> = &mut test; - | ^^^^^^^^^ help: consider changing this binding's type | LL | let rofl: &mut Vec> = &mut test; | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference - --> $DIR/issue-85765.rs:13:5 + --> $DIR/issue-85765.rs:12:5 | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written @@ -26,7 +21,7 @@ LL | let r = &mut mutvar; | +++ error[E0594]: cannot assign to `*x`, which is behind a `&` reference - --> $DIR/issue-85765.rs:20:5 + --> $DIR/issue-85765.rs:19:5 | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written @@ -37,7 +32,7 @@ LL | let x: &mut usize = &mut{0}; | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference - --> $DIR/issue-85765.rs:27:5 + --> $DIR/issue-85765.rs:26:5 | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs index c60ac62fa347..e062a253767d 100644 --- a/tests/ui/borrowck/issue-91206.rs +++ b/tests/ui/borrowck/issue-91206.rs @@ -10,7 +10,6 @@ fn main() { let client = TestClient; let inner = client.get_inner_ref(); //~^ HELP consider specifying this binding's type - //~| HELP you can `clone` the `Vec` value and consume it, but this might not be your desired behavior inner.clear(); //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr index e3dd65b64197..f96b0c7d9e1a 100644 --- a/tests/ui/borrowck/issue-91206.stderr +++ b/tests/ui/borrowck/issue-91206.stderr @@ -1,14 +1,9 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference - --> $DIR/issue-91206.rs:14:5 + --> $DIR/issue-91206.rs:13:5 | LL | inner.clear(); | ^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -help: you can `clone` the `Vec` value and consume it, but this might not be your desired behavior - --> $DIR/issue-91206.rs:11:17 - | -LL | let inner = client.get_inner_ref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider specifying this binding's type | LL | let inner: &mut Vec = client.get_inner_ref(); diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index 462deacbe8d6..17f48f5f7bf7 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -55,10 +55,15 @@ note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `b | LL | fn use_box_self(self: Box) {} | ^^^^ -help: you could `clone` the value and consume it, if the `Box: Clone` trait bound could be satisfied +help: you could `clone` the value and consume it, if the `Foo: Clone` trait bound could be satisfied | LL | boxed_foo.clone().use_box_self(); | ++++++++ +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Foo; + | error[E0382]: use of moved value: `pin_box_foo` --> $DIR/move-fn-self-receiver.rs:46:5 @@ -75,10 +80,15 @@ note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which move | LL | fn use_pin_box_self(self: Pin>) {} | ^^^^ -help: you could `clone` the value and consume it, if the `Box: Clone` trait bound could be satisfied +help: you could `clone` the value and consume it, if the `Foo: Clone` trait bound could be satisfied | LL | pin_box_foo.clone().use_pin_box_self(); | ++++++++ +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Foo; + | error[E0505]: cannot move out of `mut_foo` because it is borrowed --> $DIR/move-fn-self-receiver.rs:50:5 From 7724ba7bd5f2c947a7dc561c24b19bb8409a6ed6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 21:53:42 +0000 Subject: [PATCH 117/297] assert that trait solver is only created in proper infcx --- compiler/rustc_trait_selection/src/solve/fulfill.rs | 5 +++++ compiler/rustc_trait_selection/src/traits/fulfill.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 2139210b8736..09f4f3e9702f 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -36,6 +36,11 @@ pub struct FulfillmentCtxt<'tcx> { impl<'tcx> FulfillmentCtxt<'tcx> { pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> { + assert!( + infcx.next_trait_solver(), + "new trait solver fulfillment context created when \ + infcx is set up for old trait solver" + ); FulfillmentCtxt { obligations: Vec::new(), usable_in_snapshot: infcx.num_open_snapshots() } } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 045d7e444b6e..472342f98980 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -80,6 +80,11 @@ static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> { + assert!( + !infcx.next_trait_solver(), + "old trait solver fulfillment context created when \ + infcx is set up for new trait solver" + ); FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: infcx.num_open_snapshots(), From 2de99ec787c80d4ba5ac4638d371a5bd8b752795 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 13 Jan 2024 10:31:09 +1100 Subject: [PATCH 118/297] Reformat `struct_span_code_err!`. --- compiler/rustc_errors/src/diagnostic_builder.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index bd7c58d904e7..93b2dd61b059 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -437,11 +437,7 @@ impl Drop for DiagnosticBuilder<'_, G> { #[macro_export] macro_rules! struct_span_code_err { ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - $dcx.struct_span_err( - $span, - format!($($message)*), - ) - .with_code($crate::error_code!($code)) + $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code)) }) } From 24c1f4aa802bc6b9c3710baa4464e691b5b13bb2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 22:57:44 +0000 Subject: [PATCH 119/297] Make sure to instantiate placeholders correctly in old solver --- .../src/infer/canonical/query_response.rs | 16 ++++++++--- ...ceholders-in-query-response.current.stderr | 11 ++++++++ ...placeholders-in-query-response.next.stderr | 11 ++++++++ ...unifying-placeholders-in-query-response.rs | 27 +++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8cca4c6231fc..1f071a9ff0bc 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -483,7 +483,13 @@ impl<'tcx> InferCtxt<'tcx> { let result_subst = CanonicalVarValues { var_values: self.tcx.mk_args_from_iter( query_response.variables.iter().enumerate().map(|(index, info)| { - if info.is_existential() { + if info.universe() != ty::UniverseIndex::ROOT { + // A variable from inside a binder of the query. While ideally these shouldn't + // exist at all, we have to deal with them for now. + self.instantiate_canonical_var(cause.span, info, |u| { + universe_map[u.as_usize()] + }) + } else if info.is_existential() { match opt_values[BoundVar::new(index)] { Some(k) => k, None => self.instantiate_canonical_var(cause.span, info, |u| { @@ -491,9 +497,11 @@ impl<'tcx> InferCtxt<'tcx> { }), } } else { - self.instantiate_canonical_var(cause.span, info, |u| { - universe_map[u.as_usize()] - }) + // For placeholders which were already part of the input, we simply map this + // universal bound variable back the placeholder of the input. + opt_values[BoundVar::new(index)].expect( + "expected placeholder to be unified with itself during response", + ) } }), ), diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr new file mode 100644 index 000000000000..040009efbde2 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr new file mode 100644 index 000000000000..040009efbde2 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs new file mode 100644 index 000000000000..5e28a2ba8b9b --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs @@ -0,0 +1,27 @@ +// revisions: current next +//[next] compile-flags: -Znext-solver +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +pub trait Foo { + type Bar: ?Sized; +} + +impl Foo for () { + type Bar = K; +} + +pub fn f(a: T1, b: T2) +where + T1: for Foo = T>, + T2: for Foo = >::Bar>, +{ +} + +fn it_works() { + f((), ()); +} + +fn main() {} From 985e1e031b0d9d7c54812931c2beb57b0d304a94 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 23:08:22 +0000 Subject: [PATCH 120/297] Add a simpler test --- ...holders-in-query-response-2.current.stderr | 11 +++++++++ ...aceholders-in-query-response-2.next.stderr | 11 +++++++++ ...ifying-placeholders-in-query-response-2.rs | 23 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr new file mode 100644 index 000000000000..4082d6d47e79 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr new file mode 100644 index 000000000000..4082d6d47e79 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs new file mode 100644 index 000000000000..bbf1a1f72db6 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs @@ -0,0 +1,23 @@ +// revisions: current next +//[next] compile-flags: -Znext-solver +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Id { + type Output: ?Sized; +} + +impl Id for T { + type Output = T; +} + +trait Everyone {} +impl Everyone for T {} + +fn hello() where for ::Output: Everyone {} + +fn main() { + hello(); +} From 4ca6342eb30dfbc3fe0992de0cfc780f3992f446 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 14 Jan 2024 00:24:39 +0000 Subject: [PATCH 121/297] Add note on SpecOptionPartialEq to `newtype_index` --- compiler/rustc_index_macros/src/lib.rs | 3 +++ library/core/src/option.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs index ac374a41eb6f..4f973c1f0101 100644 --- a/compiler/rustc_index_macros/src/lib.rs +++ b/compiler/rustc_index_macros/src/lib.rs @@ -31,6 +31,9 @@ mod newtype; /// - `#[max = 0xFFFF_FFFD]`: specifies the max value, which allows niche /// optimizations. The default max value is 0xFFFF_FF00. /// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only. +/// +/// `SpecOptionPartialEq` is specialized by this macro, so using it requires enabling +/// `#![feature(min_specialization)]` for the crate. #[proc_macro] #[cfg_attr( feature = "nightly", diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ff4353492498..781c7a91a5a2 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2147,6 +2147,7 @@ impl PartialEq for Option { /// /// Once that's fixed, `Option` should go back to deriving `PartialEq`, as /// it used to do before . +/// The comment regarding this trait on the `newtype_index` macro should be removed if this is done. #[unstable(feature = "spec_option_partial_eq", issue = "none", reason = "exposed only for rustc")] #[doc(hidden)] pub trait SpecOptionPartialEq: Sized { From 6d1c396399be9dc7a31cc023513e103848a96506 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 30 Dec 2023 17:59:39 +1100 Subject: [PATCH 122/297] coverage: Determine a block's successors from just the terminator Filtering out unreachable successors is only needed by the main graph traversal loop, so we can move the filtering step into that loop instead, eliminating the need to pass the MIR body into `bcb_filtered_successors`. --- .../rustc_mir_transform/src/coverage/graph.rs | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 263bfdaaabab..b8e269b9103c 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -3,7 +3,7 @@ use rustc_data_structures::graph::dominators::{self, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode}; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; +use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind}; use std::cmp::Ordering; use std::collections::VecDeque; @@ -38,7 +38,7 @@ impl CoverageGraph { } let bcb_data = &bcbs[bcb]; let mut bcb_successors = Vec::new(); - for successor in bcb_filtered_successors(mir_body, bcb_data.last_bb()) + for successor in bcb_filtered_successors(mir_body[bcb_data.last_bb()].terminator()) .filter_map(|successor_bb| bb_to_bcb[successor_bb]) { if !seen[successor] { @@ -91,7 +91,10 @@ impl CoverageGraph { // `catch_unwind()` handlers. let mut basic_blocks = Vec::new(); - for bb in short_circuit_preorder(mir_body, bcb_filtered_successors) { + let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator()); + for bb in short_circuit_preorder(mir_body, filtered_successors) + .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable) + { if let Some(last) = basic_blocks.last() { let predecessors = &mir_body.basic_blocks.predecessors()[bb]; if predecessors.len() > 1 || !predecessors.contains(last) { @@ -347,15 +350,12 @@ impl BasicCoverageBlockData { } // Returns the subset of a block's successors that are relevant to the coverage -// graph, i.e. those that do not represent unwinds or unreachable branches. +// graph, i.e. those that do not represent unwinds or false edges. // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and // `catch_unwind()` handlers. fn bcb_filtered_successors<'a, 'tcx>( - body: &'a mir::Body<'tcx>, - bb: BasicBlock, + terminator: &'a Terminator<'tcx>, ) -> impl Iterator + Captures<'a> + Captures<'tcx> { - let terminator = body[bb].terminator(); - let take_n_successors = match terminator.kind { // SwitchInt successors are never unwinds, so all of them should be traversed. TerminatorKind::SwitchInt { .. } => usize::MAX, @@ -364,10 +364,7 @@ fn bcb_filtered_successors<'a, 'tcx>( _ => 1, }; - terminator - .successors() - .take(take_n_successors) - .filter(move |&successor| body[successor].terminator().kind != TerminatorKind::Unreachable) + terminator.successors().take(take_n_successors) } /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the @@ -544,7 +541,7 @@ fn short_circuit_preorder<'a, 'tcx, F, Iter>( filtered_successors: F, ) -> impl Iterator + Captures<'a> + Captures<'tcx> where - F: Fn(&'a mir::Body<'tcx>, BasicBlock) -> Iter, + F: Fn(BasicBlock) -> Iter, Iter: Iterator, { let mut visited = BitSet::new_empty(body.basic_blocks.len()); @@ -556,7 +553,7 @@ where continue; } - worklist.extend(filtered_successors(body, bb)); + worklist.extend(filtered_successors(bb)); return Some(bb); } From c412cd4bc2241d7a67813b594cfc7e284e32c55b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 1 Jan 2024 21:52:43 +1100 Subject: [PATCH 123/297] coverage: Indicate whether a block's successors allow BCB chaining --- .../rustc_mir_transform/src/coverage/graph.rs | 88 +++++++++++++------ compiler/rustc_mir_transform/src/lib.rs | 1 + 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index b8e269b9103c..c418d86aa705 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -39,6 +39,7 @@ impl CoverageGraph { let bcb_data = &bcbs[bcb]; let mut bcb_successors = Vec::new(); for successor in bcb_filtered_successors(mir_body[bcb_data.last_bb()].terminator()) + .into_iter() .filter_map(|successor_bb| bb_to_bcb[successor_bb]) { if !seen[successor] { @@ -122,11 +123,8 @@ impl CoverageGraph { let term = mir_body[bb].terminator(); - match term.kind { - TerminatorKind::Return { .. } - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Yield { .. } - | TerminatorKind::SwitchInt { .. } => { + match bcb_filtered_successors(term) { + CoverageSuccessors::NotChainable(_) => { // The `bb` has more than one _outgoing_ edge, or exits the function. Save the // current sequence of `basic_blocks` gathered to this point, as a new // `BasicCoverageBlockData`. @@ -153,16 +151,7 @@ impl CoverageGraph { // for a coverage region containing the `Terminator` that began the panic. This // is as intended. (See Issue #78544 for a possible future option to support // coverage in test programs that panic.) - TerminatorKind::Goto { .. } - | TerminatorKind::UnwindResume - | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } - | TerminatorKind::Call { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::Assert { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => {} + CoverageSuccessors::Chainable(_) => {} } } @@ -349,22 +338,67 @@ impl BasicCoverageBlockData { } } +/// Holds the coverage-relevant successors of a basic block's terminator, and +/// indicates whether that block can potentially be combined into the same BCB +/// as its sole successor. +#[derive(Clone, Copy, Debug)] +enum CoverageSuccessors<'a> { + /// The terminator has exactly one straight-line successor, so its block can + /// potentially be combined into the same BCB as that successor. + Chainable(BasicBlock), + /// The block cannot be combined into the same BCB as its successor(s). + NotChainable(&'a [BasicBlock]), +} + +impl IntoIterator for CoverageSuccessors<'_> { + type Item = BasicBlock; + type IntoIter = impl DoubleEndedIterator; + + fn into_iter(self) -> Self::IntoIter { + match self { + Self::Chainable(bb) => Some(bb).into_iter().chain((&[]).iter().copied()), + Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()), + } + } +} + // Returns the subset of a block's successors that are relevant to the coverage // graph, i.e. those that do not represent unwinds or false edges. // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and // `catch_unwind()` handlers. -fn bcb_filtered_successors<'a, 'tcx>( - terminator: &'a Terminator<'tcx>, -) -> impl Iterator + Captures<'a> + Captures<'tcx> { - let take_n_successors = match terminator.kind { - // SwitchInt successors are never unwinds, so all of them should be traversed. - TerminatorKind::SwitchInt { .. } => usize::MAX, - // For all other kinds, return only the first successor (if any), ignoring any - // unwind successors. - _ => 1, - }; +fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> { + use TerminatorKind::*; + match terminator.kind { + // A switch terminator can have many coverage-relevant successors. + // (If there is exactly one successor, we still treat it as not chainable.) + SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()), - terminator.successors().take(take_n_successors) + // A yield terminator has exactly 1 successor, but should not be chained, + // because its resume edge has a different execution count. + Yield { ref resume, .. } => CoverageSuccessors::NotChainable(std::slice::from_ref(resume)), + + // These terminators have exactly one coverage-relevant successor, + // and can be chained into it. + Assert { target, .. } + | Drop { target, .. } + | FalseEdge { real_target: target, .. } + | FalseUnwind { real_target: target, .. } + | Goto { target } => CoverageSuccessors::Chainable(target), + + // These terminators can normally be chained, except when they have no + // successor because they are known to diverge. + Call { target: maybe_target, .. } | InlineAsm { destination: maybe_target, .. } => { + match maybe_target { + Some(target) => CoverageSuccessors::Chainable(target), + None => CoverageSuccessors::NotChainable(&[]), + } + } + + // These terminators have no coverage-relevant successors. + CoroutineDrop | Return | Unreachable | UnwindResume | UnwindTerminate(_) => { + CoverageSuccessors::NotChainable(&[]) + } + } } /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the @@ -542,7 +576,7 @@ fn short_circuit_preorder<'a, 'tcx, F, Iter>( ) -> impl Iterator + Captures<'a> + Captures<'tcx> where F: Fn(BasicBlock) -> Iter, - Iter: Iterator, + Iter: IntoIterator, { let mut visited = BitSet::new_empty(body.basic_blocks.len()); let mut worklist = vec![mir::START_BLOCK]; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ce9043ec2870..98076077b9a4 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -4,6 +4,7 @@ #![feature(box_patterns)] #![feature(cow_is_borrowed)] #![feature(decl_macro)] +#![feature(impl_trait_in_assoc_type)] #![feature(is_sorted)] #![feature(let_chains)] #![feature(map_try_insert)] From 229d0983b5c1765a50afe1a67853487bb6b145f4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 1 Jan 2024 22:46:45 +1100 Subject: [PATCH 124/297] coverage: Simplify the loop that combines blocks into BCBs The old loop had two separate places where it would flush the acumulated list of straight-line blocks into a new BCB. One occurred at the start of the loop body when the current block couldn't be chained into, and the other occurred at the end of the loop body when the current block couldn't be chained from. The latter check can be hoisted to the start of the loop body by making it examine the previous block (which has added itself to the list) instead of the current block. With that done, we can combine the two separate flushes into one flush with two possible trigger conditions. --- .../rustc_mir_transform/src/coverage/graph.rs | 90 +++++++------------ 1 file changed, 33 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index c418d86aa705..3e27a3e990a5 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -91,74 +91,41 @@ impl CoverageGraph { // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and // `catch_unwind()` handlers. + // Accumulates a chain of blocks that will be combined into one BCB. let mut basic_blocks = Vec::new(); + let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator()); for bb in short_circuit_preorder(mir_body, filtered_successors) .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable) { - if let Some(last) = basic_blocks.last() { - let predecessors = &mir_body.basic_blocks.predecessors()[bb]; - if predecessors.len() > 1 || !predecessors.contains(last) { - // The `bb` has more than one _incoming_ edge, and should start its own - // `BasicCoverageBlockData`. (Note, the `basic_blocks` vector does not yet - // include `bb`; it contains a sequence of one or more sequential basic_blocks - // with no intermediate branches in or out. Save these as a new - // `BasicCoverageBlockData` before starting the new one.) - Self::add_basic_coverage_block( - &mut bcbs, - &mut bb_to_bcb, - basic_blocks.split_off(0), - ); - debug!( - " because {}", - if predecessors.len() > 1 { - "predecessors.len() > 1".to_owned() - } else { - format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors) - } - ); - } + // If the previous block can't be chained into `bb`, flush the accumulated + // blocks into a new BCB, then start building the next chain. + if let Some(&prev) = basic_blocks.last() + && (!filtered_successors(prev).is_chainable() || { + // If `bb` has multiple predecessor blocks, or `prev` isn't + // one of its predecessors, we can't chain and must flush. + let predecessors = &mir_body.basic_blocks.predecessors()[bb]; + predecessors.len() > 1 || !predecessors.contains(&prev) + }) + { + debug!( + terminator_kind = ?mir_body[prev].terminator().kind, + predecessors = ?&mir_body.basic_blocks.predecessors()[bb], + "can't chain from {prev:?} to {bb:?}" + ); + Self::add_basic_coverage_block( + &mut bcbs, + &mut bb_to_bcb, + basic_blocks.split_off(0), + ); } + basic_blocks.push(bb); - - let term = mir_body[bb].terminator(); - - match bcb_filtered_successors(term) { - CoverageSuccessors::NotChainable(_) => { - // The `bb` has more than one _outgoing_ edge, or exits the function. Save the - // current sequence of `basic_blocks` gathered to this point, as a new - // `BasicCoverageBlockData`. - Self::add_basic_coverage_block( - &mut bcbs, - &mut bb_to_bcb, - basic_blocks.split_off(0), - ); - debug!(" because term.kind = {:?}", term.kind); - // Note that this condition is based on `TerminatorKind`, even though it - // theoretically boils down to `successors().len() != 1`; that is, either zero - // (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but - // since the BCB CFG ignores things like unwind branches (which exist in the - // `Terminator`s `successors()` list) checking the number of successors won't - // work. - } - - // The following `TerminatorKind`s are either not expected outside an unwind branch, - // or they should not (under normal circumstances) branch. Coverage graphs are - // simplified by assuring coverage results are accurate for program executions that - // don't panic. - // - // Programs that panic and unwind may record slightly inaccurate coverage results - // for a coverage region containing the `Terminator` that began the panic. This - // is as intended. (See Issue #78544 for a possible future option to support - // coverage in test programs that panic.) - CoverageSuccessors::Chainable(_) => {} - } } if !basic_blocks.is_empty() { - // process any remaining basic_blocks into a final `BasicCoverageBlockData` + debug!("flushing accumulated blocks into one last BCB"); Self::add_basic_coverage_block(&mut bcbs, &mut bb_to_bcb, basic_blocks.split_off(0)); - debug!(" because the end of the MIR CFG was reached while traversing"); } (bcbs, bb_to_bcb) @@ -350,6 +317,15 @@ enum CoverageSuccessors<'a> { NotChainable(&'a [BasicBlock]), } +impl CoverageSuccessors<'_> { + fn is_chainable(&self) -> bool { + match self { + Self::Chainable(_) => true, + Self::NotChainable(_) => false, + } + } +} + impl IntoIterator for CoverageSuccessors<'_> { type Item = BasicBlock; type IntoIter = impl DoubleEndedIterator; From 867950f8c6f4a11e388e3e3e75cdf5344e95e4e8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 2 Jan 2024 12:48:35 +1100 Subject: [PATCH 125/297] coverage: Move helper `add_basic_coverage_block` into a local closure This also switches from `split_off(0)` to `std::mem::take` when emptying the accumulated list of blocks, because `split_off(0)` handles capacity in a way that is unintuitive when used in a loop. --- .../rustc_mir_transform/src/coverage/graph.rs | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 3e27a3e990a5..9a3605b7a6a1 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -2,7 +2,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::graph::dominators::{self, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode}; use rustc_index::bit_set::BitSet; -use rustc_index::{IndexSlice, IndexVec}; +use rustc_index::IndexVec; use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind}; use std::cmp::Ordering; @@ -81,9 +81,23 @@ impl CoverageGraph { IndexVec>, ) { let num_basic_blocks = mir_body.basic_blocks.len(); - let mut bcbs = IndexVec::with_capacity(num_basic_blocks); + let mut bcbs = IndexVec::::with_capacity(num_basic_blocks); let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks); + let mut add_basic_coverage_block = |basic_blocks: &mut Vec| { + // Take the accumulated list of blocks, leaving the vector empty + // to be used by subsequent BCBs. + let basic_blocks = std::mem::take(basic_blocks); + + let bcb = bcbs.next_index(); + for &bb in basic_blocks.iter() { + bb_to_bcb[bb] = Some(bcb); + } + let bcb_data = BasicCoverageBlockData::from(basic_blocks); + debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); + bcbs.push(bcb_data); + }; + // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows // each block terminator's `successors()`. Coverage spans must map to actual source code, // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal @@ -113,11 +127,7 @@ impl CoverageGraph { predecessors = ?&mir_body.basic_blocks.predecessors()[bb], "can't chain from {prev:?} to {bb:?}" ); - Self::add_basic_coverage_block( - &mut bcbs, - &mut bb_to_bcb, - basic_blocks.split_off(0), - ); + add_basic_coverage_block(&mut basic_blocks); } basic_blocks.push(bb); @@ -125,26 +135,12 @@ impl CoverageGraph { if !basic_blocks.is_empty() { debug!("flushing accumulated blocks into one last BCB"); - Self::add_basic_coverage_block(&mut bcbs, &mut bb_to_bcb, basic_blocks.split_off(0)); + add_basic_coverage_block(&mut basic_blocks); } (bcbs, bb_to_bcb) } - fn add_basic_coverage_block( - bcbs: &mut IndexVec, - bb_to_bcb: &mut IndexSlice>, - basic_blocks: Vec, - ) { - let bcb = bcbs.next_index(); - for &bb in basic_blocks.iter() { - bb_to_bcb[bb] = Some(bcb); - } - let bcb_data = BasicCoverageBlockData::from(basic_blocks); - debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); - bcbs.push(bcb_data); - } - #[inline(always)] pub fn iter_enumerated( &self, From 5eae9452b6762a1347a3dec4f40c8ddc7789a868 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 1 Jan 2024 22:59:47 +1100 Subject: [PATCH 126/297] coverage: Simplify computing successors in the BCB graph --- .../rustc_mir_transform/src/coverage/graph.rs | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 9a3605b7a6a1..c6badbe78a49 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -1,4 +1,5 @@ use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::{self, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode}; use rustc_index::bit_set::BitSet; @@ -30,24 +31,16 @@ impl CoverageGraph { // `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so // de-duplication is required. This is done without reordering the successors. - let mut seen = IndexVec::from_elem(false, &bcbs); let successors = IndexVec::from_fn_n( |bcb| { - for b in seen.iter_mut() { - *b = false; - } - let bcb_data = &bcbs[bcb]; - let mut bcb_successors = Vec::new(); - for successor in bcb_filtered_successors(mir_body[bcb_data.last_bb()].terminator()) + let mut seen_bcbs = FxHashSet::default(); + let terminator = mir_body[bcbs[bcb].last_bb()].terminator(); + bcb_filtered_successors(terminator) .into_iter() .filter_map(|successor_bb| bb_to_bcb[successor_bb]) - { - if !seen[successor] { - seen[successor] = true; - bcb_successors.push(successor); - } - } - bcb_successors + // Remove duplicate successor BCBs, keeping only the first. + .filter(|&successor_bcb| seen_bcbs.insert(successor_bcb)) + .collect::>() }, bcbs.len(), ); From d71f535a6f39e82313b46ac3157c4ed9267a2e40 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 13 Jan 2024 13:11:56 +1100 Subject: [PATCH 127/297] Rework how diagnostic lints are stored. `Diagnostic::code` has the type `DiagnosticId`, which has `Error` and `Lint` variants. Plus `Diagnostic::is_lint` is a bool, which should be redundant w.r.t. `Diagnostic::code`. Seems simple. Except it's possible for a lint to have an error code, in which case its `code` field is recorded as `Error`, and `is_lint` is required to indicate that it's a lint. This is what happens with `derive(LintDiagnostic)` lints. Which means those lints don't have a lint name or a `has_future_breakage` field because those are stored in the `DiagnosticId::Lint`. It's all a bit messy and confused and seems unintentional. This commit: - removes `DiagnosticId`; - changes `Diagnostic::code` to `Option`, which means both errors and lints can straightforwardly have an error code; - changes `Diagnostic::is_lint` to `Option`, where `IsLint` is a new type containing a lint name and a `has_future_breakage` bool, so all lints can have those, error code or not. --- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- .../src/annotate_snippet_emitter_writer.rs | 12 ++--- compiler/rustc_errors/src/diagnostic.rs | 45 +++++++++---------- .../rustc_errors/src/diagnostic_builder.rs | 11 +++-- compiler/rustc_errors/src/emitter.rs | 17 ++++--- compiler/rustc_errors/src/json.rs | 37 +++++++-------- compiler/rustc_errors/src/lib.rs | 37 +++++++-------- .../src/check/compare_impl_item.rs | 4 +- .../src/structured_errors.rs | 4 +- .../missing_cast_for_variadic_arg.rs | 4 +- .../structured_errors/sized_unsized_cast.rs | 4 +- .../wrong_number_of_generic_args.rs | 6 +-- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 ++-- compiler/rustc_hir_typeck/src/lib.rs | 4 +- .../infer/error_reporting/need_type_info.rs | 4 +- .../src/diagnostics/diagnostic_builder.rs | 2 +- compiler/rustc_middle/src/lint.rs | 7 +-- compiler/rustc_mir_transform/src/errors.rs | 2 +- compiler/rustc_passes/src/entry.rs | 4 +- compiler/rustc_resolve/src/late.rs | 6 +-- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_session/src/parse.rs | 5 +-- compiler/rustc_session/src/session.rs | 7 ++- 24 files changed, 110 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index af1c65944460..5d497d4a1883 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -14,7 +14,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level}; +use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level}; use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>; struct Diagnostic { msgs: Vec<(DiagnosticMessage, Style)>, args: FxHashMap, rustc_errors::DiagnosticArgValue<'static>>, - code: Option, + code: Option, lvl: Level, } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 648c9118400e..f0699a56f98e 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; use crate::translation::{to_fluent_args, Translate}; use crate::{ - CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, - LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, + CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, + Level, MultiSpan, Style, SubDiagnostic, }; use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; @@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter { level: &Level, messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, msp: &MultiSpan, _children: &[SubDiagnostic], _suggestions: &[CodeSuggestion], @@ -181,11 +181,7 @@ impl AnnotateSnippetEmitter { let snippet = Snippet { title: Some(Annotation { label: Some(&message), - id: code.as_ref().map(|c| match c { - DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => { - val.as_str() - } - }), + id: code.as_deref(), annotation_type: annotation_type_for_level(*level), }), footer: vec![], diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 786aced5b4f9..4934bc2450c7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -104,7 +104,7 @@ pub struct Diagnostic { pub(crate) level: Level, pub messages: Vec<(DiagnosticMessage, Style)>, - pub code: Option, + pub code: Option, pub span: MultiSpan, pub children: Vec, pub suggestions: Result, SuggestionsDisabled>, @@ -115,9 +115,9 @@ pub struct Diagnostic { /// `span` if there is one. Otherwise, it is `DUMMY_SP`. pub sort_span: Span, - /// If diagnostic is from Lint, custom hash function ignores notes - /// otherwise hash is based on the all the fields - pub is_lint: bool, + /// If diagnostic is from Lint, custom hash function ignores children. + /// Otherwise hash is based on the all the fields. + pub is_lint: Option, /// With `-Ztrack_diagnostics` enabled, /// we print where in rustc this error was emitted. @@ -146,13 +146,11 @@ impl fmt::Display for DiagnosticLocation { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] -pub enum DiagnosticId { - Error(String), - Lint { - name: String, - /// Indicates whether this lint should show up in cargo's future breakage report. - has_future_breakage: bool, - }, +pub struct IsLint { + /// The lint name. + pub(crate) name: String, + /// Indicates whether this lint should show up in cargo's future breakage report. + has_future_breakage: bool, } /// A "sub"-diagnostic attached to a parent diagnostic. @@ -231,7 +229,7 @@ impl Diagnostic { suggestions: Ok(vec![]), args: Default::default(), sort_span: DUMMY_SP, - is_lint: false, + is_lint: None, emitted_at: DiagnosticLocation::caller(), } } @@ -288,16 +286,13 @@ impl Diagnostic { /// Indicates whether this diagnostic should show up in cargo's future breakage report. pub(crate) fn has_future_breakage(&self) -> bool { - match self.code { - Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, - _ => false, - } + matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. })) } pub(crate) fn is_force_warn(&self) -> bool { match self.level { Level::ForceWarning(_) => { - assert!(self.is_lint); + assert!(self.is_lint.is_some()); true } _ => false, @@ -893,12 +888,12 @@ impl Diagnostic { self } - pub fn is_lint(&mut self) -> &mut Self { - self.is_lint = true; + pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self { + self.is_lint = Some(IsLint { name, has_future_breakage }); self } - pub fn code(&mut self, s: DiagnosticId) -> &mut Self { + pub fn code(&mut self, s: String) -> &mut Self { self.code = Some(s); self } @@ -908,8 +903,8 @@ impl Diagnostic { self } - pub fn get_code(&self) -> Option { - self.code.clone() + pub fn get_code(&self) -> Option<&str> { + self.code.as_deref() } pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { @@ -995,7 +990,8 @@ impl Diagnostic { &Level, &[(DiagnosticMessage, Style)], Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>, - &Option, + &Option, + &Option, &MultiSpan, &Result, SuggestionsDisabled>, Option<&[SubDiagnostic]>, @@ -1005,9 +1001,10 @@ impl Diagnostic { &self.messages, self.args().collect(), &self.code, + &self.is_lint, &self.span, &self.suggestions, - (if self.is_lint { None } else { Some(&self.children) }), + (if self.is_lint.is_some() { None } else { Some(&self.children) }), ) } } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 93b2dd61b059..87e2d295c7f4 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,8 +1,8 @@ use crate::diagnostic::IntoDiagnosticArg; use crate::{DiagCtxt, Level, MultiSpan, StashKey}; use crate::{ - Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, - ExplicitBug, SubdiagnosticMessage, + Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug, + SubdiagnosticMessage, }; use rustc_lint_defs::Applicability; use rustc_span::source_map::Spanned; @@ -395,8 +395,11 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { forward!((span, with_span)( sp: impl Into, )); + forward!((is_lint, with_is_lint)( + name: String, has_future_breakage: bool, + )); forward!((code, with_code)( - s: DiagnosticId, + s: String, )); forward!((arg, with_arg)( name: impl Into>, arg: impl IntoDiagnosticArg, @@ -443,5 +446,5 @@ macro_rules! struct_span_code_err { #[macro_export] macro_rules! error_code { - ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; + ($code:ident) => {{ stringify!($code).to_owned() }}; } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 987832e6937b..23efdaea0ebb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -16,9 +16,9 @@ use crate::snippet::{ use crate::styled_buffer::StyledBuffer; use crate::translation::{to_fluent_args, Translate}; use crate::{ - diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticId, - DiagnosticMessage, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, - SubstitutionHighlight, SuggestionStyle, TerminalUrl, + diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage, + FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, + SuggestionStyle, TerminalUrl, }; use rustc_lint_defs::pluralize; @@ -1309,7 +1309,7 @@ impl HumanEmitter { msp: &MultiSpan, msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, level: &Level, max_line_num_len: usize, is_secondary: bool, @@ -1336,14 +1336,13 @@ impl HumanEmitter { buffer.append(0, level.to_str(), Style::Level(*level)); label_width += level.to_str().len(); } - // only render error codes, not lint codes - if let Some(DiagnosticId::Error(ref code)) = *code { + if let Some(code) = code { buffer.append(0, "[", Style::Level(*level)); let code = if let TerminalUrl::Yes = self.terminal_url { let path = "https://doc.rust-lang.org/error_codes"; - format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07") + Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")) } else { - code.clone() + Cow::Borrowed(code) }; buffer.append(0, &code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); @@ -2077,7 +2076,7 @@ impl HumanEmitter { level: &Level, messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, span: &MultiSpan, children: &[SubDiagnostic], suggestions: &[CodeSuggestion], diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 87bf9c234564..51b064f4c617 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -15,10 +15,9 @@ use termcolor::{ColorSpec, WriteColor}; use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType}; use crate::registry::Registry; use crate::translation::{to_fluent_args, Translate}; -use crate::DiagnosticId; use crate::{ - CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic, - TerminalUrl, + diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, + SubDiagnostic, TerminalUrl, }; use rustc_lint_defs::Applicability; @@ -301,7 +300,8 @@ struct DiagnosticSpanMacroExpansion { #[derive(Serialize)] struct DiagnosticCode { - /// The code itself. + /// The error code (e.g. "E1234"), if the diagnostic has one. Or the lint + /// name, if it's a lint without an error code. code: String, /// An explanation for the code. explanation: Option<&'static str>, @@ -399,9 +399,21 @@ impl Diagnostic { let output = String::from_utf8(output).unwrap(); let translated_message = je.translate_messages(&diag.messages, &args); + + let code = if let Some(code) = &diag.code { + Some(DiagnosticCode { + code: code.to_string(), + explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(), + }) + } else if let Some(IsLint { name, .. }) = &diag.is_lint { + Some(DiagnosticCode { code: name.to_string(), explanation: None }) + } else { + None + }; + Diagnostic { message: translated_message.to_string(), - code: DiagnosticCode::map_opt_string(diag.code.clone(), je), + code, level: diag.level.to_str(), spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), children: diag @@ -592,18 +604,3 @@ impl DiagnosticSpanLine { .unwrap_or_else(|_| vec![]) } } - -impl DiagnosticCode { - fn map_opt_string(s: Option, je: &JsonEmitter) -> Option { - s.map(|s| { - let s = match s { - DiagnosticId::Error(s) => s, - DiagnosticId::Lint { name, .. } => name, - }; - let je_result = - je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap(); - - DiagnosticCode { code: s, explanation: je_result.ok() } - }) - } -} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 63391a0faa6b..141547b537de 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -30,7 +30,7 @@ extern crate tracing; extern crate self as rustc_errors; pub use diagnostic::{ - AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, + AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; pub use diagnostic_builder::{ @@ -442,13 +442,13 @@ struct DiagCtxtInner { /// This is used for the `good_path_delayed_bugs` check. suppressed_expected_diag: bool, - /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid + /// This set contains the code of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which /// would be unnecessary repetition. - taught_diagnostics: FxHashSet, + taught_diagnostics: FxHashSet, /// Used to suggest rustc --explain `` - emitted_diagnostic_codes: FxIndexSet, + emitted_diagnostic_codes: FxIndexSet, /// This set contains a hash of every diagnostic that has been emitted by /// this `DiagCtxt`. These hashes is used to avoid emitting the same error @@ -676,7 +676,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if diag.is_lint { + if diag.is_lint.is_some() { inner.lint_err_count += 1; } else { inner.err_count += 1; @@ -695,7 +695,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if diag.is_lint { + if diag.is_lint.is_some() { inner.lint_err_count -= 1; } else { inner.err_count -= 1; @@ -715,9 +715,7 @@ impl DiagCtxt { /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` + /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_warn( @@ -730,9 +728,7 @@ impl DiagCtxt { /// Construct a builder at the `Warning` level with the `msg`. /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` + /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { @@ -1011,11 +1007,12 @@ impl DiagCtxt { let mut error_codes = inner .emitted_diagnostic_codes .iter() - .filter_map(|x| match &x { - DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => { - Some(s.clone()) + .filter_map(|code| { + if registry.try_find_description(code).is_ok().clone() { + Some(code.clone()) + } else { + None } - _ => None, }) .collect::>(); if !error_codes.is_empty() { @@ -1058,8 +1055,8 @@ impl DiagCtxt { /// /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. - pub fn must_teach(&self, code: &DiagnosticId) -> bool { - self.inner.borrow_mut().taught_diagnostics.insert(code.clone()) + pub fn must_teach(&self, code: &str) -> bool { + self.inner.borrow_mut().taught_diagnostics.insert(code.to_string()) } pub fn force_print_diagnostic(&self, db: Diagnostic) { @@ -1231,7 +1228,7 @@ impl DiagCtxtInner { for diag in diags { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if diag.is_lint { + if diag.is_lint.is_some() { self.lint_err_count -= 1; } else { self.err_count -= 1; @@ -1363,7 +1360,7 @@ impl DiagCtxtInner { self.has_printed = true; } if diagnostic.is_error() { - if diagnostic.is_lint { + if diagnostic.is_lint.is_some() { self.lint_err_count += 1; } else { self.err_count += 1; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 469e7a6a13c5..774feb94f7dc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2,7 +2,7 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; @@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>( kind = kind, ), ); - err.code(DiagnosticId::Error("E0049".into())); + err.code("E0049".into()); let msg = format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),); diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs index 04d04304e70f..b061d6371388 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors.rs @@ -6,13 +6,13 @@ pub use self::{ missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*, }; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::DiagnosticBuilder; use rustc_session::Session; pub trait StructuredDiagnostic<'tcx> { fn session(&self) -> &Session; - fn code(&self) -> DiagnosticId; + fn code(&self) -> String; fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { let err = self.diagnostic_common(); diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs index 634904e32715..6f4435db4114 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { self.sess } - fn code(&self) -> DiagnosticId { + fn code(&self) -> String { rustc_errors::error_code!(E0617) } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs index c68d74969a54..19cac4a38aaa 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { self.sess } - fn code(&self) -> DiagnosticId { + fn code(&self) -> String { rustc_errors::error_code!(E0607) } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 6657e3fd872f..ba81e7f1f816 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -1,7 +1,5 @@ use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, MultiSpan, -}; +use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; use rustc_session::Session; @@ -1107,7 +1105,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { self.tcx.sess } - fn code(&self) -> DiagnosticId { + fn code(&self) -> String { rustc_errors::error_code!(E0107) } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index af47455c16df..ac8701a33d44 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -26,7 +26,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, - DiagnosticId, ErrorGuaranteed, StashKey, + ErrorGuaranteed, StashKey, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -941,7 +941,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment"); - err.code(DiagnosticId::Error(err_code.into())); + err.code(err_code.into()); err.span_label(lhs.span, "cannot assign to this expression"); self.comes_from_while_condition(lhs.hir_id, |expr| { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8cd5ed3494b1..3fe42d1495a5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -11,9 +11,7 @@ use crate::{ }; use rustc_ast as ast; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan, StashKey, -}; +use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -678,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pluralize!("was", provided_args.len()) ), ); - err.code(DiagnosticId::Error(err_code.to_owned())); + err.code(err_code.to_owned()); err.multipart_suggestion_verbose( "wrap these arguments in parentheses to construct a tuple", vec![ @@ -828,7 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pluralize!("was", provided_args.len()) ), ) - .with_code(DiagnosticId::Error(err_code.to_owned())) + .with_code(err_code.to_owned()) }; // As we encounter issues, keep track of what we want to provide for the suggestion diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 36dd06d944c4..67c35d717a1e 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::RawTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{struct_span_code_err, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{struct_span_code_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -369,7 +369,7 @@ fn report_unexpected_variant_res( let err = tcx .dcx() .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`")) - .with_code(DiagnosticId::Error(err_code.into())); + .with_code(err_code.into()); match res { Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => { let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 4aefadf590dd..e85c940f1b55 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -41,8 +41,8 @@ pub enum TypeAnnotationNeeded { E0284, } -impl Into for TypeAnnotationNeeded { - fn into(self) -> rustc_errors::DiagnosticId { +impl Into for TypeAnnotationNeeded { + fn into(self) -> String { match self { Self::E0282 => rustc_errors::error_code!(E0282), Self::E0283 => rustc_errors::error_code!(E0283), diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index fb908fe2db15..0b7ecff8148b 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -211,7 +211,7 @@ impl DiagnosticDeriveVariantBuilder { let code = nested.parse::()?; tokens.extend(quote! { - diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + diag.code(#code.to_string()); }); } else { span_err(path.span().unwrap(), "unknown argument") diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index c5e4dfaf19ee..4ab16cf19ba9 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan}; +use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, @@ -322,8 +322,6 @@ pub fn struct_lint_level( err.span(span); } - err.is_lint(); - // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate // can do about it. We probably want to skip the lint entirely. @@ -351,8 +349,7 @@ pub fn struct_lint_level( // suppressed the lint due to macros. err.primary_message(msg); - let name = lint.name_lower(); - err.code(DiagnosticId::Lint { name, has_future_breakage }); + err.is_lint(lint.name_lower(), has_future_breakage); // Lint diagnostics that are covered by the expect level will not be emitted outside // the compiler. It is therefore not necessary to add any information for the user. diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 446f13feff08..2ee660ddc9be 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); - diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); + diag.code("E0133".to_string()); diag.span(self.span); diag.span_label(self.span, self.details.label()); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index a9d0e0d2dd3e..25ca685cbfad 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { Default::default() }); let main_def_opt = tcx.resolutions(()).main_def; - let diagnostic_id = error_code!(E0601); - let add_teach_note = tcx.sess.teach(&diagnostic_id); + let code = error_code!(E0601); + let add_teach_note = tcx.sess.teach(&code); // The file may be empty, which leads to the diagnostic machinery not emitting this // note. This is a relatively simple way to detect that case and emit a span-less // note instead. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b9e603a49926..ccf90fbff22d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; +use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -531,7 +531,7 @@ impl<'a> PathSource<'a> { } } - fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId { + fn error_code(self, has_unexpected_resolution: bool) -> String { use rustc_errors::error_code; match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => error_code!(E0404), @@ -3759,7 +3759,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { swap(&mut err.span, &mut parent_err.span); err.children = take(&mut parent_err.children); err.sort_span = parent_err.sort_span; - err.is_lint = parent_err.is_lint; + err.is_lint = parent_err.is_lint.clone(); // merge the parent's suggestions with the typo suggestions fn append_result(res1: &mut Result, E>, res2: Result, E>) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0adea65ee58e..196f28d878dd 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -257,7 +257,7 @@ enum ResolutionError<'a> { kind: &'static str, trait_path: String, trait_item_span: Span, - code: rustc_errors::DiagnosticId, + code: String, }, /// Error E0201: multiple impl items for the same trait item. TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index c629c9884c8e..16036e5be38c 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -15,8 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::{ - fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - MultiSpan, StashKey, + fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -148,7 +147,7 @@ pub fn feature_warn_issue( // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; let future_incompatible = lint.future_incompatible.as_ref().unwrap(); - err.code(DiagnosticId::Lint { name: lint.name_lower(), has_future_breakage: false }); + err.is_lint(lint.name_lower(), /* has_future_breakage */ false); err.warn(lint.desc); err.note(format!("for more information, see {}", future_incompatible.reference)); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1c3d5a3cb881..3f6c70a18d39 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -20,9 +20,8 @@ use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ - error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId, - DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, - LazyFallbackBundle, TerminalUrl, + error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, + ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -906,7 +905,7 @@ impl Session { CodegenUnits::Default(16) } - pub fn teach(&self, code: &DiagnosticId) -> bool { + pub fn teach(&self, code: &str) -> bool { self.opts.unstable_opts.teach && self.dcx().must_teach(code) } From 5788f3d350e0367cd5bbb192b8780429949844de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 14 Jan 2024 13:55:18 +0100 Subject: [PATCH 128/297] Remove Zulip rustdoc nomination alert --- triagebot.toml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 1e1db2d16632..2b818c0a990d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -389,15 +389,6 @@ message_on_remove = "Issue #{number}'s prioritization request has been removed." message_on_close = "Issue #{number} has been closed while requested for prioritization." message_on_reopen = "Issue #{number} has been reopened." -[notify-zulip."T-rustdoc"] -required_labels = ["I-nominated"] -zulip_stream = 266220 # #rustdoc -topic = "nominated: #{number}" -message_on_add = """\ -@*T-rustdoc* issue #{number} "{title}" has been nominated for `T-rustdoc` discussion. -""" -message_on_remove = "Issue #{number}'s nomination request has been removed." - [notify-zulip."I-types-nominated"] zulip_stream = 326866 # #T-types/nominated topic = "#{number}: {title}" From c6f83b8ff6b4e0fa98713b720ff48d67efe8d932 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 14 Jan 2024 12:57:13 +0000 Subject: [PATCH 129/297] Inline 2 functions that appear in dep-graph profiles. --- compiler/rustc_index_macros/src/newtype.rs | 1 + compiler/rustc_query_system/src/dep_graph/serialized.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index df1318c835e2..ede8416125d6 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -263,6 +263,7 @@ impl Parse for Newtype { impl std::ops::Add for #name { type Output = Self; + #[inline] fn add(self, other: usize) -> Self { Self::from_usize(self.index() + other) } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 504763f6cdb3..f6f6aa07cb3f 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -169,6 +169,7 @@ impl EdgeHeader { } } +#[inline] fn mask(bits: usize) -> usize { usize::MAX >> ((std::mem::size_of::() * 8) - bits) } From 0529ccf341516b098554ccc82a77553159316c2a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 14 Jan 2024 13:22:43 +0000 Subject: [PATCH 130/297] Fix `allow_internal_unstable` for `(min_)specialization` --- .../src/traits/specialize/mod.rs | 20 ++++++++++++++++--- .../specialization/allow_internal_unstable.rs | 18 +++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 tests/ui/specialization/allow_internal_unstable.rs diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 200d022c80c6..d3862451a01a 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; -use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP}; use super::util; use super::SelectionContext; @@ -144,8 +144,22 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // taking advantage of upstream ones. let features = tcx.features(); let specialization_enabled = features.specialization || features.min_specialization; - if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) { - return false; + if !specialization_enabled && impl1_def_id.is_local() { + let span = tcx.def_span(impl1_def_id); + if !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + return false; + } + } + + if !specialization_enabled && impl2_def_id.is_local() { + let span = tcx.def_span(impl2_def_id); + if !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + return false; + } } // We determine whether there's a subset relationship by: diff --git a/tests/ui/specialization/allow_internal_unstable.rs b/tests/ui/specialization/allow_internal_unstable.rs new file mode 100644 index 000000000000..317782b7b728 --- /dev/null +++ b/tests/ui/specialization/allow_internal_unstable.rs @@ -0,0 +1,18 @@ +// check-pass +// test for #119950 +// compile-flags: --crate-type lib + +#![allow(internal_features)] +#![feature(allow_internal_unstable)] + +#[allow_internal_unstable(min_specialization)] +macro_rules! test { + () => { + struct T(U); + trait Tr {} + impl Tr for T {} + impl Tr for T {} + } +} + +test! {} From a596159dca825a02270335d4b90b8fcb128b2d11 Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Thu, 11 Jan 2024 15:55:50 -0800 Subject: [PATCH 131/297] std: Doc blocking behavior of LazyLock methods --- library/std/src/sync/lazy_lock.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 3598598cfa02..27b59cfc8c24 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -20,6 +20,9 @@ union Data { /// A value which is initialized on the first access. /// /// This type is a thread-safe [`LazyCell`], and can be used in statics. +/// Since initialization may be called from multiple threads, any +/// dereferencing call will block the calling thread if another +/// initialization routine is currently running. /// /// [`LazyCell`]: crate::cell::LazyCell /// @@ -81,8 +84,7 @@ pub struct LazyLock T> { } impl T> LazyLock { - /// Creates a new lazy value with the given initializing - /// function. + /// Creates a new lazy value with the given initializing function. #[inline] #[unstable(feature = "lazy_cell", issue = "109736")] pub const fn new(f: F) -> LazyLock { @@ -134,9 +136,11 @@ impl T> LazyLock { } } - /// Forces the evaluation of this lazy value and - /// returns a reference to result. This is equivalent - /// to the `Deref` impl, but is explicit. + /// Forces the evaluation of this lazy value and returns a reference to + /// result. This is equivalent to the `Deref` impl, but is explicit. + /// + /// This method will block the calling thread if another initialization + /// routine is currently running. /// /// # Examples /// @@ -204,6 +208,11 @@ impl Drop for LazyLock { impl T> Deref for LazyLock { type Target = T; + /// Dereferences the value. + /// + /// This method will block the calling thread if another initialization + /// routine is currently running. + /// #[inline] fn deref(&self) -> &T { LazyLock::force(self) @@ -232,7 +241,7 @@ impl fmt::Debug for LazyLock { } // We never create a `&F` from a `&LazyLock` so it is fine -// to not impl `Sync` for `F` +// to not impl `Sync` for `F`. #[unstable(feature = "lazy_cell", issue = "109736")] unsafe impl Sync for LazyLock {} // auto-derived `Send` impl is OK. From eb63d3a49d7681d6ede7dc1bcac7bb1125ff7132 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 14 Jan 2024 13:48:58 +0000 Subject: [PATCH 132/297] `allow_internal_unstable(min_specialization)` on `newtype_index` --- compiler/rustc_index_macros/src/lib.rs | 3 ++ .../src/traits/specialize/mod.rs | 32 +++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs index ac374a41eb6f..b0bf4554ba88 100644 --- a/compiler/rustc_index_macros/src/lib.rs +++ b/compiler/rustc_index_macros/src/lib.rs @@ -36,6 +36,9 @@ mod newtype; feature = "nightly", allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq) )] +// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped, +// and the corresponding one on SpecOptionPartialEq +#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))] pub fn newtype_index(input: TokenStream) -> TokenStream { newtype::newtype(input) } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index d3862451a01a..b37d9714ddd8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -142,23 +142,29 @@ pub fn translate_args_with_cause<'tcx>( pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool { // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. + // If specialization is enabled for this crate then no extra checks are needed. + // If it's not, and either of the `impl`s is local to this crate, then this definitely + // isn't specializing - unless specialization is enabled for the `impl` span, + // e.g. if it comes from an `allow_internal_unstable` macro let features = tcx.features(); let specialization_enabled = features.specialization || features.min_specialization; - if !specialization_enabled && impl1_def_id.is_local() { - let span = tcx.def_span(impl1_def_id); - if !span.allows_unstable(sym::specialization) - && !span.allows_unstable(sym::min_specialization) - { - return false; + if !specialization_enabled { + if impl1_def_id.is_local() { + let span = tcx.def_span(impl1_def_id); + if !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + return false; + } } - } - if !specialization_enabled && impl2_def_id.is_local() { - let span = tcx.def_span(impl2_def_id); - if !span.allows_unstable(sym::specialization) - && !span.allows_unstable(sym::min_specialization) - { - return false; + if impl2_def_id.is_local() { + let span = tcx.def_span(impl2_def_id); + if !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + return false; + } } } From 6f98a6cc8015cb094dc0c6acb330eb71ef75cb64 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 18:29:01 +0000 Subject: [PATCH 133/297] Simplify closure_env_ty and closure_env_param --- .../rustc_borrowck/src/universal_regions.rs | 6 +- compiler/rustc_middle/src/ty/util.rs | 14 ++-- compiler/rustc_mir_build/src/thir/cx/mod.rs | 68 +++++++------------ compiler/rustc_ty_utils/src/abi.rs | 6 +- 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index addb41ff5fc8..ae8a135f0905 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -668,7 +668,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { kind: ty::BrEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); - let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); + let closure_ty = tcx.closure_env_ty( + Ty::new_closure(tcx, def_id, args), + args.as_closure().kind(), + env_region, + ); // The "inputs" of the closure in the // signature appear as a tuple. The MIR side diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7285cdb830e3..3a50ec2251a0 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -604,19 +604,15 @@ impl<'tcx> TyCtxt<'tcx> { /// wrapped in a binder. pub fn closure_env_ty( self, - closure_def_id: DefId, - closure_args: GenericArgsRef<'tcx>, + closure_ty: Ty<'tcx>, + closure_kind: ty::ClosureKind, env_region: ty::Region<'tcx>, - ) -> Option> { - let closure_ty = Ty::new_closure(self, closure_def_id, closure_args); - let closure_kind_ty = closure_args.as_closure().kind_ty(); - let closure_kind = closure_kind_ty.to_opt_closure_kind()?; - let env_ty = match closure_kind { + ) -> Ty<'tcx> { + match closure_kind { ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty), ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty), ty::ClosureKind::FnOnce => closure_ty, - }; - Some(env_ty) + } } /// Returns `true` if the node pointed to by `def_id` is a `static` item. diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index fa3dd2afa85d..5d0bb3954ccc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -117,50 +117,32 @@ impl<'tcx> Cx<'tcx> { pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) } - fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option> { - match self.tcx.def_kind(owner_def) { - DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => { - let coroutine_ty = self.typeck_results.node_type(owner_id); - let coroutine_param = Param { - ty: coroutine_ty, - pat: None, - ty_span: None, - self_kind: None, - hir_id: None, - }; - Some(coroutine_param) - } - DefKind::Closure => { - let closure_ty = self.typeck_results.node_type(owner_id); - - let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else { - bug!("closure expr does not have closure type: {:?}", closure_ty); - }; - - let bound_vars = - self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]); - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BrEnv, - }; - let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br); - let closure_env_ty = - self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap(); - let liberated_closure_env_ty = self.tcx.instantiate_bound_regions_with_erased( - ty::Binder::bind_with_vars(closure_env_ty, bound_vars), - ); - let env_param = Param { - ty: liberated_closure_env_ty, - pat: None, - ty_span: None, - self_kind: None, - hir_id: None, - }; - - Some(env_param) - } - _ => None, + fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option> { + if self.tcx.def_kind(owner_def) != DefKind::Closure { + return None; } + + let closure_ty = self.typeck_results.node_type(expr_id); + Some(match *closure_ty.kind() { + ty::Coroutine(..) => { + Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None } + } + ty::Closure(_, closure_args) => { + let closure_env_ty = self.tcx.closure_env_ty( + closure_ty, + closure_args.as_closure().kind(), + self.tcx.lifetimes.re_erased, + ); + Param { + ty: closure_env_ty, + pat: None, + ty_span: None, + self_kind: None, + hir_id: None, + } + } + _ => bug!("unexpected closure type: {closure_ty}"), + }) } fn explicit_params<'a>( diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 2772831e731e..11f7972ceee1 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -83,7 +83,11 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); - let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); + let env_ty = tcx.closure_env_ty( + Ty::new_closure(tcx, def_id, args), + args.as_closure().kind(), + env_region, + ); let sig = sig.skip_binder(); ty::Binder::bind_with_vars( From c5cb87cf0cf9f798869c098288304e132b0e53a1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 19:59:10 +0000 Subject: [PATCH 134/297] Closure body was being built incorrectly on error... --- compiler/rustc_mir_build/src/build/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index b8d08319422d..7b987288f80c 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,5 +1,6 @@ use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; +use itertools::Itertools; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_ast::attr; @@ -654,7 +655,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ty::ClosureKind::FnOnce => closure_ty, }; ( - [self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), + [self_ty].into_iter().chain(sig.inputs()[0].tuple_fields()).collect(), sig.output(), None, ) From c811662fb0e3eab4ee88134551cf2605327705f6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 20:01:12 +0000 Subject: [PATCH 135/297] Use zip_eq to enforce that things being zipped have equal sizes --- Cargo.lock | 3 +++ .../rustc_borrowck/src/type_check/input_output.rs | 13 ++++++++++--- compiler/rustc_hir_analysis/Cargo.toml | 1 + compiler/rustc_hir_analysis/src/variance/mod.rs | 3 ++- compiler/rustc_hir_typeck/Cargo.toml | 1 + compiler/rustc_hir_typeck/src/autoderef.rs | 9 +++++++-- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 3 ++- compiler/rustc_mir_build/Cargo.toml | 1 + compiler/rustc_mir_build/src/build/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 ++- compiler/rustc_ty_utils/src/layout.rs | 4 +++- 11 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b9dd05398f4..7bbf8a526bcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3868,6 +3868,7 @@ dependencies = [ name = "rustc_hir_analysis" version = "0.0.0" dependencies = [ + "itertools", "rustc_arena", "rustc_ast", "rustc_attr", @@ -3906,6 +3907,7 @@ dependencies = [ name = "rustc_hir_typeck" version = "0.0.0" dependencies = [ + "itertools", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -4189,6 +4191,7 @@ name = "rustc_mir_build" version = "0.0.0" dependencies = [ "either", + "itertools", "rustc_apfloat", "rustc_arena", "rustc_ast", diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 61b6bef3b87b..59518f68ab14 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,6 +7,7 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use itertools::Itertools; use rustc_infer::infer::BoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; @@ -39,9 +40,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_provided_sig, ); - for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip( - // In MIR, closure args begin with an implicit `self`. Skip it! - body.args_iter().skip(1).map(|local| &body.local_decls[local]), + let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id()) + && user_provided_sig.inputs().is_empty(); + + for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq( + // In MIR, closure args begin with an implicit `self`. + // Also, coroutines have a resume type which may be implicitly `()`. + body.args_iter() + .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 }) + .map(|local| &body.local_decls[local]), ) { self.ascribe_user_type_skip_wf( arg_decl.ty, diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index b5ebc1fab765..648b569a217f 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -9,6 +9,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +itertools = "0.11" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 410706110c96..7d145ea1f23a 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -3,6 +3,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html +use itertools::Itertools; use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -91,7 +92,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow { if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) { let child_variances = self.tcx.variances_of(def_id); - for (a, v) in args.iter().zip(child_variances) { + for (a, v) in args.iter().zip_eq(child_variances) { if *v != ty::Bivariant { a.visit_with(self)?; } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index b0c60304424a..975f93756427 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 7873257c4e3d..2bb7caea3c43 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -2,6 +2,7 @@ use super::method::MethodCallee; use super::{FnCtxt, PlaceOp}; +use itertools::Itertools; use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; use rustc_infer::infer::InferOk; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; @@ -32,8 +33,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec>> { - let mut obligations = vec![]; let steps = autoderef.steps(); + if steps.is_empty() { + return InferOk { obligations: vec![], value: vec![] }; + } + + let mut obligations = vec![]; let targets = steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); let steps: Vec<_> = steps @@ -54,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }) - .zip(targets) + .zip_eq(targets) .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target }) .collect(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index da6f2042c110..5ece2fcaa80d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -8,6 +8,7 @@ use crate::{errors, Expectation::*}; use crate::{ struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy, TupleArgumentsFlag, }; +use itertools::Itertools; use rustc_ast as ast; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ @@ -420,7 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_input_tys .iter() .copied() - .zip(expected_input_tys.iter().copied()) + .zip_eq(expected_input_tys.iter().copied()) .map(|vars| self.resolve_vars_if_possible(vars)), ); diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 6d681dc295ef..d71f71213220 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" +itertools = "0.11" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 7b987288f80c..714c5f2686eb 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -836,7 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.upvars = tcx .closure_captures(self.def_id) .iter() - .zip(capture_tys) + .zip_eq(capture_tys) .enumerate() .map(|(i, (captured_place, ty))| { let name = captured_place.to_symbol(); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 78d72b302841..22094c112fc1 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -2,6 +2,7 @@ use crate::errors; use crate::thir::cx::region::Scope; use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; +use itertools::Itertools; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -565,7 +566,7 @@ impl<'tcx> Cx<'tcx> { .tcx .closure_captures(def_id) .iter() - .zip(args.upvar_tys()) + .zip_eq(args.upvar_tys()) .map(|(captured_place, ty)| { let upvars = self.capture_upvar(expr, captured_place, ty); self.thir.exprs.push(upvars) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index db89fba2a893..8b20ad05727a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1057,6 +1057,8 @@ fn variant_info_for_coroutine<'tcx>( def_id: DefId, args: ty::GenericArgsRef<'tcx>, ) -> (Vec, Option) { + use itertools::Itertools; + let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else { return (vec![], None); }; @@ -1069,7 +1071,7 @@ fn variant_info_for_coroutine<'tcx>( .as_coroutine() .upvar_tys() .iter() - .zip(upvar_names) + .zip_eq(upvar_names) .enumerate() .map(|(field_idx, (_, name))| { let field_layout = layout.field(cx, field_idx); From 56df3bb70d808d535e46f1c017bafeccbbf1cb6d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:47:10 -0800 Subject: [PATCH 136/297] Move nonzero_integers macro call to bottom of module This way all the other macros defined in this module, such as nonzero_leading_trailing_zeros, are available to call within the expansion of nonzero_integers. (Macros defined by macro_rules cannot be called from the same module above the location of the macro_rules.) In this commit the ability to call things like nonzero_leading_trailing_zeros is not immediately used, but later commits in this stack will be consolidating the entire API of NonZeroT to be generated through nonzero_integers, and will need to make use of some of the other macros to do that. --- library/core/src/num/nonzero.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 2df38ab5848a..1de9226f47f2 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -190,21 +190,6 @@ macro_rules! nonzero_integers { } } -nonzero_integers! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); -} - macro_rules! from_str_radix_nzint_impl { ($($t:ty)*) => {$( #[stable(feature = "nonzero_parse", since = "1.35.0")] @@ -1396,3 +1381,18 @@ nonzero_bits! { NonZeroUsize(usize); NonZeroIsize(isize); } + +nonzero_integers! { + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); +} From 54cb822563dc7ffd4838c23d04f7c1ad6c3e90cd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:21:50 -0800 Subject: [PATCH 137/297] Define only a single NonZero type per macro call Later in this stack, as the nonzero_integers macro is going to be responsible for producing a larger fraction of the API for the NonZero integer types, it will need to receive a number of additional arguments beyond the ones currently seen here. Additional arguments, especially named arguments across multiple lines, will turn out clearer if everything in one macro call is for the same NonZero type. This commit adopts a similar arrangement to what we do for generating the API of the integer primitives (`impl u8` etc), which also generate a single type's API per top-level macro call, rather than generating all 12 impl blocks for the 12 types from one macro call. --- library/core/src/num/nonzero.rs | 45 ++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1de9226f47f2..6b113d57f25f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -22,9 +22,10 @@ macro_rules! impl_nonzero_fmt { } } -macro_rules! nonzero_integers { - ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => { - $( +macro_rules! nonzero_integer { + ( + #[$stability:meta] #[$const_new_unchecked_stability:meta] $Ty:ident($Int:ty); + ) => { /// An integer that is known not to equal zero. /// /// This enables some memory layout optimization. @@ -186,8 +187,7 @@ macro_rules! nonzero_integers { impl_nonzero_fmt! { #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } - )+ - } + }; } macro_rules! from_str_radix_nzint_impl { @@ -1382,17 +1382,50 @@ nonzero_bits! { NonZeroIsize(isize); } -nonzero_integers! { +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } From 9196d2a552c28144252730bcf8a8e58878f625d4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:44:02 -0800 Subject: [PATCH 138/297] Unindent nonzero_integer macro body --- library/core/src/num/nonzero.rs | 286 ++++++++++++++++---------------- 1 file changed, 143 insertions(+), 143 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b113d57f25f..f7098bcf6e9c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,167 +26,167 @@ macro_rules! nonzero_integer { ( #[$stability:meta] #[$const_new_unchecked_stability:meta] $Ty:ident($Int:ty); ) => { - /// An integer that is known not to equal zero. + /// An integer that is known not to equal zero. + /// + /// This enables some memory layout optimization. + #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// + /// ```rust + /// use std::mem::size_of; + #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] + /// ``` + /// + /// # Layout + /// + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] + /// with the exception that `0` is not a valid instance. + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] + /// including in FFI. + /// + /// Thanks to the [null pointer optimization], + #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] + /// are guaranteed to have the same size and alignment: + /// + /// ``` + /// # use std::mem::{size_of, align_of}; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::>());")] + #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] + /// ``` + /// + /// [null pointer optimization]: crate::option#representation + #[$stability] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + #[rustc_diagnostic_item = stringify!($Ty)] + pub struct $Ty($Int); + + impl $Ty { + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. /// - /// This enables some memory layout optimization. - #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// # Safety /// - /// ```rust - /// use std::mem::size_of; - #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] - /// ``` - /// - /// # Layout - /// - #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] - /// with the exception that `0` is not a valid instance. - #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] - /// including in FFI. - /// - /// Thanks to the [null pointer optimization], - #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] - /// are guaranteed to have the same size and alignment: - /// - /// ``` - /// # use std::mem::{size_of, align_of}; - #[doc = concat!("use std::num::", stringify!($Ty), ";")] - /// - #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::>());")] - #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] - /// ``` - /// - /// [null pointer optimization]: crate::option#representation + /// The value must not be zero. #[$stability] - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] - #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start(1)] - #[rustc_nonnull_optimization_guaranteed] - #[rustc_diagnostic_item = stringify!($Ty)] - pub struct $Ty($Int); - - impl $Ty { - /// Creates a non-zero without checking whether the value is non-zero. - /// This results in undefined behaviour if the value is zero. - /// - /// # Safety - /// - /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] - #[must_use] - #[inline] - pub const unsafe fn new_unchecked(n: $Int) -> Self { - crate::panic::debug_assert_nounwind!( - n != 0, - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") - ); - // SAFETY: this is guaranteed to be safe by the caller. - unsafe { - Self(n) - } - } - - /// Creates a non-zero if the given value is not zero. - #[$stability] - #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[must_use] - #[inline] - pub const fn new(n: $Int) -> Option { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } - } - - /// Returns the value as a primitive type. - #[$stability] - #[inline] - #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] - pub const fn get(self) -> $Int { - // FIXME: Remove this after LLVM supports `!range` metadata for function - // arguments https://github.com/llvm/llvm-project/issues/76628 - // - // Rustc can set range metadata only if it loads `self` from - // memory somewhere. If the value of `self` was from by-value argument - // of some not-inlined function, LLVM don't have range metadata - // to understand that the value cannot be zero. - - // SAFETY: It is an invariant of this type. - unsafe { - intrinsics::assume(self.0 != 0); - } - self.0 - } - - } - - #[stable(feature = "from_nonzero", since = "1.31.0")] - impl From<$Ty> for $Int { - #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] - #[inline] - fn from(nonzero: $Ty) -> Self { - // Call nonzero to keep information range information - // from get method. - nonzero.get() + #[$const_new_unchecked_stability] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: $Int) -> Self { + crate::panic::debug_assert_nounwind!( + n != 0, + concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") + ); + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + Self(n) } } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr for $Ty { - type Output = Self; - #[inline] - fn bitor(self, rhs: Self) -> Self::Output { - // SAFETY: since `self` and `rhs` are both nonzero, the - // result of the bitwise-or will be nonzero. - unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } + /// Creates a non-zero if the given value is not zero. + #[$stability] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] + #[inline] + pub const fn new(n: $Int) -> Option { + if n != 0 { + // SAFETY: we just checked that there's no `0` + Some(unsafe { Self(n) }) + } else { + None } } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Int> for $Ty { - type Output = Self; - #[inline] - fn bitor(self, rhs: $Int) -> Self::Output { - // SAFETY: since `self` is nonzero, the result of the - // bitwise-or will be nonzero regardless of the value of - // `rhs`. - unsafe { $Ty::new_unchecked(self.get() | rhs) } + /// Returns the value as a primitive type. + #[$stability] + #[inline] + #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] + pub const fn get(self) -> $Int { + // FIXME: Remove this after LLVM supports `!range` metadata for function + // arguments https://github.com/llvm/llvm-project/issues/76628 + // + // Rustc can set range metadata only if it loads `self` from + // memory somewhere. If the value of `self` was from by-value argument + // of some not-inlined function, LLVM don't have range metadata + // to understand that the value cannot be zero. + + // SAFETY: It is an invariant of this type. + unsafe { + intrinsics::assume(self.0 != 0); } + self.0 } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Ty> for $Int { - type Output = $Ty; - #[inline] - fn bitor(self, rhs: $Ty) -> Self::Output { - // SAFETY: since `rhs` is nonzero, the result of the - // bitwise-or will be nonzero regardless of the value of - // `self`. - unsafe { $Ty::new_unchecked(self | rhs.get()) } - } - } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: Self) { - *self = *self | rhs; - } + #[stable(feature = "from_nonzero", since = "1.31.0")] + impl From<$Ty> for $Int { + #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] + #[inline] + fn from(nonzero: $Ty) -> Self { + // Call nonzero to keep information range information + // from get method. + nonzero.get() } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign<$Int> for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: $Int) { - *self = *self | rhs; - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr for $Ty { + type Output = Self; + #[inline] + fn bitor(self, rhs: Self) -> Self::Output { + // SAFETY: since `self` and `rhs` are both nonzero, the + // result of the bitwise-or will be nonzero. + unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } } + } - impl_nonzero_fmt! { - #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr<$Int> for $Ty { + type Output = Self; + #[inline] + fn bitor(self, rhs: $Int) -> Self::Output { + // SAFETY: since `self` is nonzero, the result of the + // bitwise-or will be nonzero regardless of the value of + // `rhs`. + unsafe { $Ty::new_unchecked(self.get() | rhs) } } + } + + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr<$Ty> for $Int { + type Output = $Ty; + #[inline] + fn bitor(self, rhs: $Ty) -> Self::Output { + // SAFETY: since `rhs` is nonzero, the result of the + // bitwise-or will be nonzero regardless of the value of + // `self`. + unsafe { $Ty::new_unchecked(self | rhs.get()) } + } + } + + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + *self = *self | rhs; + } + } + + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign<$Int> for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: $Int) { + *self = *self | rhs; + } + } + + impl_nonzero_fmt! { + #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + } }; } From a6152cdd9a6c287411212209a18904ca5d68d484 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:24:16 -0800 Subject: [PATCH 139/297] Format nonzero_integer macro calls same way we do the primitive int impls The `key = $value` style will be beneficial as we introduce some more macro arguments here in later commits. --- library/core/src/num/nonzero.rs | 79 ++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index f7098bcf6e9c..f6ccefa26141 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -24,7 +24,10 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( - #[$stability:meta] #[$const_new_unchecked_stability:meta] $Ty:ident($Int:ty); + Self = $Ty:ident, + Primitive = $signedness:ident $Int:ident, + feature = $feature:literal, + original_stabilization = $since:literal, ) => { /// An integer that is known not to equal zero. /// @@ -56,7 +59,7 @@ macro_rules! nonzero_integer { /// ``` /// /// [null pointer optimization]: crate::option#representation - #[$stability] + #[stable(feature = $feature, since = $since)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -71,8 +74,8 @@ macro_rules! nonzero_integer { /// # Safety /// /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] + #[stable(feature = $feature, since = $since)] + #[rustc_const_stable(feature = $feature, since = $since)] #[must_use] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { @@ -87,7 +90,7 @@ macro_rules! nonzero_integer { } /// Creates a non-zero if the given value is not zero. - #[$stability] + #[stable(feature = $feature, since = $since)] #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] #[must_use] #[inline] @@ -101,7 +104,7 @@ macro_rules! nonzero_integer { } /// Returns the value as a primitive type. - #[$stability] + #[stable(feature = $feature, since = $since)] #[inline] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] pub const fn get(self) -> $Int { @@ -119,7 +122,6 @@ macro_rules! nonzero_integer { } self.0 } - } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -185,7 +187,8 @@ macro_rules! nonzero_integer { } impl_nonzero_fmt! { - #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[stable(feature = $feature, since = $since)] + (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } }; } @@ -1383,49 +1386,85 @@ nonzero_bits! { } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); + Self = NonZeroU8, + Primitive = unsigned u8, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); + Self = NonZeroU16, + Primitive = unsigned u16, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); + Self = NonZeroU32, + Primitive = unsigned u32, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); + Self = NonZeroU64, + Primitive = unsigned u64, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); + Self = NonZeroU128, + Primitive = unsigned u128, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); + Self = NonZeroUsize, + Primitive = unsigned usize, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); + Self = NonZeroI8, + Primitive = signed i8, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); + Self = NonZeroI16, + Primitive = signed i16, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); + Self = NonZeroI32, + Primitive = signed i32, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); + Self = NonZeroI64, + Primitive = signed i64, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); + Self = NonZeroI128, + Primitive = signed i128, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); + Self = NonZeroIsize, + Primitive = signed isize, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } From 3de0af1a4da54885dd312e5e6f39641f5da06410 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:28:52 -0800 Subject: [PATCH 140/297] Move 'impl FromStr for NonZero' into nonzero_integer macro --- library/core/src/num/nonzero.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index f6ccefa26141..0f5d421235e1 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -190,13 +190,9 @@ macro_rules! nonzero_integer { #[stable(feature = $feature, since = $since)] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } - }; -} -macro_rules! from_str_radix_nzint_impl { - ($($t:ty)*) => {$( #[stable(feature = "nonzero_parse", since = "1.35.0")] - impl FromStr for $t { + impl FromStr for $Ty { type Err = ParseIntError; fn from_str(src: &str) -> Result { Self::new(from_str_radix(src, 10)?) @@ -205,12 +201,9 @@ macro_rules! from_str_radix_nzint_impl { }) } } - )*} + }; } -from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize -NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } - macro_rules! nonzero_leading_trailing_zeros { ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { $( From 81e1a7c6b5bb5bea9fbbd0f5db0c118dbea867fb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:41:24 -0800 Subject: [PATCH 141/297] Move impl Div and Rem into nonzero_integer macro --- library/core/src/num/nonzero.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0f5d421235e1..79cca2764799 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -201,6 +201,8 @@ macro_rules! nonzero_integer { }) } } + + nonzero_integer_impl_div_rem!($Ty $signedness $Int); }; } @@ -275,9 +277,12 @@ nonzero_leading_trailing_zeros! { NonZeroIsize(usize), -1isize; } -macro_rules! nonzero_integers_div { - ( $( $Ty: ident($Int: ty); )+ ) => { - $( +macro_rules! nonzero_integer_impl_div_rem { + ($Ty:ident signed $Int:ty) => { + // nothing for signed ints + }; + + ($Ty:ident unsigned $Int:ty) => { #[stable(feature = "nonzero_div", since = "1.51.0")] impl Div<$Ty> for $Int { type Output = $Int; @@ -302,17 +307,7 @@ macro_rules! nonzero_integers_div { unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } } } - )+ - } -} - -nonzero_integers_div! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); + }; } // A bunch of methods for unsigned nonzero types only. From a78d9a6de1848358b3835d3ac8ce6b20a24c061f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:07:42 -0800 Subject: [PATCH 142/297] Unindent nonzero_integer_impl_div_rem macro body --- library/core/src/num/nonzero.rs | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 79cca2764799..75429d9059a6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -283,30 +283,30 @@ macro_rules! nonzero_integer_impl_div_rem { }; ($Ty:ident unsigned $Int:ty) => { - #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Div<$Ty> for $Int { - type Output = $Int; - /// This operation rounds towards zero, - /// truncating any fractional part of the exact result, and cannot panic. - #[inline] - fn div(self, other: $Ty) -> $Int { - // SAFETY: div by zero is checked because `other` is a nonzero, - // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_div(self, other.get()) } - } + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Div<$Ty> for $Int { + type Output = $Int; + /// This operation rounds towards zero, + /// truncating any fractional part of the exact result, and cannot panic. + #[inline] + fn div(self, other: $Ty) -> $Int { + // SAFETY: div by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_div(self, other.get()) } } + } - #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Rem<$Ty> for $Int { - type Output = $Int; - /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. - #[inline] - fn rem(self, other: $Ty) -> $Int { - // SAFETY: rem by zero is checked because `other` is a nonzero, - // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } - } + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Rem<$Ty> for $Int { + type Output = $Int; + /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. + #[inline] + fn rem(self, other: $Ty) -> $Int { + // SAFETY: rem by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } } + } }; } From f846ed53e41a18fbb900e794467351fda5ffbb80 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:37:28 -0800 Subject: [PATCH 143/297] Move leading_zeros and trailing_zeros methods into nonzero_integer macro --- library/core/src/num/nonzero.rs | 146 ++++++++++++++++---------------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 75429d9059a6..9c396710fd48 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,8 +26,12 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, + UnsignedPrimitive = $UnsignedPrimitive:ty, feature = $feature:literal, original_stabilization = $since:literal, + + // Used in doc comments. + leading_zeros_test = $leading_zeros_test:expr, ) => { /// An integer that is known not to equal zero. /// @@ -122,6 +126,53 @@ macro_rules! nonzero_integer { } self.0 } + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($leading_zeros_test), ").unwrap();")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. + unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. + unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -206,77 +257,6 @@ macro_rules! nonzero_integer { }; } -macro_rules! nonzero_leading_trailing_zeros { - ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { - $( - impl $Ty { - /// Returns the number of leading zeros in the binary representation of `self`. - /// - /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] - /// - /// assert_eq!(n.leading_zeros(), 0); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn leading_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. - unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 } - } - - /// Returns the number of trailing zeros in the binary representation - /// of `self`. - /// - /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] - /// - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. - unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 } - } - - } - )+ - } -} - -nonzero_leading_trailing_zeros! { - NonZeroU8(u8), u8::MAX; - NonZeroU16(u16), u16::MAX; - NonZeroU32(u32), u32::MAX; - NonZeroU64(u64), u64::MAX; - NonZeroU128(u128), u128::MAX; - NonZeroUsize(usize), usize::MAX; - NonZeroI8(u8), -1i8; - NonZeroI16(u16), -1i16; - NonZeroI32(u32), -1i32; - NonZeroI64(u64), -1i64; - NonZeroI128(u128), -1i128; - NonZeroIsize(usize), -1isize; -} - macro_rules! nonzero_integer_impl_div_rem { ($Ty:ident signed $Int:ty) => { // nothing for signed ints @@ -1376,83 +1356,107 @@ nonzero_bits! { nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, + UnsignedPrimitive = u8, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u8::MAX, } nonzero_integer! { Self = NonZeroU16, Primitive = unsigned u16, + UnsignedPrimitive = u16, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u16::MAX, } nonzero_integer! { Self = NonZeroU32, Primitive = unsigned u32, + UnsignedPrimitive = u32, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u32::MAX, } nonzero_integer! { Self = NonZeroU64, Primitive = unsigned u64, + UnsignedPrimitive = u64, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u64::MAX, } nonzero_integer! { Self = NonZeroU128, Primitive = unsigned u128, + UnsignedPrimitive = u128, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u128::MAX, } nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, + UnsignedPrimitive = usize, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = usize::MAX, } nonzero_integer! { Self = NonZeroI8, Primitive = signed i8, + UnsignedPrimitive = u8, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i8, } nonzero_integer! { Self = NonZeroI16, Primitive = signed i16, + UnsignedPrimitive = u16, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i16, } nonzero_integer! { Self = NonZeroI32, Primitive = signed i32, + UnsignedPrimitive = u32, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i32, } nonzero_integer! { Self = NonZeroI64, Primitive = signed i64, + UnsignedPrimitive = u64, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i64, } nonzero_integer! { Self = NonZeroI128, Primitive = signed i128, + UnsignedPrimitive = u128, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i128, } nonzero_integer! { Self = NonZeroIsize, Primitive = signed isize, + UnsignedPrimitive = usize, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1isize, } From 23483664a24434e0bd5dab1576dffe4d8ada712c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 13 Jan 2024 17:53:14 -0800 Subject: [PATCH 144/297] Split out `option::unwrap_failed` like we have `result::unwrap_failed` ...and like `option::expect_failed` --- library/core/src/option.rs | 12 ++++++++++-- tests/codegen/debuginfo-inline-callsite-location.rs | 4 ++-- ...352.num_to_digit.PreCodegen.after.panic-abort.mir | 2 +- ...52.num_to_digit.PreCodegen.after.panic-unwind.mir | 2 +- ..._invalid_constant.main.GVN.32bit.panic-abort.diff | 2 +- ...invalid_constant.main.GVN.32bit.panic-unwind.diff | 2 +- ..._invalid_constant.main.GVN.64bit.panic-abort.diff | 2 +- ...invalid_constant.main.GVN.64bit.panic-unwind.diff | 2 +- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ff4353492498..975aff90d35f 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -921,14 +921,14 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.unwrap(), "air"); // fails /// ``` - #[inline] + #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn unwrap(self) -> T { match self { Some(val) => val, - None => panic("called `Option::unwrap()` on a `None` value"), + None => unwrap_failed(), } } @@ -1970,6 +1970,14 @@ impl Option> { } } +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cold] +#[track_caller] +const fn unwrap_failed() -> ! { + panic("called `Option::unwrap()` on a `None` value") +} + // This is a separate function to reduce the code size of .expect() itself. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs index b1475ee79316..d529f9ccead5 100644 --- a/tests/codegen/debuginfo-inline-callsite-location.rs +++ b/tests/codegen/debuginfo-inline-callsite-location.rs @@ -4,9 +4,9 @@ // can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail // calls to panic. -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E // CHECK-SAME: !dbg ![[#first_dbg:]] -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E // CHECK-SAME: !dbg ![[#second_dbg:]] // CHECK-DAG: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap" diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index 5d25c6557002..f7be8b75db7b 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -51,7 +51,7 @@ fn num_to_digit(_1: char) -> u32 { } bb4: { - _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _7 = option::unwrap_failed() -> unwind unreachable; } bb5: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index 4677c0108e3b..e76fe992ac7d 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -51,7 +51,7 @@ fn num_to_digit(_1: char) -> u32 { } bb4: { - _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _7 = option::unwrap_failed() -> unwind continue; } bb5: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 47e0d402347d..cf93897d591f 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -62,7 +62,7 @@ } bb1: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _11 = option::unwrap_failed() -> unwind unreachable; } bb2: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index dee57ce6c27b..ca33619aa1fb 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -60,7 +60,7 @@ } bb2: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _11 = option::unwrap_failed() -> unwind continue; } bb3: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index a255b15920cb..9c026280ea9c 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -62,7 +62,7 @@ } bb1: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _11 = option::unwrap_failed() -> unwind unreachable; } bb2: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index 192ffea25915..7eec7ffb01f3 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -60,7 +60,7 @@ } bb2: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _11 = option::unwrap_failed() -> unwind continue; } bb3: { From 757ed2566701feba8fc67cae3d21a7423254efba Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:50:14 -0800 Subject: [PATCH 145/297] Move Neg impl into the macro that generates Div and Rem --- library/core/src/num/nonzero.rs | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 9c396710fd48..b1dd766de315 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -253,15 +253,12 @@ macro_rules! nonzero_integer { } } - nonzero_integer_impl_div_rem!($Ty $signedness $Int); + nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int); }; } -macro_rules! nonzero_integer_impl_div_rem { - ($Ty:ident signed $Int:ty) => { - // nothing for signed ints - }; - +macro_rules! nonzero_integer_signedness_dependent_impls { + // Impls for unsigned nonzero types only. ($Ty:ident unsigned $Int:ty) => { #[stable(feature = "nonzero_div", since = "1.51.0")] impl Div<$Ty> for $Int { @@ -288,6 +285,23 @@ macro_rules! nonzero_integer_impl_div_rem { } } }; + + // Impls for signed nonzero types only. + ($Ty:ident signed $Int:ty) => { + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] + impl Neg for $Ty { + type Output = $Ty; + + #[inline] + fn neg(self) -> $Ty { + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().neg()) } + } + } + + forward_ref_unop! { impl Neg, neg for $Ty, + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } + }; } // A bunch of methods for unsigned nonzero types only. @@ -921,20 +935,6 @@ macro_rules! nonzero_signed_operations { unsafe { $Ty::new_unchecked(result) } } } - - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] - impl Neg for $Ty { - type Output = $Ty; - - #[inline] - fn neg(self) -> $Ty { - // SAFETY: negation of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().neg()) } - } - } - - forward_ref_unop! { impl Neg, neg for $Ty, - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } )+ } } From 4291b3ff62e4aad3dae4c573bde5f203d3baec79 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:03:55 -0800 Subject: [PATCH 146/297] Move signedness dependent methods into the omnibus impl block --- library/core/src/num/nonzero.rs | 65 +++++++++++++++------------------ 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index b1dd766de315..1b8920f94774 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,6 +26,7 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, + $(UnsignedNonZero = $UnsignedNonZero:ident,)? UnsignedPrimitive = $UnsignedPrimitive:ty, feature = $feature:literal, original_stabilization = $since:literal, @@ -173,6 +174,13 @@ macro_rules! nonzero_integer { // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } } + + nonzero_integer_signedness_dependent_methods! { + Self = $Ty, + Primitive = $signedness $Int, + $(UnsignedNonZero = $UnsignedNonZero,)? + UnsignedPrimitive = $UnsignedPrimitive, + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -304,11 +312,13 @@ macro_rules! nonzero_integer_signedness_dependent_impls { }; } -// A bunch of methods for unsigned nonzero types only. -macro_rules! nonzero_unsigned_operations { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { +macro_rules! nonzero_integer_signedness_dependent_methods { + // Methods for unsigned nonzero types only. + ( + Self = $Ty:ident, + Primitive = unsigned $Int:ident, + UnsignedPrimitive = $Uint:ty, + ) => { /// Adds an unsigned integer to a non-zero value. /// Checks for overflow and returns [`None`] on overflow. /// As a consequence, the result cannot wrap to zero. @@ -538,25 +548,15 @@ macro_rules! nonzero_unsigned_operations { // never being 0. unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } } - } - )+ - } -} + }; -nonzero_unsigned_operations! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); -} - -// A bunch of methods for signed nonzero types only. -macro_rules! nonzero_signed_operations { - ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => { - $( - impl $Ty { + // Methods for signed nonzero types only. + ( + Self = $Ty:ident, + Primitive = signed $Int:ident, + UnsignedNonZero = $Uty:ident, + UnsignedPrimitive = $Uint:ty, + ) => { /// Computes the absolute value of self. #[doc = concat!("See [`", stringify!($Int), "::abs`]")] /// for documentation on overflow behaviour. @@ -934,18 +934,7 @@ macro_rules! nonzero_signed_operations { // SAFETY: negation of nonzero cannot yield zero values. unsafe { $Ty::new_unchecked(result) } } - } - )+ - } -} - -nonzero_signed_operations! { - NonZeroI8(i8) -> NonZeroU8(u8); - NonZeroI16(i16) -> NonZeroU16(u16); - NonZeroI32(i32) -> NonZeroU32(u32); - NonZeroI64(i64) -> NonZeroU64(u64); - NonZeroI128(i128) -> NonZeroU128(u128); - NonZeroIsize(isize) -> NonZeroUsize(usize); + }; } // A bunch of methods for both signed and unsigned nonzero types. @@ -1410,6 +1399,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI8, Primitive = signed i8, + UnsignedNonZero = NonZeroU8, UnsignedPrimitive = u8, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1419,6 +1409,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI16, Primitive = signed i16, + UnsignedNonZero = NonZeroU16, UnsignedPrimitive = u16, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1428,6 +1419,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI32, Primitive = signed i32, + UnsignedNonZero = NonZeroU32, UnsignedPrimitive = u32, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1437,6 +1429,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI64, Primitive = signed i64, + UnsignedNonZero = NonZeroU64, UnsignedPrimitive = u64, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1446,6 +1439,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI128, Primitive = signed i128, + UnsignedNonZero = NonZeroU128, UnsignedPrimitive = u128, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1455,6 +1449,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroIsize, Primitive = signed isize, + UnsignedNonZero = NonZeroUsize, UnsignedPrimitive = usize, feature = "signed_nonzero", original_stabilization = "1.34.0", From b21b9cc901c3f021c7b7475c406662cd9c0d76e1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:06:40 -0800 Subject: [PATCH 147/297] Unindent nonzero_integer_signedness_dependent_methods macro body --- library/core/src/num/nonzero.rs | 1178 +++++++++++++++---------------- 1 file changed, 589 insertions(+), 589 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1b8920f94774..8550a7b4c7b6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -319,235 +319,235 @@ macro_rules! nonzero_integer_signedness_dependent_methods { Primitive = unsigned $Int:ident, UnsignedPrimitive = $Uint:ty, ) => { - /// Adds an unsigned integer to a non-zero value. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(two), one.checked_add(1)); - /// assert_eq!(None, max.checked_add(1)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_add(self, other: $Int) -> Option<$Ty> { - if let Some(result) = self.get().checked_add(other) { - // SAFETY: - // - `checked_add` returns `None` on overflow - // - `self` is non-zero - // - the only way to get zero from an addition without overflow is for both - // sides to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } + /// Adds an unsigned integer to a non-zero value. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), one.checked_add(1)); + /// assert_eq!(None, max.checked_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, other: $Int) -> Option<$Ty> { + if let Some(result) = self.get().checked_add(other) { + // SAFETY: + // - `checked_add` returns `None` on overflow + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } - /// Adds an unsigned integer to a non-zero value. - #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(two, one.saturating_add(1)); - /// assert_eq!(max, max.saturating_add(1)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_add(self, other: $Int) -> $Ty { - // SAFETY: - // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero - // - `self` is non-zero - // - the only way to get zero from an addition without overflow is for both - // sides to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } - } + /// Adds an unsigned integer to a non-zero value. + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(two, one.saturating_add(1)); + /// assert_eq!(max, max.saturating_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add(self, other: $Int) -> $Ty { + // SAFETY: + // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } + } - /// Adds an unsigned integer to a non-zero value, - /// assuming overflow cannot occur. - /// Overflow is unchecked, and it is undefined behaviour to overflow - /// *even if the result would wrap to a non-zero value*. - /// The behaviour is undefined as soon as - #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] - /// - /// # Examples - /// - /// ``` - /// #![feature(nonzero_ops)] - /// - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - /// - /// assert_eq!(two, unsafe { one.unchecked_add(1) }); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "nonzero_ops", issue = "84186")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { - // SAFETY: The caller ensures there is no overflow. - unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } - } + /// Adds an unsigned integer to a non-zero value, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + /// + /// assert_eq!(two, unsafe { one.unchecked_add(1) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } + } - /// Returns the smallest power of two greater than or equal to n. - /// Checks for overflow and returns [`None`] - /// if the next power of two is greater than the type’s maximum value. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(two), two.checked_next_power_of_two() ); - /// assert_eq!(Some(four), three.checked_next_power_of_two() ); - /// assert_eq!(None, max.checked_next_power_of_two() ); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_next_power_of_two(self) -> Option<$Ty> { - if let Some(nz) = self.get().checked_next_power_of_two() { - // SAFETY: The next power of two is positive - // and overflow is checked. - Some(unsafe { $Ty::new_unchecked(nz) }) - } else { - None - } - } + /// Returns the smallest power of two greater than or equal to n. + /// Checks for overflow and returns [`None`] + /// if the next power of two is greater than the type’s maximum value. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), two.checked_next_power_of_two() ); + /// assert_eq!(Some(four), three.checked_next_power_of_two() ); + /// assert_eq!(None, max.checked_next_power_of_two() ); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_next_power_of_two(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_next_power_of_two() { + // SAFETY: The next power of two is positive + // and overflow is checked. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None + } + } - /// Returns the base 2 logarithm of the number, rounded down. - /// - /// This is the same operation as - #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] - /// except that it has no failure cases to worry about - /// since this value can never be zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] - /// ``` - #[stable(feature = "int_log", since = "1.67.0")] - #[rustc_const_stable(feature = "int_log", since = "1.67.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn ilog2(self) -> u32 { - Self::BITS - 1 - self.leading_zeros() - } + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog2(self) -> u32 { + Self::BITS - 1 - self.leading_zeros() + } - /// Returns the base 10 logarithm of the number, rounded down. - /// - /// This is the same operation as - #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] - /// except that it has no failure cases to worry about - /// since this value can never be zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] - /// ``` - #[stable(feature = "int_log", since = "1.67.0")] - #[rustc_const_stable(feature = "int_log", since = "1.67.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn ilog10(self) -> u32 { - super::int_log10::$Int(self.get()) - } + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog10(self) -> u32 { + super::int_log10::$Int(self.get()) + } - /// Calculates the middle point of `self` and `rhs`. - /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. - /// - /// # Examples - /// - /// ``` - /// #![feature(num_midpoint)] - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - /// - /// assert_eq!(one.midpoint(four), two); - /// assert_eq!(four.midpoint(one), two); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] - #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] - #[rustc_allow_const_fn_unstable(const_num_midpoint)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn midpoint(self, rhs: Self) -> Self { - // SAFETY: The only way to get `0` with midpoint is to have two opposite or - // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because - // of the unsignedness of this number and also because $Ty is guaranteed to - // never being 0. - unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } - } + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(one.midpoint(four), two); + /// assert_eq!(four.midpoint(one), two); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[rustc_allow_const_fn_unstable(const_num_midpoint)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + // SAFETY: The only way to get `0` with midpoint is to have two opposite or + // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because + // of the unsignedness of this number and also because $Ty is guaranteed to + // never being 0. + unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } + } }; // Methods for signed nonzero types only. @@ -557,383 +557,383 @@ macro_rules! nonzero_integer_signedness_dependent_methods { UnsignedNonZero = $Uty:ident, UnsignedPrimitive = $Uint:ty, ) => { - /// Computes the absolute value of self. - #[doc = concat!("See [`", stringify!($Int), "::abs`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - /// - /// assert_eq!(pos, pos.abs()); - /// assert_eq!(pos, neg.abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn abs(self) -> $Ty { - // SAFETY: This cannot overflow to zero. - unsafe { $Ty::new_unchecked(self.get().abs()) } - } + /// Computes the absolute value of self. + #[doc = concat!("See [`", stringify!($Int), "::abs`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + /// + /// assert_eq!(pos, pos.abs()); + /// assert_eq!(pos, neg.abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs(self) -> $Ty { + // SAFETY: This cannot overflow to zero. + unsafe { $Ty::new_unchecked(self.get().abs()) } + } - /// Checked absolute value. - /// Checks for overflow and returns [`None`] if - #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] - /// The result cannot be zero. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(Some(pos), neg.checked_abs()); - /// assert_eq!(None, min.checked_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_abs(self) -> Option<$Ty> { - if let Some(nz) = self.get().checked_abs() { - // SAFETY: absolute value of nonzero cannot yield zero values. - Some(unsafe { $Ty::new_unchecked(nz) }) - } else { - None - } - } + /// Checked absolute value. + /// Checks for overflow and returns [`None`] if + #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] + /// The result cannot be zero. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(Some(pos), neg.checked_abs()); + /// assert_eq!(None, min.checked_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_abs(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_abs() { + // SAFETY: absolute value of nonzero cannot yield zero values. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None + } + } - /// Computes the absolute value of self, - /// with overflow information, see - #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!((pos, false), pos.overflowing_abs()); - /// assert_eq!((pos, false), neg.overflowing_abs()); - /// assert_eq!((min, true), min.overflowing_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_abs(self) -> ($Ty, bool) { - let (nz, flag) = self.get().overflowing_abs(); - ( - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(nz) }, - flag, - ) - } + /// Computes the absolute value of self, + /// with overflow information, see + #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!((pos, false), pos.overflowing_abs()); + /// assert_eq!((pos, false), neg.overflowing_abs()); + /// assert_eq!((min, true), min.overflowing_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_abs(self) -> ($Ty, bool) { + let (nz, flag) = self.get().overflowing_abs(); + ( + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(nz) }, + flag, + ) + } - /// Saturating absolute value, see - #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN + 1)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos, pos.saturating_abs()); - /// assert_eq!(pos, neg.saturating_abs()); - /// assert_eq!(max, min.saturating_abs()); - /// assert_eq!(max, min_plus.saturating_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_abs(self) -> $Ty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } - } + /// Saturating absolute value, see + #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.saturating_abs()); + /// assert_eq!(pos, neg.saturating_abs()); + /// assert_eq!(max, min.saturating_abs()); + /// assert_eq!(max, min_plus.saturating_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } + } - /// Wrapping absolute value, see - #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("# let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos, pos.wrapping_abs()); - /// assert_eq!(pos, neg.wrapping_abs()); - /// assert_eq!(min, min.wrapping_abs()); - /// assert_eq!(max, (-max).wrapping_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_abs(self) -> $Ty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } - } + /// Wrapping absolute value, see + #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("# let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.wrapping_abs()); + /// assert_eq!(pos, neg.wrapping_abs()); + /// assert_eq!(min, min.wrapping_abs()); + /// assert_eq!(max, (-max).wrapping_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } + } - /// Computes the absolute value of self - /// without any wrapping or panicking. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("# use std::num::", stringify!($Uty), ";")] - /// - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] - #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", - stringify!($Uint), "::MAX / 2 + 1)?;")] - /// - /// assert_eq!(u_pos, i_pos.unsigned_abs()); - /// assert_eq!(u_pos, i_neg.unsigned_abs()); - /// assert_eq!(u_max, i_min.unsigned_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn unsigned_abs(self) -> $Uty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } - } + /// Computes the absolute value of self + /// without any wrapping or panicking. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("# use std::num::", stringify!($Uty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] + #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", + stringify!($Uint), "::MAX / 2 + 1)?;")] + /// + /// assert_eq!(u_pos, i_pos.unsigned_abs()); + /// assert_eq!(u_pos, i_neg.unsigned_abs()); + /// assert_eq!(u_max, i_min.unsigned_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unsigned_abs(self) -> $Uty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } + } - /// Returns `true` if `self` is positive and `false` if the - /// number is negative. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - /// - /// assert!(pos_five.is_positive()); - /// assert!(!neg_five.is_positive()); - /// # Some(()) - /// # } - /// ``` - #[must_use] - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn is_positive(self) -> bool { - self.get().is_positive() - } + /// Returns `true` if `self` is positive and `false` if the + /// number is negative. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(pos_five.is_positive()); + /// assert!(!neg_five.is_positive()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_positive(self) -> bool { + self.get().is_positive() + } - /// Returns `true` if `self` is negative and `false` if the - /// number is positive. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - /// - /// assert!(neg_five.is_negative()); - /// assert!(!pos_five.is_negative()); - /// # Some(()) - /// # } - /// ``` - #[must_use] - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn is_negative(self) -> bool { - self.get().is_negative() - } + /// Returns `true` if `self` is negative and `false` if the + /// number is positive. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(neg_five.is_negative()); + /// assert!(!pos_five.is_negative()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_negative(self) -> bool { + self.get().is_negative() + } - /// Checked negation. Computes `-self`, - #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); - /// assert_eq!(min.checked_neg(), None); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn checked_neg(self) -> Option<$Ty> { - if let Some(result) = self.get().checked_neg() { - // SAFETY: negation of nonzero cannot yield zero values. - return Some(unsafe { $Ty::new_unchecked(result) }); - } - None - } + /// Checked negation. Computes `-self`, + #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); + /// assert_eq!(min.checked_neg(), None); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn checked_neg(self) -> Option<$Ty> { + if let Some(result) = self.get().checked_neg() { + // SAFETY: negation of nonzero cannot yield zero values. + return Some(unsafe { $Ty::new_unchecked(result) }); + } + None + } - /// Negates self, overflowing if this is equal to the minimum value. - /// - #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); - /// assert_eq!(min.overflowing_neg(), (min, true)); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn overflowing_neg(self) -> ($Ty, bool) { - let (result, overflow) = self.get().overflowing_neg(); - // SAFETY: negation of nonzero cannot yield zero values. - ((unsafe { $Ty::new_unchecked(result) }), overflow) - } + /// Negates self, overflowing if this is equal to the minimum value. + /// + #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); + /// assert_eq!(min.overflowing_neg(), (min, true)); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn overflowing_neg(self) -> ($Ty, bool) { + let (result, overflow) = self.get().overflowing_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + ((unsafe { $Ty::new_unchecked(result) }), overflow) + } - /// Saturating negation. Computes `-self`, - #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] - #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] - /// instead of overflowing. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN + 1)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos_five.saturating_neg(), neg_five); - /// assert_eq!(min.saturating_neg(), max); - /// assert_eq!(max.saturating_neg(), min_plus_one); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn saturating_neg(self) -> $Ty { - if let Some(result) = self.checked_neg() { - return result; - } - $Ty::MAX - } + /// Saturating negation. Computes `-self`, + #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] + #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] + /// instead of overflowing. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos_five.saturating_neg(), neg_five); + /// assert_eq!(min.saturating_neg(), max); + /// assert_eq!(max.saturating_neg(), min_plus_one); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn saturating_neg(self) -> $Ty { + if let Some(result) = self.checked_neg() { + return result; + } + $Ty::MAX + } - /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary - /// of the type. - /// - #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.wrapping_neg(), neg_five); - /// assert_eq!(min.wrapping_neg(), min); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn wrapping_neg(self) -> $Ty { - let result = self.get().wrapping_neg(); - // SAFETY: negation of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(result) } - } + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.wrapping_neg(), neg_five); + /// assert_eq!(min.wrapping_neg(), min); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn wrapping_neg(self) -> $Ty { + let result = self.get().wrapping_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(result) } + } }; } From c6d776ef4ba4f133b5f370f144b99cd3f39388fa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:38:38 -0800 Subject: [PATCH 148/297] Work around rustfmt doc attribute indentation bug --- library/core/src/num/nonzero.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8550a7b4c7b6..6b28f8100e78 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -312,6 +312,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { }; } +#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974 macro_rules! nonzero_integer_signedness_dependent_methods { // Methods for unsigned nonzero types only. ( From 63256af236f4620701d7d8771f874c4ef57e6ff2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:46:18 -0800 Subject: [PATCH 149/297] Move nonzero_unsigned_signed_operations methods into the omnibus impl block --- library/core/src/num/nonzero.rs | 426 +++++++++++++++----------------- 1 file changed, 201 insertions(+), 225 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b28f8100e78..c9693a22e876 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -181,6 +181,207 @@ macro_rules! nonzero_integer { $(UnsignedNonZero = $UnsignedNonZero,)? UnsignedPrimitive = $UnsignedPrimitive, } + + /// Multiplies two non-zero integers together. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(four), two.checked_mul(two)); + /// assert_eq!(None, max.checked_mul(two)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { + if let Some(result) = self.get().checked_mul(other.get()) { + // SAFETY: + // - `checked_mul` returns `None` on overflow + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Multiplies two non-zero integers together. + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(four, two.saturating_mul(two)); + /// assert_eq!(max, four.saturating_mul(max)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, other: $Ty) -> $Ty { + // SAFETY: + // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } + } + + /// Multiplies two non-zero integers together, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", + "or `self * rhs < ", stringify!($Int), "::MIN`.") + } + if unsigned { + concat!("`self * rhs > ", stringify!($Int), "::MAX`.") + } + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } + } + + /// Raises non-zero value to an integer power. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX / 2)?;")] + /// + /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); + /// assert_eq!(None, half_max.checked_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, other: u32) -> Option<$Ty> { + if let Some(result) = self.get().checked_pow(other) { + // SAFETY: + // - `checked_pow` returns `None` on overflow/underflow + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Raise non-zero value to an integer power. + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("Return [`", stringify!($Ty), "::MIN`] ", + "or [`", stringify!($Ty), "::MAX`] on overflow.") + } + if unsigned { + concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") + } + }] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(twenty_seven, three.saturating_pow(3)); + /// assert_eq!(max, max.saturating_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, other: u32) -> $Ty { + // SAFETY: + // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -938,216 +1139,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods { }; } -// A bunch of methods for both signed and unsigned nonzero types. -macro_rules! nonzero_unsigned_signed_operations { - ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => { - $( - impl $Ty { - /// Multiplies two non-zero integers together. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(four), two.checked_mul(two)); - /// assert_eq!(None, max.checked_mul(two)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { - if let Some(result) = self.get().checked_mul(other.get()) { - // SAFETY: - // - `checked_mul` returns `None` on overflow - // - `self` and `other` are non-zero - // - the only way to get zero from a multiplication without overflow is for one - // of the sides to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } - - /// Multiplies two non-zero integers together. - #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(four, two.saturating_mul(two)); - /// assert_eq!(max, four.saturating_mul(max)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_mul(self, other: $Ty) -> $Ty { - // SAFETY: - // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, - // all of which are non-zero - // - `self` and `other` are non-zero - // - the only way to get zero from a multiplication without overflow is for one - // of the sides to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } - } - - /// Multiplies two non-zero integers together, - /// assuming overflow cannot occur. - /// Overflow is unchecked, and it is undefined behaviour to overflow - /// *even if the result would wrap to a non-zero value*. - /// The behaviour is undefined as soon as - #[doc = sign_dependent_expr!{ - $signedness ? - if signed { - concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", - "or `self * rhs < ", stringify!($Int), "::MIN`.") - } - if unsigned { - concat!("`self * rhs > ", stringify!($Int), "::MAX`.") - } - }] - /// - /// # Examples - /// - /// ``` - /// #![feature(nonzero_ops)] - /// - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - /// - /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "nonzero_ops", issue = "84186")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { - // SAFETY: The caller ensures there is no overflow. - unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } - } - - /// Raises non-zero value to an integer power. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] - #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX / 2)?;")] - /// - /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); - /// assert_eq!(None, half_max.checked_pow(3)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_pow(self, other: u32) -> Option<$Ty> { - if let Some(result) = self.get().checked_pow(other) { - // SAFETY: - // - `checked_pow` returns `None` on overflow/underflow - // - `self` is non-zero - // - the only way to get zero from an exponentiation without overflow is - // for base to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } - - /// Raise non-zero value to an integer power. - #[doc = sign_dependent_expr!{ - $signedness ? - if signed { - concat!("Return [`", stringify!($Ty), "::MIN`] ", - "or [`", stringify!($Ty), "::MAX`] on overflow.") - } - if unsigned { - concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") - } - }] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(twenty_seven, three.saturating_pow(3)); - /// assert_eq!(max, max.saturating_pow(3)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_pow(self, other: u32) -> $Ty { - // SAFETY: - // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, - // all of which are non-zero - // - `self` is non-zero - // - the only way to get zero from an exponentiation without overflow is - // for base to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } - } - } - )+ - } -} - // Use this when the generated code should differ between signed and unsigned types. macro_rules! sign_dependent_expr { (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { @@ -1158,21 +1149,6 @@ macro_rules! sign_dependent_expr { }; } -nonzero_unsigned_signed_operations! { - unsigned NonZeroU8(u8); - unsigned NonZeroU16(u16); - unsigned NonZeroU32(u32); - unsigned NonZeroU64(u64); - unsigned NonZeroU128(u128); - unsigned NonZeroUsize(usize); - signed NonZeroI8(i8); - signed NonZeroI16(i16); - signed NonZeroI32(i32); - signed NonZeroI64(i64); - signed NonZeroI128(i128); - signed NonZeroIsize(isize); -} - macro_rules! nonzero_unsigned_is_power_of_two { ( $( $Ty: ident )+ ) => { $( From 441913626d33919b743e167c5c9e951487291fdd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:47:53 -0800 Subject: [PATCH 150/297] Move is_power_of_two into unsigned part of signedness_dependent_methods --- library/core/src/num/nonzero.rs | 68 ++++++++++++++------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c9693a22e876..0c34012ab5c6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -750,6 +750,34 @@ macro_rules! nonzero_integer_signedness_dependent_methods { // never being 0. unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } } + + /// Returns `true` if and only if `self == (1 << k)` for some `k`. + /// + /// On many architectures, this function can perform better than `is_power_of_two()` + /// on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] + /// assert!(eight.is_power_of_two()); + #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] + /// assert!(!ten.is_power_of_two()); + /// ``` + #[must_use] + #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[inline] + pub const fn is_power_of_two(self) -> bool { + // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. + // On the basic x86-64 target, this saves 3 instructions for the zero check. + // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction + // compared to the `POPCNT` implementation on the underlying integer type. + + intrinsics::ctpop(self.get()) < 2 + } }; // Methods for signed nonzero types only. @@ -1149,46 +1177,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_unsigned_is_power_of_two { - ( $( $Ty: ident )+ ) => { - $( - impl $Ty { - - /// Returns `true` if and only if `self == (1 << k)` for some `k`. - /// - /// On many architectures, this function can perform better than `is_power_of_two()` - /// on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] - /// assert!(eight.is_power_of_two()); - #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] - /// assert!(!ten.is_power_of_two()); - /// ``` - #[must_use] - #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[inline] - pub const fn is_power_of_two(self) -> bool { - // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. - // On the basic x86-64 target, this saves 3 instructions for the zero check. - // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction - // compared to the `POPCNT` implementation on the underlying integer type. - - intrinsics::ctpop(self.get()) < 2 - } - - } - )+ - } -} - -nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize } - macro_rules! nonzero_min_max_unsigned { ( $( $Ty: ident($Int: ident); )+ ) => { $( From 7f7c5af097678da556cd57936a8d8b6c02858502 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:49:44 -0800 Subject: [PATCH 151/297] Move unsigned MIN and MAX into signedness_dependent_methods --- library/core/src/num/nonzero.rs | 69 +++++++++++++-------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0c34012ab5c6..0ab89aa0d6c2 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -515,12 +515,37 @@ macro_rules! nonzero_integer_signedness_dependent_impls { #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974 macro_rules! nonzero_integer_signedness_dependent_methods { - // Methods for unsigned nonzero types only. + // Associated items for unsigned nonzero types only. ( Self = $Ty:ident, Primitive = unsigned $Int:ident, UnsignedPrimitive = $Uint:ty, ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, 1. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(1).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + /// Adds an unsigned integer to a non-zero value. /// Checks for overflow and returns [`None`] on overflow. /// As a consequence, the result cannot wrap to zero. @@ -1177,39 +1202,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_min_max_unsigned { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// The smallest value that can be represented by this non-zero - /// integer type, 1. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MIN: Self = Self::new(1).unwrap(); - - /// The largest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - } - )+ - } -} - macro_rules! nonzero_min_max_signed { ( $( $Ty: ident($Int: ident); )+ ) => { $( @@ -1252,15 +1244,6 @@ macro_rules! nonzero_min_max_signed { } } -nonzero_min_max_unsigned! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); -} - nonzero_min_max_signed! { NonZeroI8(i8); NonZeroI16(i16); From 66cda3b75fb35655076b1fa555bf4f95fdd9b54e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:50:31 -0800 Subject: [PATCH 152/297] Move signed MIN and MAX into signedness_dependent_methods --- library/core/src/num/nonzero.rs | 87 +++++++++++++-------------------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0ab89aa0d6c2..9c48a5b0dbdd 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -805,13 +805,47 @@ macro_rules! nonzero_integer_signedness_dependent_methods { } }; - // Methods for signed nonzero types only. + // Associated items for signed nonzero types only. ( Self = $Ty:ident, Primitive = signed $Int:ident, UnsignedNonZero = $Uty:ident, UnsignedPrimitive = $Uint:ty, ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + /// Computes the absolute value of self. #[doc = concat!("See [`", stringify!($Int), "::abs`]")] /// for documentation on overflow behaviour. @@ -1202,57 +1236,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_min_max_signed { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// The smallest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] - /// - /// Note: While most integer types are defined for every whole - /// number between `MIN` and `MAX`, signed non-zero integers are - /// a special case. They have a "gap" at 0. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); - - /// The largest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] - /// - /// Note: While most integer types are defined for every whole - /// number between `MIN` and `MAX`, signed non-zero integers are - /// a special case. They have a "gap" at 0. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - } - )+ - } -} - -nonzero_min_max_signed! { - NonZeroI8(i8); - NonZeroI16(i16); - NonZeroI32(i32); - NonZeroI64(i64); - NonZeroI128(i128); - NonZeroIsize(isize); -} - macro_rules! nonzero_bits { ( $( $Ty: ident($Int: ty); )+ ) => { $( From c53713274cc6c04cad7b903c597ff54e4cdc8d27 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:52:20 -0800 Subject: [PATCH 153/297] Move BITS into omnibus impl block --- library/core/src/num/nonzero.rs | 51 +++++++++------------------------ 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 9c48a5b0dbdd..0b42b628675a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -128,6 +128,20 @@ macro_rules! nonzero_integer { self.0 } + /// The size of this non-zero integer type in bits. + /// + #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] + /// ``` + #[stable(feature = "nonzero_bits", since = "1.67.0")] + pub const BITS: u32 = <$Int>::BITS; + /// Returns the number of leading zeros in the binary representation of `self`. /// /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. @@ -1236,43 +1250,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_bits { - ( $( $Ty: ident($Int: ty); )+ ) => { - $( - impl $Ty { - /// The size of this non-zero integer type in bits. - /// - #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// - #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] - /// ``` - #[stable(feature = "nonzero_bits", since = "1.67.0")] - pub const BITS: u32 = <$Int>::BITS; - } - )+ - } -} - -nonzero_bits! { - NonZeroU8(u8); - NonZeroI8(i8); - NonZeroU16(u16); - NonZeroI16(i16); - NonZeroU32(u32); - NonZeroI32(i32); - NonZeroU64(u64); - NonZeroI64(i64); - NonZeroU128(u128); - NonZeroI128(i128); - NonZeroUsize(usize); - NonZeroIsize(isize); -} - nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, From cdee1feb49989f13e5091c591fbba90ef9278add Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 6 Dec 2023 00:41:18 -0800 Subject: [PATCH 154/297] Unbreak tidy's feature parser tidy error: /git/rust/library/core/src/num/nonzero.rs:67: malformed stability attribute: missing `feature` key tidy error: /git/rust/library/core/src/num/nonzero.rs:82: malformed stability attribute: missing `feature` key tidy error: /git/rust/library/core/src/num/nonzero.rs:98: malformed stability attribute: missing the `since` key tidy error: /git/rust/library/core/src/num/nonzero.rs:112: malformed stability attribute: missing `feature` key tidy error: /git/rust/library/core/src/num/nonzero.rs:450: malformed stability attribute: missing `feature` key some tidy checks failed --- library/core/src/num/nonzero.rs | 83 ++++++++++++--------------------- 1 file changed, 31 insertions(+), 52 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0b42b628675a..174fa200737c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -24,12 +24,12 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( + #[$stability:meta] + #[$const_new_unchecked_stability:meta] Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, $(UnsignedNonZero = $UnsignedNonZero:ident,)? UnsignedPrimitive = $UnsignedPrimitive:ty, - feature = $feature:literal, - original_stabilization = $since:literal, // Used in doc comments. leading_zeros_test = $leading_zeros_test:expr, @@ -64,7 +64,7 @@ macro_rules! nonzero_integer { /// ``` /// /// [null pointer optimization]: crate::option#representation - #[stable(feature = $feature, since = $since)] + #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -79,8 +79,8 @@ macro_rules! nonzero_integer { /// # Safety /// /// The value must not be zero. - #[stable(feature = $feature, since = $since)] - #[rustc_const_stable(feature = $feature, since = $since)] + #[$stability] + #[$const_new_unchecked_stability] #[must_use] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { @@ -95,7 +95,7 @@ macro_rules! nonzero_integer { } /// Creates a non-zero if the given value is not zero. - #[stable(feature = $feature, since = $since)] + #[$stability] #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] #[must_use] #[inline] @@ -109,7 +109,7 @@ macro_rules! nonzero_integer { } /// Returns the value as a primitive type. - #[stable(feature = $feature, since = $since)] + #[$stability] #[inline] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] pub const fn get(self) -> $Int { @@ -151,7 +151,7 @@ macro_rules! nonzero_integer { /// Basic usage: /// /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($leading_zeros_test), ").unwrap();")] + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", $leading_zeros_test, ").unwrap();")] /// /// assert_eq!(n.leading_zeros(), 0); /// ``` @@ -461,8 +461,7 @@ macro_rules! nonzero_integer { } impl_nonzero_fmt! { - #[stable(feature = $feature, since = $since)] - (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } #[stable(feature = "nonzero_parse", since = "1.35.0")] @@ -478,6 +477,28 @@ macro_rules! nonzero_integer { nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int); }; + + (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => { + nonzero_integer! { + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + Self = $Ty, + Primitive = unsigned $Int, + UnsignedPrimitive = $Int, + leading_zeros_test = concat!(stringify!($Int), "::MAX"), + } + }; + + (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => { + nonzero_integer! { + #[stable(feature = "signed_nonzero", since = "1.34.0")] + #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] + Self = $Ty, + Primitive = signed $Int, + $($rest)* + leading_zeros_test = concat!("-1", stringify!($Int)), + } + }; } macro_rules! nonzero_integer_signedness_dependent_impls { @@ -1253,55 +1274,31 @@ macro_rules! sign_dependent_expr { nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, - UnsignedPrimitive = u8, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u8::MAX, } nonzero_integer! { Self = NonZeroU16, Primitive = unsigned u16, - UnsignedPrimitive = u16, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u16::MAX, } nonzero_integer! { Self = NonZeroU32, Primitive = unsigned u32, - UnsignedPrimitive = u32, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u32::MAX, } nonzero_integer! { Self = NonZeroU64, Primitive = unsigned u64, - UnsignedPrimitive = u64, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u64::MAX, } nonzero_integer! { Self = NonZeroU128, Primitive = unsigned u128, - UnsignedPrimitive = u128, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u128::MAX, } nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, - UnsignedPrimitive = usize, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = usize::MAX, } nonzero_integer! { @@ -1309,9 +1306,6 @@ nonzero_integer! { Primitive = signed i8, UnsignedNonZero = NonZeroU8, UnsignedPrimitive = u8, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i8, } nonzero_integer! { @@ -1319,9 +1313,6 @@ nonzero_integer! { Primitive = signed i16, UnsignedNonZero = NonZeroU16, UnsignedPrimitive = u16, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i16, } nonzero_integer! { @@ -1329,9 +1320,6 @@ nonzero_integer! { Primitive = signed i32, UnsignedNonZero = NonZeroU32, UnsignedPrimitive = u32, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i32, } nonzero_integer! { @@ -1339,9 +1327,6 @@ nonzero_integer! { Primitive = signed i64, UnsignedNonZero = NonZeroU64, UnsignedPrimitive = u64, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i64, } nonzero_integer! { @@ -1349,9 +1334,6 @@ nonzero_integer! { Primitive = signed i128, UnsignedNonZero = NonZeroU128, UnsignedPrimitive = u128, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i128, } nonzero_integer! { @@ -1359,7 +1341,4 @@ nonzero_integer! { Primitive = signed isize, UnsignedNonZero = NonZeroUsize, UnsignedPrimitive = usize, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1isize, } From 4efddb141a37577c6fc6a9a39248cc86b736750b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Jan 2024 10:55:08 +1100 Subject: [PATCH 155/297] Add some helpful comments in `trimmed_def_paths`. To explain things that took me a minute to work out. --- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a10bdc6012c0..4d9a1be2087f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3083,7 +3083,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { let mut map: DefIdMap = Default::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { - // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting. + // Trimming paths is expensive and not optimized, since we expect it to only be used for + // error reporting. // // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` // wrapper can be used to suppress this query, in exchange for full paths being formatted. @@ -3092,6 +3093,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { ); } + // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while + // non-unique pairs will have a `None` entry. let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option> = &mut FxHashMap::default(); @@ -3121,6 +3124,7 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { } }); + // Put the symbol from all the unique namespace+symbol pairs into `map`. for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() { use std::collections::hash_map::Entry::{Occupied, Vacant}; From 086d17b7cb77850ce9bc549b29082b6938a6c0d4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Jan 2024 11:08:06 +1100 Subject: [PATCH 156/297] Refactor `try_print_trimmed_def_path`. Inverting the condition lets us merge the two `Ok(false)` paths. I also find the inverted condition easier to read: "all the things that must be true for trimming to occur", instead of "any of the things that must be true for trimming to not occur". --- compiler/rustc_middle/src/ty/print/pretty.rs | 29 ++++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4d9a1be2087f..3c6ad90b2ea9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -365,26 +365,19 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Try to see if this path can be trimmed to a unique symbol name. fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result { - if with_forced_trimmed_paths() { - let trimmed = self.force_print_trimmed_def_path(def_id)?; - if trimmed { - return Ok(true); - } + if with_forced_trimmed_paths() && self.force_print_trimmed_def_path(def_id)? { + return Ok(true); } - if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths - || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) - || with_no_trimmed_paths() - || with_crate_prefix() + if self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths + && !matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) + && !with_no_trimmed_paths() + && !with_crate_prefix() + && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id) { - return Ok(false); - } - - match self.tcx().trimmed_def_paths(()).get(&def_id) { - None => Ok(false), - Some(symbol) => { - write!(self, "{}", Ident::with_dummy_span(*symbol))?; - Ok(true) - } + write!(self, "{}", Ident::with_dummy_span(*symbol))?; + Ok(true) + } else { + Ok(false) } } From 32de78cade63ae338bd6e0d47d2f9d7278d7edfc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Jan 2024 12:47:22 +1100 Subject: [PATCH 157/297] Replace `TrimmedDefPaths` with a bool. It's a tri-state enum but the `Always` variant is never used, so a bool is simpler. --- compiler/rustc_driver_impl/src/lib.rs | 4 ++-- compiler/rustc_middle/src/ty/print/pretty.rs | 24 +++++++++----------- compiler/rustc_session/src/config.rs | 22 +++--------------- compiler/rustc_session/src/options.rs | 2 +- 4 files changed, 17 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e4baf26176c..11dcf4108d4e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -35,7 +35,7 @@ use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; -use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths}; +use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; use rustc_session::{config, EarlyDiagCtxt, Session}; @@ -204,7 +204,7 @@ impl Callbacks for TimePassesCallbacks { // self.time_passes = (config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes) .then(|| config.opts.unstable_opts.time_passes_format); - config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath; + config.opts.trimmed_def_paths = true; } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3c6ad90b2ea9..6c9000c45f61 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -15,7 +15,6 @@ use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathDataName}; use rustc_hir::LangItem; -use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_session::Limit; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -369,7 +368,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { return Ok(true); } if self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths - && !matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) + && self.tcx().sess.opts.trimmed_def_paths && !with_no_trimmed_paths() && !with_crate_prefix() && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id) @@ -3073,18 +3072,16 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`]. // this is pub to be able to intra-doc-link it pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { - let mut map: DefIdMap = Default::default(); + assert!(tcx.sess.opts.trimmed_def_paths); - if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { - // Trimming paths is expensive and not optimized, since we expect it to only be used for - // error reporting. - // - // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` - // wrapper can be used to suppress this query, in exchange for full paths being formatted. - tcx.sess.good_path_delayed_bug( - "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", - ); - } + // Trimming paths is expensive and not optimized, since we expect it to only be used for error + // reporting. + // + // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` + // wrapper can be used to suppress this query, in exchange for full paths being formatted. + tcx.sess.good_path_delayed_bug( + "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", + ); // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while // non-unique pairs will have a `None` entry. @@ -3118,6 +3115,7 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { }); // Put the symbol from all the unique namespace+symbol pairs into `map`. + let mut map: DefIdMap = Default::default(); for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() { use std::collections::hash_map::Entry::{Occupied, Vacant}; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fe1166457bae..ac15c3b407b2 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -533,21 +533,6 @@ impl Default for ErrorOutputType { } } -/// Parameter to control path trimming. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] -pub enum TrimmedDefPaths { - /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive - /// query. - #[default] - Never, - /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call - /// `good_path_delayed_bug`. - Always, - /// `try_print_trimmed_def_path` calls the expensive query, the query calls - /// `good_path_delayed_bug`. - GoodPath, -} - #[derive(Clone, Hash, Debug)] pub enum ResolveDocLinks { /// Do not resolve doc links. @@ -1089,7 +1074,7 @@ impl Default for Options { debug_assertions: true, actually_rustdoc: false, resolve_doc_links: ResolveDocLinks::None, - trimmed_def_paths: TrimmedDefPaths::default(), + trimmed_def_paths: false, cli_forced_codegen_units: None, cli_forced_local_thinlto_off: false, remap_path_prefix: Vec::new(), @@ -2926,7 +2911,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M debug_assertions, actually_rustdoc: false, resolve_doc_links: ResolveDocLinks::ExportedMetadata, - trimmed_def_paths: TrimmedDefPaths::default(), + trimmed_def_paths: false, cli_forced_codegen_units: codegen_units, cli_forced_local_thinlto_off: disable_local_thinlto, remap_path_prefix, @@ -3210,7 +3195,7 @@ pub(crate) mod dep_tracking { LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - TrimmedDefPaths, WasiExecModel, + WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3305,7 +3290,6 @@ pub(crate) mod dep_tracking { SymbolManglingVersion, RemapPathScopeComponents, SourceFileHashAlgorithm, - TrimmedDefPaths, OutFileName, OutputType, RealFileName, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2d91a3fbd911..f4bf79f93f28 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -183,7 +183,7 @@ top_level_options!( resolve_doc_links: ResolveDocLinks [TRACKED], /// Control path trimming. - trimmed_def_paths: TrimmedDefPaths [TRACKED], + trimmed_def_paths: bool [TRACKED], /// Specifications of codegen units / ThinLTO which are forced as a /// result of parsing command line options. These are not necessarily From f7602232a5a27165fc5f8ead2c72adca97b1330a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jan 2024 11:49:03 +0100 Subject: [PATCH 158/297] Add private `NonZero` type alias. --- library/core/src/num/mod.rs | 24 ++++++----- library/core/src/num/nonzero.rs | 63 +++++++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 4 +- library/core/src/slice/iter.rs | 6 +-- 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 695e87aaabf8..f53a6f9e1340 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -59,6 +59,8 @@ pub use dec2flt::ParseFloatError; #[stable(feature = "rust1", since = "1.0.0")] pub use error::ParseIntError; +pub(crate) use nonzero::NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; @@ -482,7 +484,7 @@ impl u8 { Self = u8, ActualT = u8, SignedT = i8, - NonZeroT = NonZeroU8, + NonZeroT = NonZero, BITS = 8, MAX = 255, rot = 2, @@ -791,7 +793,7 @@ impl u8 { #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] pub const fn is_ascii_alphanumeric(&self) -> bool { - matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'Z') | matches!(*self, b'a'..=b'z') + matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z') } /// Checks if the value is an ASCII decimal digit: @@ -1097,7 +1099,7 @@ impl u16 { Self = u16, ActualT = u16, SignedT = i16, - NonZeroT = NonZeroU16, + NonZeroT = NonZero, BITS = 16, MAX = 65535, rot = 4, @@ -1146,7 +1148,7 @@ impl u32 { Self = u32, ActualT = u32, SignedT = i32, - NonZeroT = NonZeroU32, + NonZeroT = NonZero, BITS = 32, MAX = 4294967295, rot = 8, @@ -1170,7 +1172,7 @@ impl u64 { Self = u64, ActualT = u64, SignedT = i64, - NonZeroT = NonZeroU64, + NonZeroT = NonZero, BITS = 64, MAX = 18446744073709551615, rot = 12, @@ -1194,7 +1196,7 @@ impl u128 { Self = u128, ActualT = u128, SignedT = i128, - NonZeroT = NonZeroU128, + NonZeroT = NonZero, BITS = 128, MAX = 340282366920938463463374607431768211455, rot = 16, @@ -1204,9 +1206,9 @@ impl u128 { swapped = "0x12907856341290785634129078563412", reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ - 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", to_xe_bytes_doc = "", from_xe_bytes_doc = "", bound_condition = "", @@ -1220,7 +1222,7 @@ impl usize { Self = usize, ActualT = u16, SignedT = isize, - NonZeroT = NonZeroUsize, + NonZeroT = NonZero, BITS = 16, MAX = 65535, rot = 4, @@ -1245,7 +1247,7 @@ impl usize { Self = usize, ActualT = u32, SignedT = isize, - NonZeroT = NonZeroUsize, + NonZeroT = NonZero, BITS = 32, MAX = 4294967295, rot = 8, @@ -1270,7 +1272,7 @@ impl usize { Self = usize, ActualT = u64, SignedT = isize, - NonZeroT = NonZeroUsize, + NonZeroT = NonZero, BITS = 64, MAX = 18446744073709551615, rot = 12, diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 2df38ab5848a..715c3a0b8ac3 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -8,6 +8,69 @@ use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; use crate::intrinsics; +mod private { + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + #[const_trait] + pub trait Sealed {} +} + +/// A marker trait for primitive types which can be zero. +/// +/// This is an implementation detail for [`NonZero`](NonZero) which may disappear or be replaced at any time. +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +#[const_trait] +pub trait ZeroablePrimitive: Sized + Copy + private::Sealed { + type NonZero; +} + +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +pub(crate) type NonZero = ::NonZero; + +macro_rules! impl_zeroable_primitive { + ($NonZero:ident ( $primitive:ty )) => { + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + impl const private::Sealed for $primitive {} + + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + impl const ZeroablePrimitive for $primitive { + type NonZero = $NonZero; + } + }; +} + +impl_zeroable_primitive!(NonZeroU8(u8)); +impl_zeroable_primitive!(NonZeroU16(u16)); +impl_zeroable_primitive!(NonZeroU32(u32)); +impl_zeroable_primitive!(NonZeroU64(u64)); +impl_zeroable_primitive!(NonZeroU128(u128)); +impl_zeroable_primitive!(NonZeroUsize(usize)); +impl_zeroable_primitive!(NonZeroI8(i8)); +impl_zeroable_primitive!(NonZeroI16(i16)); +impl_zeroable_primitive!(NonZeroI32(i32)); +impl_zeroable_primitive!(NonZeroI64(i64)); +impl_zeroable_primitive!(NonZeroI128(i128)); +impl_zeroable_primitive!(NonZeroIsize(isize)); + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 11a53aaf122e..bbbbd61c4b1c 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3,7 +3,7 @@ macro_rules! uint_impl { Self = $SelfT:ty, ActualT = $ActualT:ident, SignedT = $SignedT:ident, - NonZeroT = $NonZeroT:ident, + NonZeroT = $NonZeroT:ty, // There are all for use *only* in doc comments. // As such, they're all passed as literals -- passing them as a string @@ -842,6 +842,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_ilog2(self) -> Option { + // FIXME: Simply use `NonZero::new` once it is actually generic. if let Some(x) = <$NonZeroT>::new(self) { Some(x.ilog2()) } else { @@ -864,6 +865,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_ilog10(self) -> Option { + // FIXME: Simply use `NonZero::new` once it is actually generic. if let Some(x) = <$NonZeroT>::new(self) { Some(x.ilog10()) } else { diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 3d58afd26eac..4a64faf9b3f2 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -12,7 +12,7 @@ use crate::iter::{ }; use crate::marker::PhantomData; use crate::mem::{self, SizedTypeProperties}; -use crate::num::NonZeroUsize; +use crate::num::{NonZero, NonZeroUsize}; use crate::ptr::{self, invalid, invalid_mut, NonNull}; use super::{from_raw_parts, from_raw_parts_mut}; @@ -1305,12 +1305,12 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Windows<'a, T: 'a> { v: &'a [T], - size: NonZeroUsize, + size: NonZero, } impl<'a, T: 'a> Windows<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self { + pub(super) fn new(slice: &'a [T], size: NonZero) -> Self { Self { v: slice, size } } } From 70b03645002e50fbe0c8ed29a0b0e801ace48a10 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 15 Jan 2024 16:26:25 +0100 Subject: [PATCH 159/297] std: move OS String implementation into `sys` --- library/std/src/sys/mod.rs | 1 + .../src/sys/{pal/unix/os_str.rs => os_str/bytes.rs} | 1 - .../sys/{pal/unix/os_str => os_str/bytes}/tests.rs | 0 library/std/src/sys/os_str/mod.rs | 12 ++++++++++++ .../sys/{pal/windows/os_str.rs => os_str/wtf8.rs} | 0 library/std/src/sys/pal/hermit/mod.rs | 2 -- library/std/src/sys/pal/sgx/mod.rs | 2 -- library/std/src/sys/pal/solid/mod.rs | 2 -- library/std/src/sys/pal/teeos/mod.rs | 2 -- library/std/src/sys/pal/uefi/mod.rs | 2 -- library/std/src/sys/pal/unix/mod.rs | 1 - library/std/src/sys/pal/unsupported/mod.rs | 2 -- library/std/src/sys/pal/wasi/mod.rs | 2 -- library/std/src/sys/pal/wasm/mod.rs | 2 -- library/std/src/sys/pal/windows/mod.rs | 1 - library/std/src/sys/pal/xous/mod.rs | 2 -- 16 files changed, 13 insertions(+), 21 deletions(-) rename library/std/src/sys/{pal/unix/os_str.rs => os_str/bytes.rs} (99%) rename library/std/src/sys/{pal/unix/os_str => os_str/bytes}/tests.rs (100%) create mode 100644 library/std/src/sys/os_str/mod.rs rename library/std/src/sys/{pal/windows/os_str.rs => os_str/wtf8.rs} (100%) diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index bbdcb32606cc..d95c0d8d0628 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -3,6 +3,7 @@ /// descriptors. mod pal; +pub mod os_str; mod personality; // FIXME(117276): remove this, move feature implementations into individual diff --git a/library/std/src/sys/pal/unix/os_str.rs b/library/std/src/sys/os_str/bytes.rs similarity index 99% rename from library/std/src/sys/pal/unix/os_str.rs rename to library/std/src/sys/os_str/bytes.rs index 7bd2f656a24e..3a75ce9ebb78 100644 --- a/library/std/src/sys/pal/unix/os_str.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -14,7 +14,6 @@ use crate::sys_common::{AsInner, IntoInner}; use core::str::Utf8Chunks; #[cfg(test)] -#[path = "../unix/os_str/tests.rs"] mod tests; #[derive(Hash)] diff --git a/library/std/src/sys/pal/unix/os_str/tests.rs b/library/std/src/sys/os_str/bytes/tests.rs similarity index 100% rename from library/std/src/sys/pal/unix/os_str/tests.rs rename to library/std/src/sys/os_str/bytes/tests.rs diff --git a/library/std/src/sys/os_str/mod.rs b/library/std/src/sys/os_str/mod.rs new file mode 100644 index 000000000000..b509729475bf --- /dev/null +++ b/library/std/src/sys/os_str/mod.rs @@ -0,0 +1,12 @@ +cfg_if::cfg_if! { + if #[cfg(any( + target_os = "windows", + target_os = "uefi", + ))] { + mod wtf8; + pub use wtf8::{Buf, Slice}; + } else { + mod bytes; + pub use bytes::{Buf, Slice}; + } +} diff --git a/library/std/src/sys/pal/windows/os_str.rs b/library/std/src/sys/os_str/wtf8.rs similarity index 100% rename from library/std/src/sys/pal/windows/os_str.rs rename to library/std/src/sys/os_str/wtf8.rs diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 937603cfd8a0..503362969196 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -30,8 +30,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 09d3f7638ca2..893c5f765a79 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -24,8 +24,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 5af83653cf84..5742ce9d72c6 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -31,8 +31,6 @@ pub mod fs; pub mod io; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index ed8c54b2c36f..764a4e6ad35e 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -27,8 +27,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 4edc00e3ea02..fb1a531182a7 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -28,8 +28,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../windows/os_str.rs"] -pub mod os_str; pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index b5da5f870ec1..86027c2b0b0a 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -29,7 +29,6 @@ pub mod net; #[cfg(target_os = "l4re")] pub use self::l4re::net; pub mod os; -pub mod os_str; pub mod path; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index e1a38de64711..6254c67a2a3b 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -11,8 +11,6 @@ pub mod locks; pub mod net; pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; pub mod pipe; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 5919cc506d92..c1fc053bf049 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -32,8 +32,6 @@ pub mod io; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 6c05b56e1bfc..d2181565887f 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -30,8 +30,6 @@ pub mod io; pub mod net; #[path = "../unsupported/os.rs"] pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 8b722f01a5d3..d097a7b8bb26 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -24,7 +24,6 @@ pub mod locks; pub mod memchr; pub mod net; pub mod os; -pub mod os_str; pub mod path; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index c2550dcfd831..230067907c8f 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -17,8 +17,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] From 9a8f117d7b20e5503b8499112c26076cbbf570eb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 15 Jan 2024 15:49:58 +0000 Subject: [PATCH 160/297] Don't create the array type twice --- compiler/rustc_hir_typeck/src/expr.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index af47455c16df..a08f36ddfda1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1526,13 +1526,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_repeat_element_needs_copy_bound(element, count, element_ty); - self.register_wf_obligation( - Ty::new_array_with_const_len(tcx, t, count).into(), - expr.span, - traits::WellFormed(None), - ); + let ty = Ty::new_array_with_const_len(tcx, t, count); - Ty::new_array_with_const_len(tcx, t, count) + self.register_wf_obligation(ty.into(), expr.span, traits::WellFormed(None)); + + ty } fn check_repeat_element_needs_copy_bound( From 2ad780eaf03816ae26cd4285eb379e2bb0c55672 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:18:48 +0100 Subject: [PATCH 161/297] Clarify that the status of `&!` is undecided --- compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f6c5e4a5cd6e..1b7be98600ff 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -289,7 +289,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { fn is_known_valid_scrutinee(&self, scrutinee: &Expr<'tcx>) -> bool { use ExprKind::*; match &scrutinee.kind { - // Both pointers and references can validly point to a place with invalid data. + // Pointers can validly point to a place with invalid data. It is undecided whether + // references can too, so we conservatively assume they can. Deref { .. } => false, // Inherit validity of the parent place, unless the parent is an union. Field { lhs, .. } => { From bf913ad0aee7e97b93f50824e9b2292414670954 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:42:23 +0100 Subject: [PATCH 162/297] Simplify use of `ValidityConstraint` We had reached a point where the shenanigans about omitting empty arms are unnecessary. --- .../rustc_pattern_analysis/src/usefulness.rs | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 6244cf0ff7d7..72459582113b 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -768,9 +768,6 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { pub enum ValidityConstraint { ValidOnly, MaybeInvalid, - /// Option for backwards compatibility: the place is not known to be valid but we allow omitting - /// `useful && !reachable` arms anyway. - MaybeInvalidButAllowOmittingArms, } impl ValidityConstraint { @@ -778,20 +775,9 @@ impl ValidityConstraint { if is_valid_only { ValidOnly } else { MaybeInvalid } } - fn allow_omitting_side_effecting_arms(self) -> Self { - match self { - MaybeInvalid | MaybeInvalidButAllowOmittingArms => MaybeInvalidButAllowOmittingArms, - // There are no side-effecting empty arms here, nothing to do. - ValidOnly => ValidOnly, - } - } - fn is_known_valid(self) -> bool { matches!(self, ValidOnly) } - fn allows_omitting_empty_arms(self) -> bool { - matches!(self, ValidOnly | MaybeInvalidButAllowOmittingArms) - } /// If the place has validity given by `self` and we read that the value at the place has /// constructor `ctor`, this computes what we can assume about the validity of the constructor @@ -814,7 +800,7 @@ impl fmt::Display for ValidityConstraint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { ValidOnly => "✓", - MaybeInvalid | MaybeInvalidButAllowOmittingArms => "?", + MaybeInvalid => "?", }; write!(f, "{s}") } @@ -1460,8 +1446,6 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // Whether the place/column we are inspecting is known to contain valid data. let place_validity = matrix.place_validity[0]; - // For backwards compability we allow omitting some empty arms that we ideally shouldn't. - let place_validity = place_validity.allow_omitting_side_effecting_arms(); // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); @@ -1486,12 +1470,9 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". let report_individual_missing_ctors = always_report_all || !all_missing; // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => - // split_ctors.contains(Missing)`. The converse usually holds except in the - // `MaybeInvalidButAllowOmittingArms` backwards-compatibility case. - let mut missing_ctors = split_set.missing; - if !place_validity.allows_omitting_empty_arms() { - missing_ctors.extend(split_set.missing_empty); - } + // split_ctors.contains(Missing)`. The converse usually holds except when + // `!place_validity.is_known_valid()`. + let missing_ctors = split_set.missing; let mut ret = WitnessMatrix::empty(); for ctor in split_ctors { From edb27a306a29b5b3e9f63da3e74e985736905bc2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:23:21 +0100 Subject: [PATCH 163/297] Make all the empty pattern decisions in `usefulness` --- .../rustc_pattern_analysis/src/constructor.rs | 19 +++++-------------- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- .../rustc_pattern_analysis/src/usefulness.rs | 18 +++++++++++++----- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index c1042d5b66ec..af5538408985 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -858,12 +858,14 @@ impl ConstructorSet { /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation /// and its invariants. - #[instrument(level = "debug", skip(self, pcx, ctors), ret)] + #[instrument(level = "debug", skip(self, ctors), ret)] pub(crate) fn split<'a>( &self, - pcx: &PlaceCtxt<'a, Cx>, ctors: impl Iterator> + Clone, - ) -> SplitConstructorSet { + ) -> SplitConstructorSet + where + Cx: 'a, + { let mut present: SmallVec<[_; 1]> = SmallVec::new(); // Empty constructors found missing. let mut missing_empty = Vec::new(); @@ -1003,17 +1005,6 @@ impl ConstructorSet { } } - // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty. - // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty - // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty. - if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on() - && !(pcx.is_scrutinee && matches!(self, Self::NoConstructors)) - { - // Treat all missing constructors as nonempty. - // This clears `missing_empty`. - missing.append(&mut missing_empty); - } - SplitConstructorSet { present, missing, missing_empty } } } diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index cfe4ca3ce93d..cf3dddfafeb0 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -59,7 +59,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { ) -> Result, ErrorGuaranteed> { let column_ctors = self.patterns.iter().map(|p| p.ctor()); let ctors_for_ty = &pcx.ctors_for_ty()?; - Ok(ctors_for_ty.split(pcx, column_ctors)) + Ok(ctors_for_ty.split(column_ctors)) } /// Does specialization: given a constructor, this takes the patterns from the column that match diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 72459582113b..490a84c65db5 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -737,15 +737,13 @@ pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { pub(crate) mcx: MatchCtxt<'a, Cx>, /// Type of the place under investigation. pub(crate) ty: Cx::Ty, - /// Whether the place is the original scrutinee place, as opposed to a subplace of it. - pub(crate) is_scrutinee: bool, } impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { /// A `PlaceCtxt` when code other than `is_useful` needs one. #[cfg_attr(not(feature = "rustc"), allow(dead_code))] pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: Cx::Ty) -> Self { - PlaceCtxt { mcx, ty, is_scrutinee: false } + PlaceCtxt { mcx, ty } } pub(crate) fn ctor_arity(&self, ctor: &Constructor) -> usize { @@ -1442,7 +1440,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { mcx, ty, is_scrutinee: is_top_level }; + let pcx = &PlaceCtxt { mcx, ty }; // Whether the place/column we are inspecting is known to contain valid data. let place_validity = matrix.place_validity[0]; @@ -1451,7 +1449,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( let ctors = matrix.heads().map(|p| p.ctor()); let ctors_for_ty = pcx.ctors_for_ty()?; let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics. - let split_set = ctors_for_ty.split(pcx, ctors); + let mut split_set = ctors_for_ty.split(ctors); + // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty. + // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty + // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty. + if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on() + && !(is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors)) + { + // Treat all missing constructors as nonempty. + // This clears `missing_empty`. + split_set.missing.append(&mut split_set.missing_empty); + } let all_missing = split_set.present.is_empty(); // Build the set of constructors we will specialize with. It must cover the whole type. From de77f1a86ef732d3cbffd284bb32c5908a535748 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:47:52 +0100 Subject: [PATCH 164/297] Simplify empty pattern logic a bit --- .../rustc_pattern_analysis/src/usefulness.rs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 490a84c65db5..ec9cbeb4fefe 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1441,21 +1441,20 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( debug!("ty: {ty:?}"); let pcx = &PlaceCtxt { mcx, ty }; + let ctors_for_ty = pcx.ctors_for_ty()?; // Whether the place/column we are inspecting is known to contain valid data. let place_validity = matrix.place_validity[0]; + // We treat match scrutinees of type `!` or `EmptyEnum` differently. + let is_toplevel_exception = + is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); + // Whether empty patterns can be omitted for exhaustiveness. + let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on(); // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); - let ctors_for_ty = pcx.ctors_for_ty()?; - let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics. let mut split_set = ctors_for_ty.split(ctors); - // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty. - // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty - // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty. - if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on() - && !(is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors)) - { + if !can_omit_empty_arms { // Treat all missing constructors as nonempty. // This clears `missing_empty`. split_set.missing.append(&mut split_set.missing_empty); @@ -1463,17 +1462,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( let all_missing = split_set.present.is_empty(); // Build the set of constructors we will specialize with. It must cover the whole type. + // We need to iterate over a full set of constructors, so we add `Missing` to represent the + // missing ones. This is explained under "Constructor Splitting" at the top of this file. let mut split_ctors = split_set.present; - if !split_set.missing.is_empty() { - // We need to iterate over a full set of constructors, so we add `Missing` to represent the - // missing ones. This is explained under "Constructor Splitting" at the top of this file. - split_ctors.push(Constructor::Missing); - } else if !split_set.missing_empty.is_empty() && !place_validity.is_known_valid() { - // The missing empty constructors are reachable if the place can contain invalid data. + if !(split_set.missing.is_empty() + && (split_set.missing_empty.is_empty() || place_validity.is_known_valid())) + { split_ctors.push(Constructor::Missing); } // Decide what constructors to report. + let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); let always_report_all = is_top_level && !is_integers; // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". let report_individual_missing_ctors = always_report_all || !all_missing; From d95644d3ae276ba787cdf9214a97f27b82c1348e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 23:08:31 +0100 Subject: [PATCH 165/297] Simplify empty pattern logic some more --- compiler/rustc_pattern_analysis/src/usefulness.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index ec9cbeb4fefe..d8c63e0571db 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1450,23 +1450,19 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns can be omitted for exhaustiveness. let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on(); + // Whether empty patterns are counted as useful or not. + let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms; // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); let mut split_set = ctors_for_ty.split(ctors); - if !can_omit_empty_arms { - // Treat all missing constructors as nonempty. - // This clears `missing_empty`. - split_set.missing.append(&mut split_set.missing_empty); - } let all_missing = split_set.present.is_empty(); - // Build the set of constructors we will specialize with. It must cover the whole type. // We need to iterate over a full set of constructors, so we add `Missing` to represent the // missing ones. This is explained under "Constructor Splitting" at the top of this file. let mut split_ctors = split_set.present; if !(split_set.missing.is_empty() - && (split_set.missing_empty.is_empty() || place_validity.is_known_valid())) + && (split_set.missing_empty.is_empty() || empty_arms_are_unreachable)) { split_ctors.push(Constructor::Missing); } @@ -1479,7 +1475,10 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => // split_ctors.contains(Missing)`. The converse usually holds except when // `!place_validity.is_known_valid()`. - let missing_ctors = split_set.missing; + let mut missing_ctors = split_set.missing; + if !can_omit_empty_arms { + missing_ctors.append(&mut split_set.missing_empty); + } let mut ret = WitnessMatrix::empty(); for ctor in split_ctors { From 0a049cb71e884bf430e33515e2ad4a09bc6443d0 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:00:28 -0500 Subject: [PATCH 166/297] Update books --- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/nomicon b/src/doc/nomicon index f6bd083c4ccf..6bc2415218d4 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit f6bd083c4ccfc4ce6699b8b4154e3c45c5a27a8c +Subproject commit 6bc2415218d4dd0cb01433d8320f5ccf79c343a1 diff --git a/src/doc/reference b/src/doc/reference index 3565c7978cfc..8c77e8be9da1 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3565c7978cfc9662f5963b135690ff9cbbfa0318 +Subproject commit 8c77e8be9da1a9c70545556218d563c8d061f1fd diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index c0be6299e52e..ddf5cb0e6ee5 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit c0be6299e52e4164c30ba6f41bd0ad0aaee64972 +Subproject commit ddf5cb0e6ee54ba2dd84c8ca3e1314120014e20d diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index d13e85152a97..4af29d1a7f64 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit d13e85152a977cd0bcaf583cf5f49e86225697de +Subproject commit 4af29d1a7f64f88a36539662c6a84fe1fbe6cde1 From 65409c46096886a6f25bf0d327e23613c821f0ea Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Mon, 15 Jan 2024 12:26:45 -0500 Subject: [PATCH 167/297] Ensure `callee_id`s are body owners --- src/tools/clippy/clippy_lints/src/derive.rs | 4 +-- .../src/loops/explicit_iter_loop.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 30 +++++++------------ 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index d8abe411030b..a8217d0602a5 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -450,12 +450,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) - && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[]) + && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]) // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[])) + .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index c7980060807c..814ccaa36f5a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>( .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output && let param_env = cx.tcx.param_env(fn_id) - && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[]) + && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[]) && let Some(into_iter_ty) = make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 61d0663aa839..a07d6587bf97 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -214,36 +214,21 @@ pub fn implements_trait<'tcx>( trait_id: DefId, args: &[GenericArg<'tcx>], ) -> bool { - let callee_id = cx - .enclosing_body - .map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id()); - implements_trait_with_env_from_iter( - cx.tcx, - cx.param_env, - ty, - trait_id, - callee_id, - args.iter().map(|&x| Some(x)), - ) + implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. +/// +/// The `callee_id` argument is used to determine the "effect arg", if one is needed. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, - callee_id: DefId, + callee_id: Option, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter( - tcx, - param_env, - ty, - trait_id, - Some(callee_id), - args.iter().map(|&x| Some(x)), - ) + implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait_from_env` but takes the arguments as an iterator. @@ -258,6 +243,11 @@ pub fn implements_trait_with_env_from_iter<'tcx>( // Clippy shouldn't have infer types assert!(!ty.has_infer()); + // If a `callee_id` is passed, then "assert" it is a body owner. + if let Some(callee_id) = callee_id { + let _ = tcx.hir().body_owner_kind(callee_id); + } + let ty = tcx.erase_regions(ty); if ty.has_escaping_bound_vars() { return false; From ee370a1157be0b0260a7804c91a8e78fd03e932a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 15 Jan 2024 09:23:05 -0800 Subject: [PATCH 168/297] Consistently unset RUSTC_BOOTSTRAP when compiling bootstrap --- src/bootstrap/bootstrap.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index fea194a80efb..6f3be1f6e938 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -917,6 +917,19 @@ class RustBuild(object): if toml_val is not None: env["{}_{}".format(var_name, host_triple_sanitized)] = toml_val + # In src/etc/rust_analyzer_settings.json, we configure rust-analyzer to + # pass RUSTC_BOOTSTRAP=1 to all cargo invocations because the standard + # library uses unstable Cargo features. Without RUSTC_BOOTSTRAP, + # rust-analyzer would fail to fetch workspace layout when the system's + # default toolchain is not nightly. + # + # But that setting has the collateral effect of rust-analyzer also + # passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various + # overrideCommand). For compiling bootstrap, that is unwanted and can + # cause spurious rebuilding of bootstrap when rust-analyzer x.py + # invocations are interleaved with handwritten ones on the command line. + env.pop("RUSTC_BOOTSTRAP", None) + # preserve existing RUSTFLAGS env.setdefault("RUSTFLAGS", "") From 924ea05103da3bd25e6021535615ca7f8b9ec76d Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 12 Jan 2024 08:22:05 +0100 Subject: [PATCH 169/297] Implement TypeVisitable and TypeFoldable for Spanned The traits are already implemented for Span, so it makes sense to also have them for Spanned (upcoming commits will make use of this). --- .../rustc_middle/src/ty/structural_impls.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7c869adbd832..11b579a1f85b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -9,6 +9,7 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; +use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; @@ -819,3 +820,27 @@ impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { visitor.visit_ty(self.ty) } } + +impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeVisitable> + for Spanned +{ + fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + self.node.visit_with(visitor)?; + self.span.visit_with(visitor)?; + ControlFlow::Continue(()) + } +} + +impl<'tcx, T: TypeFoldable> + Debug + Clone> TypeFoldable> + for Spanned +{ + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + Ok(Spanned { + node: self.node.try_fold_with(folder)?, + span: self.span.try_fold_with(folder)?, + }) + } +} From 16ba56c24238b2f44e0a97da760c83d8795abd80 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 12 Jan 2024 08:21:42 +0100 Subject: [PATCH 170/297] compiler: Lower fn call arg spans down to MIR To enable improved accuracy of diagnostics in upcoming commits. --- .../src/diagnostics/conflict_errors.rs | 8 +- .../src/diagnostics/explain_borrow.rs | 2 +- .../rustc_borrowck/src/diagnostics/mod.rs | 7 +- compiler/rustc_borrowck/src/lib.rs | 2 +- .../src/polonius/loan_invalidations.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 9 +- .../rustc_codegen_cranelift/src/abi/mod.rs | 13 +-- .../src/intrinsics/llvm.rs | 2 +- .../src/intrinsics/llvm_aarch64.rs | 2 +- .../src/intrinsics/llvm_x86.rs | 86 +++++++++---------- .../src/intrinsics/mod.rs | 22 +++-- .../src/intrinsics/simd.rs | 24 +++--- compiler/rustc_codegen_ssa/src/mir/block.rs | 21 +++-- .../src/interpret/terminator.rs | 8 +- .../src/transform/check_consts/check.rs | 4 +- .../src/transform/validate.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 5 +- compiler/rustc_middle/src/mir/visit.rs | 2 +- .../rustc_middle/src/util/find_self_call.rs | 9 +- .../src/build/custom/parse/instruction.rs | 5 +- .../src/build/expr/as_rvalue.rs | 10 ++- .../rustc_mir_build/src/build/expr/into.rs | 6 +- .../rustc_mir_build/src/build/matches/test.rs | 10 ++- compiler/rustc_mir_build/src/build/scope.rs | 5 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 7 +- .../src/move_paths/builder.rs | 2 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 6 +- .../src/dead_store_elimination.rs | 4 +- .../src/deduce_param_attrs.rs | 2 +- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- .../src/function_item_references.rs | 9 +- compiler/rustc_mir_transform/src/inline.rs | 17 ++-- .../rustc_mir_transform/src/instsimplify.rs | 4 +- compiler/rustc_mir_transform/src/lib.rs | 12 +-- compiler/rustc_mir_transform/src/lint.rs | 2 +- .../src/lower_intrinsics.rs | 24 +++--- .../src/lower_slice_len.rs | 2 +- .../rustc_mir_transform/src/promote_consts.rs | 7 +- compiler/rustc_mir_transform/src/shim.rs | 5 +- compiler/rustc_monomorphize/src/collector.rs | 4 +- .../rustc_smir/src/rustc_smir/convert/mir.rs | 2 +- compiler/rustc_span/src/source_map.rs | 2 +- .../clippy_lints/src/redundant_clone.rs | 4 +- .../clippy_utils/src/mir/possible_borrower.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 47 files changed, 221 insertions(+), 170 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index b4a73574aa2e..8909f47af2d8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1257,7 +1257,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return None; }; debug!("checking call args for uses of inner_param: {:?}", args); - args.contains(&Operand::Move(inner_param)).then_some((loc, term)) + args.iter() + .map(|a| &a.node) + .any(|a| a == &Operand::Move(inner_param)) + .then_some((loc, term)) }) else { debug!("no uses of inner_param found as a by-move call arg"); @@ -3242,7 +3245,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assigned_to, args ); for operand in args { - let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand + let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = + &operand.node else { continue; }; diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 6606be2f9f42..4f66468a865f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -691,7 +691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Check if one of the arguments to this function is the target place. let found_target = args.iter().any(|arg| { - if let Operand::Move(place) = arg { + if let Operand::Move(place) = arg.node { if let Some(potential) = place.as_local() { potential == target } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index bb802c4eb461..0f22fc21d3c9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -23,6 +23,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::util::{call_kind, CallDesugaringKind}; use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::def_id::LocalDefId; +use rustc_span::source_map::Spanned; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; @@ -111,9 +112,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("add_moved_or_invoked_closure_note: id={:?}", id); if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() { let closure = match args.first() { - Some(Operand::Copy(place) | Operand::Move(place)) - if target == place.local_or_deref_local() => - { + Some(Spanned { + node: Operand::Copy(place) | Operand::Move(place), .. + }) if target == place.local_or_deref_local() => { place.local_or_deref_local().unwrap() } _ => return false, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 0457b4e6ddc7..b304fb5589f3 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -703,7 +703,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } => { self.consume_operand(loc, (func, span), flow_state); for arg in args { - self.consume_operand(loc, (arg, span), flow_state); + self.consume_operand(loc, (&arg.node, arg.span), flow_state); } self.mutate_place(loc, (*destination, span), Deep, flow_state); } diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 232bd7418259..5c9056272cc0 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -120,7 +120,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { } => { self.consume_operand(location, func); for arg in args { - self.consume_operand(location, arg); + self.consume_operand(location, &arg.node); } self.mutate_place(location, *destination, Deep); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9c0f53ddb86f..33190e19104d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -36,6 +36,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArgsRef, UserArgs}; use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; @@ -1359,7 +1360,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { TerminatorKind::Call { func, args, destination, call_source, target, .. } => { self.check_operand(func, term_location); for arg in args { - self.check_operand(arg, term_location); + self.check_operand(&arg.node, term_location); } let func_ty = func.ty(body, tcx); @@ -1580,7 +1581,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { term: &Terminator<'tcx>, func: &Operand<'tcx>, sig: &ty::FnSig<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], term_location: Location, call_source: CallSource, ) { @@ -1593,7 +1594,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if self.tcx().is_intrinsic(def_id) { match self.tcx().item_name(def_id) { sym::simd_shuffle => { - if !matches!(args[2], Operand::Constant(_)) { + if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) { self.tcx() .dcx() .emit_err(SimdShuffleLastConst { span: term.source_info.span }); @@ -1606,7 +1607,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!(?func_ty); for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { - let op_arg_ty = op_arg.ty(body, self.tcx()); + let op_arg_ty = op_arg.node.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if call_source.from_hir_call() { diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 795c8daec6a3..abd70dd4458f 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -11,6 +11,7 @@ use cranelift_module::ModuleError; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; use rustc_session::Session; +use rustc_span::source_map::Spanned; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -360,7 +361,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, func: &Operand<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], destination: Place<'tcx>, target: Option, ) { @@ -415,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let extra_args = &args[fn_sig.inputs().skip_binder().len()..]; let extra_args = fx.tcx.mk_type_list_from_iter( - extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))), + extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))), ); let fn_abi = if let Some(instance) = instance { RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) @@ -440,10 +441,10 @@ pub(crate) fn codegen_terminator_call<'tcx>( // Unpack arguments tuple for closures let mut args = if fn_sig.abi() == Abi::RustCall { let (self_arg, pack_arg) = match args { - [pack_arg] => (None, codegen_call_argument_operand(fx, pack_arg)), + [pack_arg] => (None, codegen_call_argument_operand(fx, &pack_arg.node)), [self_arg, pack_arg] => ( - Some(codegen_call_argument_operand(fx, self_arg)), - codegen_call_argument_operand(fx, pack_arg), + Some(codegen_call_argument_operand(fx, &self_arg.node)), + codegen_call_argument_operand(fx, &pack_arg.node), ), _ => panic!("rust-call abi requires one or two arguments"), }; @@ -463,7 +464,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } args } else { - args.iter().map(|arg| codegen_call_argument_operand(fx, arg)).collect::>() + args.iter().map(|arg| codegen_call_argument_operand(fx, &arg.node)).collect::>() }; // Pass the caller location for `#[track_caller]`. diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index a38a728c926d..1345c4614e25 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -7,7 +7,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs index c8f9c3997a63..f6f3b85d3ef8 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs @@ -7,7 +7,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, _args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, ) { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 81114cbf40d8..994dc66835cd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -11,7 +11,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, _args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, @@ -175,9 +175,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [x, y, kind] => (x, y, kind), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); - let kind = match kind { + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); + let kind = match &kind.node { Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, Operand::Copy(_) | Operand::Move(_) => unreachable!("{kind:?}"), }; @@ -287,8 +287,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [a, b] => (a, b), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let a = codegen_operand(fx, a); - let b = codegen_operand(fx, b); + let a = codegen_operand(fx, &a.node); + let b = codegen_operand(fx, &b.node); // Based on the pseudocode at https://github.com/rust-lang/stdarch/blob/1cfbca8b38fd9b4282b2f054f61c6ca69fc7ce29/crates/core_arch/src/x86/avx2.rs#L2319-L2332 let zero = fx.bcx.ins().iconst(types::I8, 0); @@ -325,9 +325,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [a, b, imm8] => (a, b, imm8), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let a = codegen_operand(fx, a); - let b = codegen_operand(fx, b); - let imm8 = codegen_operand(fx, imm8).load_scalar(fx); + let a = codegen_operand(fx, &a.node); + let b = codegen_operand(fx, &b.node); + let imm8 = codegen_operand(fx, &imm8.node).load_scalar(fx); let a_low = a.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); let a_high = a.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); @@ -956,14 +956,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = b.load_scalar(fx); let lb = lb.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) - { - imm8 - } else { - fx.tcx - .dcx() - .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1009,14 +1009,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = b.load_scalar(fx); let lb = lb.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) - { - imm8 - } else { - fx.tcx - .dcx() - .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1056,15 +1056,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2]) - { - imm8 - } else { - fx.tcx.dcx().span_fatal( - span, - "Index argument for `_mm_clmulepi64_si128` is not a constant", - ); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2].node) { + imm8 + } else { + fx.tcx.dcx().span_fatal( + span, + "Index argument for `_mm_clmulepi64_si128` is not a constant", + ); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1093,15 +1093,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let a = a.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1]) - { - imm8 - } else { - fx.tcx.dcx().span_fatal( - span, - "Index argument for `_mm_aeskeygenassist_si128` is not a constant", - ); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1].node) { + imm8 + } else { + fx.tcx.dcx().span_fatal( + span, + "Index argument for `_mm_aeskeygenassist_si128` is not a constant", + ); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 15249402a63e..a27853fa0a82 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -5,7 +5,7 @@ macro_rules! intrinsic_args { ($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => { #[allow(unused_parens)] let ($($arg),*) = if let [$($arg),*] = $args { - ($(codegen_operand($fx, $arg)),*) + ($(codegen_operand($fx, &($arg).node)),*) } else { $crate::intrinsics::bug_on_incorrect_arg_count($intrinsic); }; @@ -22,6 +22,7 @@ use rustc_middle::ty; use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; @@ -263,7 +264,7 @@ fn bool_to_zero_or_max_uint<'tcx>( pub(crate) fn codegen_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, instance: Instance<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], destination: CPlace<'tcx>, target: Option, source_info: mir::SourceInfo, @@ -301,7 +302,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( fn codegen_float_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { @@ -353,18 +354,21 @@ fn codegen_float_intrinsic_call<'tcx>( let (a, b, c); let args = match args { [x] => { - a = [codegen_operand(fx, x).load_scalar(fx)]; + a = [codegen_operand(fx, &x.node).load_scalar(fx)]; &a as &[_] } [x, y] => { - b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)]; + b = [ + codegen_operand(fx, &x.node).load_scalar(fx), + codegen_operand(fx, &y.node).load_scalar(fx), + ]; &b } [x, y, z] => { c = [ - codegen_operand(fx, x).load_scalar(fx), - codegen_operand(fx, y).load_scalar(fx), - codegen_operand(fx, z).load_scalar(fx), + codegen_operand(fx, &x.node).load_scalar(fx), + codegen_operand(fx, &y.node).load_scalar(fx), + codegen_operand(fx, &z.node).load_scalar(fx), ]; &c } @@ -422,7 +426,7 @@ fn codegen_regular_intrinsic_call<'tcx>( instance: Instance<'tcx>, intrinsic: Symbol, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, destination: Option, source_info: mir::SourceInfo, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 78ea7c2dbfc3..d56d17892d5b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -21,7 +21,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: BasicBlock, span: Span, @@ -121,8 +121,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let [x, y] = args else { bug!("wrong number of args for intrinsic {intrinsic}"); }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); @@ -172,8 +172,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); @@ -182,7 +182,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. - let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + let idx_ty = fx.monomorphize(idx.node.ty(fx.mir, fx.tcx)); let n: u16 = match idx_ty.kind() { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) @@ -215,7 +215,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = match idx { + let idx_const = match &idx.node { Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, Operand::Copy(_) | Operand::Move(_) => unreachable!("{idx:?}"), }; @@ -269,12 +269,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let base = codegen_operand(fx, base); - let val = codegen_operand(fx, val); + let base = codegen_operand(fx, &base.node); + let val = codegen_operand(fx, &val.node); // FIXME validate let idx_const = if let Some(idx_const) = - crate::constant::mir_operand_get_const_val(fx, idx) + crate::constant::mir_operand_get_const_val(fx, &idx.node) { idx_const } else { @@ -304,7 +304,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let v = codegen_operand(fx, v); + let v = codegen_operand(fx, &v.node); if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -312,7 +312,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } let idx_const = if let Some(idx_const) = - crate::constant::mir_operand_get_const_val(fx, idx) + crate::constant::mir_operand_get_const_val(fx, &idx.node) { idx_const } else { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a1662f25e149..e35b4029b450 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_session::config::OptLevel; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{source_map::Spanned, sym, Span, Symbol}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -742,7 +742,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], destination: mir::Place<'tcx>, target: Option, unwind: mir::UnwindAction, @@ -793,7 +793,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().skip_binder().len()..]; let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); + let op_ty = op_arg.node.ty(self.mir, bx.tcx()); self.monomorphize(op_ty) })); @@ -863,7 +863,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // checked by const-qualification, which also // promotes any complex rvalues to constants. if i == 2 && intrinsic == sym::simd_shuffle { - if let mir::Operand::Constant(constant) = arg { + if let mir::Operand::Constant(constant) = &arg.node { let (llval, ty) = self.simd_shuffle_indices(bx, constant); return OperandRef { val: Immediate(llval), @@ -874,7 +874,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - self.codegen_operand(bx, arg) + self.codegen_operand(bx, &arg.node) }) .collect(); @@ -910,7 +910,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let mut copied_constant_arguments = vec![]; 'make_args: for (i, arg) in first_args.iter().enumerate() { - let mut op = self.codegen_operand(bx, arg); + let mut op = self.codegen_operand(bx, &arg.node); if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { match op.val { @@ -988,7 +988,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The callee needs to own the argument memory if we pass it // by-ref, so make a local copy of non-immediate constants. - match (arg, op.val) { + match (&arg.node, op.val) { (&mir::Operand::Copy(_), Ref(_, None, _)) | (&mir::Operand::Constant(_), Ref(_, None, _)) => { let tmp = PlaceRef::alloca(bx, op.layout); @@ -1003,7 +1003,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(bx, op, &mut llargs, &fn_abi.args[i]); } let num_untupled = untuple.map(|tup| { - self.codegen_arguments_untupled(bx, tup, &mut llargs, &fn_abi.args[first_args.len()..]) + self.codegen_arguments_untupled( + bx, + &tup.node, + &mut llargs, + &fn_abi.args[first_args.len()..], + ) }); let needs_location = diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 2358caffc9b4..7b993279f18e 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -9,7 +9,7 @@ use rustc_middle::{ AdtDef, Instance, Ty, }, }; -use rustc_span::sym; +use rustc_span::{source_map::Spanned, sym}; use rustc_target::abi::{self, FieldIdx}; use rustc_target::abi::{ call::{ArgAbi, FnAbi, PassMode}, @@ -242,13 +242,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Evaluate the arguments of a function call pub(super) fn eval_fn_call_arguments( &self, - ops: &[mir::Operand<'tcx>], + ops: &[Spanned>], ) -> InterpResult<'tcx, Vec>> { ops.iter() .map(|op| { - Ok(match op { + Ok(match &op.node { mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?), - _ => FnArg::Copy(self.eval_operand(op, None)?), + _ => FnArg::Copy(self.eval_operand(&op.node, None)?), }) }) .collect() diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index ae9595d7e644..89c65d923258 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -804,7 +804,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { - match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { + match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if ty.is_str() => return, _ => self.check_op(ops::PanicNonStr), } @@ -812,7 +812,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str` if tcx.has_attr(callee, sym::rustc_const_panic_str) { - match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { + match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) => { return; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 0b73691204d5..9c2f336e9128 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -402,7 +402,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ); } for arg in args { - if let Operand::Move(place) = arg { + if let Operand::Move(place) = &arg.node { if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 1a6b0f4031d3..239929a2c0ef 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -785,7 +785,7 @@ impl<'tcx> TerminatorKind<'tcx> { Call { func, args, destination, .. } => { write!(fmt, "{destination:?} = ")?; write!(fmt, "{func:?}(")?; - for (index, arg) in args.iter().enumerate() { + for (index, arg) in args.iter().map(|a| &a.node).enumerate() { if index > 0 { write!(fmt, ", ")?; } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 462076d750f2..6ebe57e29da2 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -16,6 +16,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::def_id::DefId; use rustc_hir::{self, CoroutineKind}; use rustc_index::IndexVec; +use rustc_span::source_map::Spanned; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; @@ -673,7 +674,9 @@ pub enum TerminatorKind<'tcx> { /// These are owned by the callee, which is free to modify them. /// This allows the memory occupied by "by-value" arguments to be /// reused across function calls without duplicating the contents. - args: Vec>, + /// The span for each arg is also included + /// (e.g. `a` and `b` in `x.foo(a, b)`). + args: Vec>>, /// Where the returned value will be written destination: Place<'tcx>, /// Where to go after this call returns. If none, the call necessarily diverges. diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 2ccf5a9f6f7a..4696f54c8978 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -524,7 +524,7 @@ macro_rules! make_mir_visitor { } => { self.visit_operand(func, location); for arg in args { - self.visit_operand(arg, location); + self.visit_operand(&$($mutability)? arg.node, location); } self.visit_place( destination, diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs index 9f1e4ac11c23..0ca4fce5da9b 100644 --- a/compiler/rustc_middle/src/util/find_self_call.rs +++ b/compiler/rustc_middle/src/util/find_self_call.rs @@ -2,6 +2,7 @@ use crate::mir::*; use crate::ty::GenericArgsRef; use crate::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; +use rustc_span::source_map::Spanned; /// Checks if the specified `local` is used as the `self` parameter of a method call /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is @@ -23,7 +24,13 @@ pub fn find_self_call<'tcx>( tcx.opt_associated_item(def_id) { debug!("find_self_call: args={:?}", fn_args); - if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args { + if let [ + Spanned { + node: Operand::Move(self_place) | Operand::Copy(self_place), .. + }, + .., + ] = **args + { if self_place.as_local() == Some(local) { return Some((def_id, fn_args)); } diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index e3dea2212df0..5428333a1161 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::cast::mir_cast_kind; use rustc_middle::{mir::*, thir::*, ty}; +use rustc_span::source_map::Spanned; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; @@ -162,7 +163,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let fun = self.parse_operand(*fun)?; let args = args .iter() - .map(|arg| self.parse_operand(*arg)) + .map(|arg| + Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } ) + ) .collect::>>()?; Ok(TerminatorKind::Call { func: fun, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index f799be165ecd..6e8af7bb6df6 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -2,6 +2,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::ty::util::IntTypeExt; +use rustc_span::source_map::Spanned; use rustc_target::abi::{Abi, FieldIdx, Primitive}; use crate::build::expr::as_place::PlaceBase; @@ -15,7 +16,7 @@ use rustc_middle::thir::*; use rustc_middle::ty::cast::{mir_cast_kind, CastTy}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Ty, UpvarArgs}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns an rvalue suitable for use until the end of the current @@ -156,7 +157,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { synth_info, TerminatorKind::Call { func: exchange_malloc, - args: vec![Operand::Move(size), Operand::Move(align)], + args: vec![ + Spanned { node: Operand::Move(size), span: DUMMY_SP }, + Spanned { node: Operand::Move(align), span: DUMMY_SP }, + ], destination: storage, target: Some(success), unwind: UnwindAction::Continue, @@ -733,7 +737,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.diverge_from(block); block = success; } - this.record_operands_moved(&[value_operand]); + this.record_operands_moved(&[Spanned { node: value_operand, span: DUMMY_SP }]); } block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), IndexVec::new())) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 060a3b521a4f..2978491d646e 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::CanonicalUserTypeAnnotation; +use rustc_span::source_map::Spanned; use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -248,7 +249,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let args: Vec<_> = args .into_iter() .copied() - .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) + .map(|arg| Spanned { + node: unpack!(block = this.as_local_call_operand(block, arg)), + span: this.thir.exprs[arg].span, + }) .collect(); let success = this.cfg.start_new_block(); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 53e5d70f946e..990be30b2d68 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -17,8 +17,9 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; use rustc_span::def_id::DefId; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; use std::cmp::Ordering; @@ -271,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { user_ty: None, const_: method, })), - args: vec![Operand::Move(ref_string)], + args: vec![Spanned { node: Operand::Move(ref_string), span: DUMMY_SP }], destination: ref_str, target: Some(eq_block), unwind: UnwindAction::Continue, @@ -526,7 +527,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { const_: method, })), - args: vec![Operand::Copy(val), expect], + args: vec![ + Spanned { node: Operand::Copy(val), span: DUMMY_SP }, + Spanned { node: expect, span: DUMMY_SP }, + ], destination: eq_result, target: Some(eq_block), unwind: UnwindAction::Continue, diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 48b237f3ae62..6827797df372 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -91,6 +91,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::{ExprId, LintLevel}; use rustc_session::lint::Level; +use rustc_span::source_map::Spanned; use rustc_span::{Span, DUMMY_SP}; #[derive(Debug)] @@ -1020,14 +1021,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// spurious borrow-check errors -- the problem, ironically, is /// not the `DROP(_X)` itself, but the (spurious) unwind pathways /// that it creates. See #64391 for an example. - pub(crate) fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) { + pub(crate) fn record_operands_moved(&mut self, operands: &[Spanned>]) { let local_scope = self.local_scope(); let scope = self.scopes.scopes.last_mut().unwrap(); assert_eq!(scope.region_scope, local_scope, "local scope is not the topmost scope!",); // look for moves of a local variable, like `MOVE(_X)` - let locals_moved = operands.iter().flat_map(|operand| match operand { + let locals_moved = operands.iter().flat_map(|operand| match operand.node { Operand::Copy(_) | Operand::Constant(_) => None, Operand::Move(place) => place.as_local(), }); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index c9930565186f..862876f53c76 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -7,6 +7,8 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::source_map::Spanned; +use rustc_span::DUMMY_SP; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use std::{fmt, iter}; @@ -652,7 +654,10 @@ where [ty.into()], self.source_info.span, ), - args: vec![Operand::Move(Place::from(ref_place))], + args: vec![Spanned { + node: Operand::Move(Place::from(ref_place)), + span: DUMMY_SP, + }], destination: unit_temp, target: Some(succ), unwind: unwind.into_action(), diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index cae357653087..38ee26c5a876 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -469,7 +469,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } => { self.gather_operand(func); for arg in args { - self.gather_operand(arg); + self.gather_operand(&arg.node); } if let Some(_bb) = target { self.create_move_path(destination); diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 5373876d1c2c..08a5d70fb6fc 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -209,7 +209,7 @@ impl PeekCall { assert_eq!(fn_args.len(), 1); let kind = PeekCallKind::from_arg_ty(fn_args.type_at(0)); - let arg = match &args[0] { + let arg = match &args[0].node { Operand::Copy(place) | Operand::Move(place) => { if let Some(local) = place.as_local() { local diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 379e96e263c2..eaa36e0cc91e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -675,9 +675,9 @@ fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local let terminator = bb_data.terminator.take().unwrap(); if let TerminatorKind::Call { mut args, destination, target, .. } = terminator.kind { let arg = args.pop().unwrap(); - let local = arg.place().unwrap().local; + let local = arg.node.place().unwrap().local; - let arg = Rvalue::Use(arg); + let arg = Rvalue::Use(arg.node); let assign = Statement { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new((destination, arg))), @@ -1865,7 +1865,7 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { self.check_assigned_place(*destination, |this| { this.visit_operand(func, location); for arg in args { - this.visit_operand(arg, location); + this.visit_operand(&arg.node, location); } }); } diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3d74ef7e3278..0f0a2bcd870a 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -52,7 +52,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { live.seek_to_block_end(bb); let mut state = live.get().clone(); - for (index, arg) in args.iter().enumerate().rev() { + for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() { if let Operand::Copy(place) = *arg && !place.is_indirect() // Do not skip the transformation if the local is in debuginfo, as we do @@ -119,7 +119,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let TerminatorKind::Call { ref mut args, .. } = bbs[block].terminator_mut().kind else { bug!() }; - let arg = &mut args[argument_index]; + let arg = &mut args[argument_index].node; let Operand::Copy(place) = *arg else { bug!() }; *arg = Operand::Move(place); } diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 990cfb05e607..a6750911394b 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -111,7 +111,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly { if let TerminatorKind::Call { ref args, .. } = terminator.kind { for arg in args { - if let Operand::Move(place) = *arg { + if let Operand::Move(place) = arg.node { let local = place.local; if place.is_indirect() || local == RETURN_PLACE diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 49b0edc0db88..2cc76f30fcfd 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -609,7 +609,7 @@ impl WriteInfo { self.add_place(*destination); self.add_operand(func); for arg in args { - self.add_operand(arg); + self.add_operand(&arg.node); } } TerminatorKind::InlineAsm { operands, .. } => { diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 340bb1948ebf..61d99f1f018b 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -4,6 +4,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt}; use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; +use rustc_span::source_map::Spanned; use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; @@ -43,7 +44,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { if let ty::FnDef(def_id, args_ref) = *func_ty.kind() { // Handle calls to `transmute` if self.tcx.is_diagnostic_item(sym::transmute, def_id) { - let arg_ty = args[0].ty(self.body, self.tcx); + let arg_ty = args[0].node.ty(self.body, self.tcx); for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) { if let Some((fn_id, fn_args)) = FunctionItemRefChecker::is_fn_ref(inner_ty) { @@ -67,7 +68,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { &self, def_id: DefId, args_ref: GenericArgsRef<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], source_info: SourceInfo, ) { let param_env = self.tcx.param_env(def_id); @@ -134,8 +135,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { .unwrap_or(None) } - fn nth_arg_span(&self, args: &[Operand<'tcx>], n: usize) -> Span { - match &args[n] { + fn nth_arg_span(&self, args: &[Spanned>], n: usize) -> Span { + match &args[n].node { Operand::Copy(place) | Operand::Move(place) => { self.body.local_decls[place.local].source_info.span } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index ebefc3b47cc4..67668a216dee 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -11,6 +11,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; +use rustc_span::source_map::Spanned; use rustc_target::abi::FieldIdx; use rustc_target::spec::abi::Abi; @@ -172,7 +173,7 @@ impl<'tcx> Inliner<'tcx> { let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; for arg in args { - if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) { + if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) { // We do not allow inlining functions with unsized params. Inlining these functions // could create unsized locals, which are unsound and being phased out. return Err("Call has unsized argument"); @@ -238,9 +239,9 @@ impl<'tcx> Inliner<'tcx> { }; let self_arg_ty = - self_arg.map(|self_arg| self_arg.ty(&caller_body.local_decls, self.tcx)); + self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, self.tcx)); - let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx); + let arg_tuple_ty = arg_tuple.node.ty(&caller_body.local_decls, self.tcx); let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else { bug!("Closure arguments are not passed as a tuple"); }; @@ -263,7 +264,7 @@ impl<'tcx> Inliner<'tcx> { } else { for (arg, input) in args.iter().zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; - let arg_ty = arg.ty(&caller_body.local_decls, self.tcx); + let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx); if !util::relate_types( self.tcx, self.param_env, @@ -694,7 +695,7 @@ impl<'tcx> Inliner<'tcx> { fn make_call_args( &self, - args: Vec>, + args: Vec>>, callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>, callee_body: &Body<'tcx>, @@ -728,13 +729,13 @@ impl<'tcx> Inliner<'tcx> { if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() { let mut args = args.into_iter(); let self_ = self.create_temp_if_necessary( - args.next().unwrap(), + args.next().unwrap().node, callsite, caller_body, return_block, ); let tuple = self.create_temp_if_necessary( - args.next().unwrap(), + args.next().unwrap().node, callsite, caller_body, return_block, @@ -761,7 +762,7 @@ impl<'tcx> Inliner<'tcx> { closure_ref_arg.chain(tuple_tmp_args).collect() } else { args.into_iter() - .map(|a| self.create_temp_if_necessary(a, callsite, caller_body, return_block)) + .map(|a| self.create_temp_if_necessary(a.node, callsite, caller_body, return_block)) .collect() } } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 4f0f63d22a4d..a28db0defc99 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -215,7 +215,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { // These types are easily available from locals, so check that before // doing DefId lookups to figure out what we're actually calling. - let arg_ty = args[0].ty(self.local_decls, self.tcx); + let arg_ty = args[0].node.ty(self.local_decls, self.tcx); let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return }; @@ -238,7 +238,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { return; } - let Some(arg_place) = args.pop().unwrap().place() else { return }; + let Some(arg_place) = args.pop().unwrap().node.place() else { return }; statements.push(Statement { source_info: terminator.source_info, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 98076077b9a4..6f3fd14cd973 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -41,7 +41,7 @@ use rustc_middle::mir::{ }; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::sym; +use rustc_span::{source_map::Spanned, sym, DUMMY_SP}; use rustc_trait_selection::traits; #[macro_use] @@ -170,13 +170,13 @@ fn remap_mir_for_const_eval_select<'tcx>( { let [tupled_args, called_in_const, called_at_rt]: [_; 3] = std::mem::take(args).try_into().unwrap(); - let ty = tupled_args.ty(&body.local_decls, tcx); + let ty = tupled_args.node.ty(&body.local_decls, tcx); let fields = ty.tuple_fields(); let num_args = fields.len(); let func = if context == hir::Constness::Const { called_in_const } else { called_at_rt }; let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = - match tupled_args { + match tupled_args.node { Operand::Constant(_) => { // there is no good way of extracting a tuple arg from a constant (const generic stuff) // so we just create a temporary and deconstruct that. @@ -185,7 +185,7 @@ fn remap_mir_for_const_eval_select<'tcx>( source_info: SourceInfo::outermost(fn_span), kind: StatementKind::Assign(Box::new(( local.into(), - Rvalue::Use(tupled_args.clone()), + Rvalue::Use(tupled_args.node.clone()), ))), }); (Operand::Move, local.into()) @@ -200,11 +200,11 @@ fn remap_mir_for_const_eval_select<'tcx>( place_elems.push(ProjectionElem::Field(x.into(), fields[x])); let projection = tcx.mk_place_elems(&place_elems); let place = Place { local: place.local, projection }; - method(place) + Spanned { node: method(place), span: DUMMY_SP } }) .collect(); terminator.kind = TerminatorKind::Call { - func, + func: func.node, args: arguments, destination, target, diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index c0c0a3f5ee64..5b269185e87a 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { self.places.insert(destination.as_ref()); let mut has_duplicates = false; for arg in args { - if let Operand::Move(place) = arg { + if let Operand::Move(place) = &arg.node { has_duplicates |= !self.places.insert(place.as_ref()); } } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 18f588dccf62..897375e0e164 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -45,9 +45,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { kind: StatementKind::Intrinsic(Box::new( NonDivergingIntrinsic::CopyNonOverlapping( rustc_middle::mir::CopyNonOverlapping { - src: args.next().unwrap(), - dst: args.next().unwrap(), - count: args.next().unwrap(), + src: args.next().unwrap().node, + dst: args.next().unwrap().node, + count: args.next().unwrap().node, }, ), )), @@ -66,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { block.statements.push(Statement { source_info: terminator.source_info, kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::Assume(args.next().unwrap()), + NonDivergingIntrinsic::Assume(args.next().unwrap().node), )), }); assert_eq!( @@ -112,7 +112,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::BinaryOp(bin_op, Box::new((lhs, rhs))), + Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), ))), }); terminator.kind = TerminatorKind::Goto { target }; @@ -136,7 +136,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs, rhs))), + Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs.node, rhs.node))), ))), }); terminator.kind = TerminatorKind::Goto { target }; @@ -164,7 +164,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { let [arg] = args.as_slice() else { span_bug!(terminator.source_info.span, "Wrong number of arguments"); }; - let derefed_place = if let Some(place) = arg.place() + let derefed_place = if let Some(place) = arg.node.place() && let Some(local) = place.as_local() { tcx.mk_place_deref(local.into()) @@ -200,7 +200,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { "Wrong number of arguments for write_via_move intrinsic", ); }; - let derefed_place = if let Some(place) = ptr.place() + let derefed_place = if let Some(place) = ptr.node.place() && let Some(local) = place.as_local() { tcx.mk_place_deref(local.into()) @@ -214,13 +214,13 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( derefed_place, - Rvalue::Use(val), + Rvalue::Use(val.node), ))), }); terminator.kind = TerminatorKind::Goto { target }; } sym::discriminant_value => { - if let (Some(target), Some(arg)) = (*target, args[0].place()) { + if let (Some(target), Some(arg)) = (*target, args[0].node.place()) { let arg = tcx.mk_place_deref(arg); block.statements.push(Statement { source_info: terminator.source_info, @@ -244,7 +244,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))), + Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr.node, delta.node))), ))), }); terminator.kind = TerminatorKind::Goto { target }; @@ -265,7 +265,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::Cast(CastKind::Transmute, arg, dst_ty), + Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty), ))), }); diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index daeb56666f4d..8137525a3324 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -50,7 +50,7 @@ fn lower_slice_len_call<'tcx>( } = &terminator.kind // some heuristics for fast rejection && let [arg] = &args[..] - && let Some(arg) = arg.place() + && let Some(arg) = arg.node.place() && let ty::FnDef(fn_def_id, _) = func.ty(local_decls, tcx).kind() && *fn_def_id == slice_len_fn_item_def_id { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 841b86fed454..c00093ea27ed 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_span::source_map::Spanned; use std::assert_matches::assert_matches; use std::cell::Cell; @@ -565,7 +566,7 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_call( &mut self, callee: &Operand<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], ) -> Result<(), Unpromotable> { let fn_ty = callee.ty(self.body, self.tcx); @@ -595,7 +596,7 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(callee)?; for arg in args { - self.validate_operand(arg)?; + self.validate_operand(&arg.node)?; } Ok(()) @@ -731,7 +732,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } => { self.visit_operand(&mut func, loc); for arg in &mut args { - self.visit_operand(arg, loc); + self.visit_operand(&mut arg.node, loc); } let last = self.promoted.basic_blocks.last_index().unwrap(); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f6b820bfcd01..89414ce940e0 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -9,7 +9,7 @@ use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_index::{Idx, IndexVec}; -use rustc_span::Span; +use rustc_span::{source_map::Spanned, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use std::fmt; @@ -526,7 +526,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { vec![statement], TerminatorKind::Call { func, - args: vec![Operand::Move(ref_loc)], + args: vec![Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }], destination: dest, target: Some(next), unwind: UnwindAction::Cleanup(cleanup), @@ -811,6 +811,7 @@ fn build_call_shim<'tcx>( }; // BB #0 + let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect::>(); block( &mut blocks, statements, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 92f001cc3212..1d7bad6cba32 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -668,7 +668,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { fn check_fn_args_move_size( &mut self, callee_ty: Ty<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], location: Location, ) { let limit = self.tcx.move_size_limit(); @@ -693,7 +693,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { } for arg in args { - self.check_operand_move_size(arg, location); + self.check_operand_move_size(&arg.node, location); } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index c5fb6f7a26f1..2f3d9d69b858 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -609,7 +609,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { fn_span: _, } => TerminatorKind::Call { func: func.stable(tables), - args: args.iter().map(|arg| arg.stable(tables)).collect(), + args: args.iter().map(|arg| arg.node.stable(tables)).collect(), destination: destination.stable(tables), target: target.map(|t| t.as_usize()), unwind: unwind.stable(tables), diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 8253ffefcaa7..72a8b23721d7 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -70,7 +70,7 @@ mod monotonic { impl !DerefMut for MonotonicVec {} } -#[derive(Clone, Encodable, Decodable, Debug, Copy, HashStable_Generic)] +#[derive(Clone, Encodable, Decodable, Debug, Copy, PartialEq, Hash, HashStable_Generic)] pub struct Spanned { pub node: T, pub span: Span, diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index c62c351e7167..3416a93e3c4a 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -257,9 +257,9 @@ fn is_call_with_ref_arg<'tcx>( .. } = kind && args.len() == 1 - && let mir::Operand::Move(mir::Place { local, .. }) = &args[0] + && let mir::Operand::Move(mir::Place { local, .. }) = &args[0].node && let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind() - && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx)) + && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].node.ty(mir, cx.tcx)) && !is_copy(cx, inner_ty) { Some((def_id, *local, inner_ty, destination.as_local()?)) diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 703985b9d4b3..f9cc5f191253 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -104,7 +104,7 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, let mut mutable_borrowers = vec![]; for op in args { - match op { + match &op.node { mir::Operand::Copy(p) | mir::Operand::Move(p) => { if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() { mutable_borrowers.push(p.local); diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 668ea9fcf3b4..81f4fcc2133d 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -345,7 +345,7 @@ fn check_terminator<'tcx>( check_operand(tcx, func, span, body)?; for arg in args { - check_operand(tcx, arg, span, body)?; + check_operand(tcx, &arg.node, span, body)?; } Ok(()) } else { From 8f440f06c68846fc0094f5c2d1c9509ec80455ef Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sat, 7 Oct 2023 14:34:29 +0200 Subject: [PATCH 171/297] large_assignments: Lint on specific large args passed to functions --- compiler/rustc_middle/src/mir/tcx.rs | 12 ++ compiler/rustc_monomorphize/src/collector.rs | 104 +++++++++++------- .../box_rc_arc_allowed.stderr | 4 +- .../ui/lint/large_assignments/copy_into_fn.rs | 24 ++++ .../large_assignments/copy_into_fn.stderr | 31 ++++++ 5 files changed, 134 insertions(+), 41 deletions(-) create mode 100644 tests/ui/lint/large_assignments/copy_into_fn.rs create mode 100644 tests/ui/lint/large_assignments/copy_into_fn.stderr diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 234ccee55468..5597609c7d79 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -229,6 +229,18 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(c) => c.const_.ty(), } } + + pub fn span(&self, local_decls: &D) -> Span + where + D: HasLocalDecls<'tcx>, + { + match self { + &Operand::Copy(ref l) | &Operand::Move(ref l) => { + local_decls.local_decls()[l.local].source_info.span + } + Operand::Constant(c) => c.span, + } + } } impl<'tcx> BinOp { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1d7bad6cba32..070580860c16 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -614,8 +614,8 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { } fn check_operand_move_size(&mut self, operand: &mir::Operand<'tcx>, location: Location) { - let limit = self.tcx.move_size_limit().0; - if limit == 0 { + let limit = self.tcx.move_size_limit(); + if limit.0 == 0 { return; } @@ -627,48 +627,19 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { return; } - let limit = Size::from_bytes(limit); - let ty = operand.ty(self.body, self.tcx); - let ty = self.monomorphize(ty); - let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { return }; - if layout.size <= limit { - return; - } - debug!(?layout); let source_info = self.body.source_info(location); debug!(?source_info); - for span in &self.move_size_spans { - if span.overlaps(source_info.span) { - return; - } - } - let lint_root = source_info.scope.lint_root(&self.body.source_scopes); - debug!(?lint_root); - let Some(lint_root) = lint_root else { - // This happens when the issue is in a function from a foreign crate that - // we monomorphized in the current crate. We can't get a `HirId` for things - // in other crates. - // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root - // but correct span? This would make the lint at least accept crate-level lint attributes. - return; + + if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) { + self.lint_large_assignment(limit.0, too_large_size, location, source_info.span); }; - self.tcx.emit_spanned_lint( - LARGE_ASSIGNMENTS, - lint_root, - source_info.span, - LargeAssignmentsLint { - span: source_info.span, - size: layout.size.bytes(), - limit: limit.bytes(), - }, - ); - self.move_size_spans.push(source_info.span); } fn check_fn_args_move_size( &mut self, callee_ty: Ty<'tcx>, args: &[Spanned>], + fn_span: Span, location: Location, ) { let limit = self.tcx.move_size_limit(); @@ -692,10 +663,65 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { return; } + debug!(?def_id, ?fn_span); + for arg in args { - self.check_operand_move_size(&arg.node, location); + if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) { + self.lint_large_assignment(limit.0, too_large_size, location, arg.span); + }; } } + + fn operand_size_if_too_large( + &mut self, + limit: Limit, + operand: &mir::Operand<'tcx>, + ) -> Option { + let ty = operand.ty(self.body, self.tcx); + let ty = self.monomorphize(ty); + let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { + return None; + }; + if layout.size.bytes_usize() > limit.0 { + debug!(?layout); + Some(layout.size) + } else { + None + } + } + + fn lint_large_assignment( + &mut self, + limit: usize, + too_large_size: Size, + location: Location, + span: Span, + ) { + let source_info = self.body.source_info(location); + debug!(?source_info); + for reported_span in &self.move_size_spans { + if reported_span.overlaps(span) { + return; + } + } + let lint_root = source_info.scope.lint_root(&self.body.source_scopes); + debug!(?lint_root); + let Some(lint_root) = lint_root else { + // This happens when the issue is in a function from a foreign crate that + // we monomorphized in the current crate. We can't get a `HirId` for things + // in other crates. + // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root + // but correct span? This would make the lint at least accept crate-level lint attributes. + return; + }; + self.tcx.emit_spanned_lint( + LARGE_ASSIGNMENTS, + lint_root, + span, + LargeAssignmentsLint { span, size: too_large_size.bytes(), limit: limit as u64 }, + ); + self.move_size_spans.push(span); + } } impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { @@ -813,11 +839,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { }; match terminator.kind { - mir::TerminatorKind::Call { ref func, ref args, .. } => { + mir::TerminatorKind::Call { ref func, ref args, ref fn_span, .. } => { let callee_ty = func.ty(self.body, tcx); let callee_ty = self.monomorphize(callee_ty); - self.check_fn_args_move_size(callee_ty, args, location); - visit_fn_use(self.tcx, callee_ty, true, source, self.output) + self.check_fn_args_move_size(callee_ty, args, *fn_span, location); + visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) } mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; diff --git a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr b/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr index b45cbe5da4dc..fefb3a9621b5 100644 --- a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr +++ b/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr @@ -1,8 +1,8 @@ error: moving 9999 bytes - --> $DIR/box_rc_arc_allowed.rs:16:13 + --> $DIR/box_rc_arc_allowed.rs:16:25 | LL | let _ = NotBox::new([0; 9999]); - | ^^^^^^^^^^^^^^^^^^^^^^ value moved from here + | ^^^^^^^^^ value moved from here | = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` note: the lint level is defined here diff --git a/tests/ui/lint/large_assignments/copy_into_fn.rs b/tests/ui/lint/large_assignments/copy_into_fn.rs new file mode 100644 index 000000000000..ee204bf7af17 --- /dev/null +++ b/tests/ui/lint/large_assignments/copy_into_fn.rs @@ -0,0 +1,24 @@ +// build-fail + +#![feature(large_assignments)] +#![move_size_limit = "1000"] +#![deny(large_assignments)] +#![allow(unused)] + +// We want copy semantics, because moving data into functions generally do not +// translate to actual `memcpy`s. +#[derive(Copy, Clone)] +struct Data([u8; 9999]); + +fn main() { + one_arg(Data([0; 9999])); //~ ERROR large_assignments + + // each individual large arg shall have its own span + many_args(Data([0; 9999]), true, Data([0; 9999])); + //~^ ERROR large_assignments + //~| ERROR large_assignments +} + +fn one_arg(a: Data) {} + +fn many_args(a: Data, b: bool, c: Data) {} diff --git a/tests/ui/lint/large_assignments/copy_into_fn.stderr b/tests/ui/lint/large_assignments/copy_into_fn.stderr new file mode 100644 index 000000000000..f05fc33e17e1 --- /dev/null +++ b/tests/ui/lint/large_assignments/copy_into_fn.stderr @@ -0,0 +1,31 @@ +error: moving 9999 bytes + --> $DIR/copy_into_fn.rs:14:13 + | +LL | one_arg(Data([0; 9999])); + | ^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/copy_into_fn.rs:5:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 9999 bytes + --> $DIR/copy_into_fn.rs:17:15 + | +LL | many_args(Data([0; 9999]), true, Data([0; 9999])); + | ^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: moving 9999 bytes + --> $DIR/copy_into_fn.rs:17:38 + | +LL | many_args(Data([0; 9999]), true, Data([0; 9999])); + | ^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 3 previous errors + From 8b66f497ebe3458226dbcc91501b5dd1c1728b45 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 15 Jan 2024 19:17:28 +0100 Subject: [PATCH 172/297] Lint overlapping ranges directly from exhaustiveness --- compiler/rustc_pattern_analysis/src/lib.rs | 25 +++++++------ compiler/rustc_pattern_analysis/src/lints.rs | 32 ++--------------- compiler/rustc_pattern_analysis/src/rustc.rs | 35 ++++++++++++++----- .../rustc_pattern_analysis/src/usefulness.rs | 16 +++------ 4 files changed, 49 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index ed10a5155084..0bc432fa6f0a 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -27,11 +27,9 @@ use rustc_middle::ty::Ty; #[cfg(feature = "rustc")] use rustc_span::ErrorGuaranteed; -use crate::constructor::{Constructor, ConstructorSet}; +use crate::constructor::{Constructor, ConstructorSet, IntRange}; #[cfg(feature = "rustc")] -use crate::lints::{ - lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn, -}; +use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn}; use crate::pat::DeconstructedPat; #[cfg(feature = "rustc")] use crate::rustc::RustcMatchCheckCtxt; @@ -77,6 +75,17 @@ pub trait TypeCx: Sized + fmt::Debug { /// Raise a bug. fn bug(&self, fmt: fmt::Arguments<'_>) -> !; + + /// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range + /// they overlapped over is `overlaps_on`. We only detect singleton overlaps. + /// The default implementation does nothing. + fn lint_overlapping_range_endpoints( + &self, + _pat: &DeconstructedPat<'_, Self>, + _overlaps_on: IntRange, + _overlaps_with: &[&DeconstructedPat<'_, Self>], + ) { + } } /// Context that provides information global to a match. @@ -111,16 +120,10 @@ pub fn analyze_match<'p, 'tcx>( let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?; - let pat_column = PatternColumn::new(arms); - - // Lint ranges that overlap on their endpoints, which is likely a mistake. - if !report.overlapping_range_endpoints.is_empty() { - lint_overlapping_range_endpoints(cx, &report.overlapping_range_endpoints); - } - // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { + let pat_column = PatternColumn::new(arms); lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?; } diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index cfe4ca3ce93d..4266e2a405e5 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,14 +1,11 @@ -use rustc_session::lint; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; -use crate::errors::{ - self, NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered, -}; +use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; use crate::pat::PatOrWild; use crate::rustc::{ - self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, - RustcMatchCheckCtxt, SplitConstructorSet, WitnessPat, + Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt, + SplitConstructorSet, WitnessPat, }; /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that @@ -196,26 +193,3 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } Ok(()) } - -pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>( - cx: MatchCtxt<'a, 'p, 'tcx>, - overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>], -) { - let rcx = cx.tycx; - for overlap in overlapping_range_endpoints { - let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty()); - let overlaps: Vec<_> = overlap - .overlaps_with - .iter() - .map(|pat| pat.data().unwrap().span) - .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span }) - .collect(); - let pat_span = overlap.pat.data().unwrap().span; - rcx.tcx.emit_spanned_lint( - lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, - rcx.match_lint_level, - pat_span, - errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span }, - ); - } -} diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index e82d6666b1af..dbb2bf4a4cbf 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,3 +1,4 @@ +use smallvec::SmallVec; use std::fmt; use std::iter::once; @@ -5,24 +6,21 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_data_structures::captures::Captures; use rustc_hir::def_id::DefId; use rustc_hir::HirId; -use rustc_index::Idx; -use rustc_index::IndexVec; +use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::TypeVisitableExt; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef}; -use rustc_span::ErrorGuaranteed; -use rustc_span::{Span, DUMMY_SP}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef}; +use rustc_session::lint; +use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; -use smallvec::SmallVec; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; -use crate::TypeCx; +use crate::{errors, TypeCx}; use crate::constructor::Constructor::*; @@ -991,6 +989,27 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { span_bug!(self.scrut_span, "{}", fmt) } + + fn lint_overlapping_range_endpoints( + &self, + pat: &crate::pat::DeconstructedPat<'_, Self>, + overlaps_on: IntRange, + overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>], + ) { + let overlap_as_pat = self.hoist_pat_range(&overlaps_on, pat.ty()); + let overlaps: Vec<_> = overlaps_with + .iter() + .map(|pat| pat.data().unwrap().span) + .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span }) + .collect(); + let pat_span = pat.data().unwrap().span; + self.tcx.emit_spanned_lint( + lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, + self.match_lint_level, + pat_span, + errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span }, + ); + } } /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 6244cf0ff7d7..1d505f0c1cda 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1340,10 +1340,11 @@ impl WitnessMatrix { /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( + mcx: MatchCtxt<'_, Cx>, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>, - overlapping_range_endpoints: &mut Vec>, + _overlapping_range_endpoints: &mut Vec>, ) { let overlap = overlap_range.lo; // Ranges that look like `lo..=overlap`. @@ -1373,11 +1374,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( .map(|&(_, pat)| pat) .collect(); if !overlaps_with.is_empty() { - overlapping_range_endpoints.push(OverlappingRanges { - pat, - overlaps_on: overlap_range, - overlaps_with, - }); + mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); } } suffixes.push((child_row_id, pat)) @@ -1393,11 +1390,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( .map(|&(_, pat)| pat) .collect(); if !overlaps_with.is_empty() { - overlapping_range_endpoints.push(OverlappingRanges { - pat, - overlaps_on: overlap_range, - overlaps_with, - }); + mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); } } prefixes.push((child_row_id, pat)) @@ -1538,6 +1531,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty()) { collect_overlapping_range_endpoints( + mcx, overlap_range, matrix, &spec_matrix, From 448c4a4efb689f5d7d1479a1c3d1cac0d3a1fc82 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 15 Jan 2024 19:26:55 +0100 Subject: [PATCH 173/297] Remove the unused `overlapping_range_endpoints` Vec --- compiler/rustc_pattern_analysis/src/rustc.rs | 2 - .../rustc_pattern_analysis/src/usefulness.rs | 42 +++---------------- 2 files changed, 5 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index dbb2bf4a4cbf..87e70d68c1b4 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -32,8 +32,6 @@ pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type OverlappingRanges<'p, 'tcx> = - crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type PlaceCtxt<'a, 'p, 'tcx> = crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type SplitConstructorSet<'p, 'tcx> = diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 1d505f0c1cda..c78949942134 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1344,7 +1344,6 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( overlap_range: IntRange, matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>, - _overlapping_range_endpoints: &mut Vec>, ) { let overlap = overlap_range.lo; // Ranges that look like `lo..=overlap`. @@ -1416,7 +1415,6 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( mcx: MatchCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, - overlapping_range_endpoints: &mut Vec>, is_top_level: bool, ) -> Result, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1496,12 +1494,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty(); let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant); let mut witnesses = ensure_sufficient_stack(|| { - compute_exhaustiveness_and_usefulness( - mcx, - &mut spec_matrix, - overlapping_range_endpoints, - false, - ) + compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) })?; // Transform witnesses for `spec_matrix` into witnesses for `matrix`. @@ -1530,13 +1523,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( && spec_matrix.rows.len() >= 2 && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty()) { - collect_overlapping_range_endpoints( - mcx, - overlap_range, - matrix, - &spec_matrix, - overlapping_range_endpoints, - ); + collect_overlapping_range_endpoints(mcx, overlap_range, matrix, &spec_matrix); } } } @@ -1563,15 +1550,6 @@ pub enum Usefulness<'p, Cx: TypeCx> { Redundant, } -/// Indicates that the range `pat` overlapped with all the ranges in `overlaps_with`, where the -/// range they overlapped over is `overlaps_on`. We only detect singleton overlaps. -#[derive(Clone, Debug)] -pub struct OverlappingRanges<'p, Cx: TypeCx> { - pub pat: &'p DeconstructedPat<'p, Cx>, - pub overlaps_on: IntRange, - pub overlaps_with: Vec<&'p DeconstructedPat<'p, Cx>>, -} - /// The output of checking a match for exhaustiveness and arm usefulness. pub struct UsefulnessReport<'p, Cx: TypeCx> { /// For each arm of the input, whether that arm is useful after the arms above it. @@ -1579,7 +1557,6 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of /// exhaustiveness. pub non_exhaustiveness_witnesses: Vec>, - pub overlapping_range_endpoints: Vec>, } /// Computes whether a match is exhaustive and which of its arms are useful. @@ -1590,14 +1567,9 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Result, Cx::Error> { - let mut overlapping_range_endpoints = Vec::new(); let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity); - let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness( - cx, - &mut matrix, - &mut overlapping_range_endpoints, - true, - )?; + let non_exhaustiveness_witnesses = + compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?; let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column(); let arm_usefulness: Vec<_> = arms @@ -1615,9 +1587,5 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( }) .collect(); - Ok(UsefulnessReport { - arm_usefulness, - non_exhaustiveness_witnesses, - overlapping_range_endpoints, - }) + Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }) } From 604d2083d3921471e5b0d4f90baf61a746ba3603 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 15 Jan 2024 13:09:46 -0800 Subject: [PATCH 174/297] Revert unrelated changes from PR 119990 --- library/core/src/num/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f53a6f9e1340..f5d765e690db 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -793,7 +793,7 @@ impl u8 { #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] pub const fn is_ascii_alphanumeric(&self) -> bool { - matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z') + matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'Z') | matches!(*self, b'a'..=b'z') } /// Checks if the value is an ASCII decimal digit: @@ -1206,9 +1206,9 @@ impl u128 { swapped = "0x12907856341290785634129078563412", reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ - 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", to_xe_bytes_doc = "", from_xe_bytes_doc = "", bound_condition = "", From 37849643c670f7f0809948986329b04ce5c90405 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 14 Jan 2024 18:08:02 -0500 Subject: [PATCH 175/297] Cache local DefId-keyed queries without hashing Foreign maps are used to cache external DefIds, typically backed by metadata decoding. In the future we might skip caching `V` there (since loading from metadata usually is already cheap enough), but for now this cuts down on the impact to memory usage and time to None-init a bunch of memory. Foreign data is usually much sparser, since we're not usually loading *all* entries from the foreign crate(s). --- compiler/rustc_middle/src/query/keys.rs | 3 +- .../rustc_query_system/src/query/caches.rs | 79 ++++++++++++++++++- compiler/rustc_query_system/src/query/mod.rs | 3 +- 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 945f17d5df2a..69d3974184db 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -9,6 +9,7 @@ use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; +use rustc_query_system::query::DefIdCacheSelector; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -152,7 +153,7 @@ impl Key for LocalDefId { } impl Key for DefId { - type CacheSelector = DefaultCacheSelector; + type CacheSelector = DefIdCacheSelector; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 0240f012da05..674a0984ae98 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -2,8 +2,11 @@ use crate::dep_graph::DepNodeIndex; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::{self, Sharded}; -use rustc_data_structures::sync::OnceLock; +use rustc_data_structures::sync::{Lock, OnceLock}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_index::{Idx, IndexVec}; +use rustc_span::def_id::DefId; +use rustc_span::def_id::DefIndex; use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; @@ -148,6 +151,8 @@ where #[inline(always)] fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { + // FIXME: lock_shard_by_hash will use high bits which are usually zero in the index() passed + // here. This makes sharding essentially useless, always selecting the zero'th shard. let lock = self.cache.lock_shard_by_hash(key.index() as u64); if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None } } @@ -168,3 +173,75 @@ where } } } + +pub struct DefIdCacheSelector; + +impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for DefIdCacheSelector { + type Cache = DefIdCache + where + V: Copy; +} + +pub struct DefIdCache { + /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is + /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap. + /// + /// The second element of the tuple is the set of keys actually present in the IndexVec, used + /// for faster iteration in `iter()`. + // FIXME: This may want to be sharded, like VecCache. However *how* to shard an IndexVec isn't + // super clear; VecCache is effectively not sharded today (see FIXME there). For now just omit + // that complexity here. + local: Lock<(IndexVec>, Vec)>, + foreign: DefaultCache, +} + +impl Default for DefIdCache { + fn default() -> Self { + DefIdCache { local: Default::default(), foreign: Default::default() } + } +} + +impl QueryCache for DefIdCache +where + V: Copy, +{ + type Key = DefId; + type Value = V; + + #[inline(always)] + fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> { + if key.krate == LOCAL_CRATE { + let cache = self.local.lock(); + cache.0.get(key.index).and_then(|v| *v) + } else { + self.foreign.lookup(key) + } + } + + #[inline] + fn complete(&self, key: DefId, value: V, index: DepNodeIndex) { + if key.krate == LOCAL_CRATE { + let mut cache = self.local.lock(); + let (cache, present) = &mut *cache; + let slot = cache.ensure_contains_elem(key.index, Default::default); + if slot.is_none() { + // FIXME: Only store the present set when running in incremental mode. `iter` is not + // used outside of saving caches to disk and self-profile. + present.push(key.index); + } + *slot = Some((value, index)); + } else { + self.foreign.complete(key, value, index) + } + } + + fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { + let guard = self.local.lock(); + let (cache, present) = &*guard; + for &idx in present.iter() { + let value = cache[idx].unwrap(); + f(&DefId { krate: LOCAL_CRATE, index: idx }, &value.0, value.1); + } + self.foreign.iter(f); + } +} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 9ff04c4e910d..eecbf86c173b 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -10,7 +10,8 @@ pub use self::job::{ mod caches; pub use self::caches::{ - CacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, VecCacheSelector, + CacheSelector, DefIdCacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, + VecCacheSelector, }; mod config; From f1494425bbb68e71f2bf3aa215fb71978b36acf2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 13:40:01 +1100 Subject: [PATCH 176/297] coverage: Add `#[rustfmt::skip]` to tests with non-standard formatting These tests deliberately use non-standard formatting, so that the line execution counts reported by `llvm-cov` reveal additional information about where code regions begin and end. --- tests/coverage/abort.cov-map | 4 +- tests/coverage/abort.coverage | 1 + tests/coverage/abort.rs | 1 + tests/coverage/async.cov-map | 100 +++++++++++------------ tests/coverage/async.coverage | 2 + tests/coverage/async.rs | 2 + tests/coverage/closure.cov-map | 84 +++++++++---------- tests/coverage/closure.coverage | 1 + tests/coverage/closure.rs | 1 + tests/coverage/closure_bug.cov-map | 20 ++--- tests/coverage/closure_bug.coverage | 1 + tests/coverage/closure_bug.rs | 1 + tests/coverage/if.cov-map | 4 +- tests/coverage/if.coverage | 1 + tests/coverage/if.rs | 1 + tests/coverage/if_else.cov-map | 4 +- tests/coverage/if_else.coverage | 1 + tests/coverage/if_else.rs | 1 + tests/coverage/if_not.cov-map | 4 +- tests/coverage/if_not.coverage | 1 + tests/coverage/if_not.rs | 1 + tests/coverage/issue-84561.cov-map | 24 +++--- tests/coverage/issue-84561.coverage | 2 + tests/coverage/issue-84561.rs | 2 + tests/coverage/lazy_boolean.cov-map | 4 +- tests/coverage/lazy_boolean.coverage | 1 + tests/coverage/lazy_boolean.rs | 1 + tests/coverage/loop_break_value.cov-map | 4 +- tests/coverage/loop_break_value.coverage | 1 + tests/coverage/loop_break_value.rs | 1 + tests/coverage/simple_loop.cov-map | 4 +- tests/coverage/simple_loop.coverage | 1 + tests/coverage/simple_loop.rs | 1 + tests/coverage/simple_match.cov-map | 4 +- tests/coverage/simple_match.coverage | 1 + tests/coverage/simple_match.rs | 1 + tests/coverage/try_error_result.cov-map | 20 ++--- tests/coverage/try_error_result.coverage | 3 + tests/coverage/try_error_result.rs | 3 + tests/coverage/while_early_ret.cov-map | 4 +- tests/coverage/while_early_ret.coverage | 1 + tests/coverage/while_early_ret.rs | 1 + 42 files changed, 178 insertions(+), 142 deletions(-) diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 45d3795eff8f..1c36f2871dd1 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -1,5 +1,5 @@ Function name: abort::main -Raw bytes (105): 0x[01, 01, 12, 01, 47, 05, 09, 03, 0d, 42, 11, 03, 0d, 11, 3e, 42, 11, 03, 0d, 3b, 15, 11, 3e, 42, 11, 03, 0d, 15, 36, 3b, 15, 11, 3e, 42, 11, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 42, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 3e, 02, 0a, 00, 0b, 3b, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 36, 00, 31, 00, 32, 33, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 31, 00, 32, 47, 01, 09, 00, 17, 0d, 02, 05, 01, 02] +Raw bytes (105): 0x[01, 01, 12, 01, 47, 05, 09, 03, 0d, 42, 11, 03, 0d, 11, 3e, 42, 11, 03, 0d, 3b, 15, 11, 3e, 42, 11, 03, 0d, 15, 36, 3b, 15, 11, 3e, 42, 11, 03, 0d, 05, 09, 0d, 01, 0e, 01, 01, 1b, 03, 02, 0b, 00, 18, 42, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 3e, 02, 0a, 00, 0b, 3b, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 36, 00, 31, 00, 32, 33, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 31, 00, 32, 47, 01, 09, 00, 17, 0d, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 18 @@ -22,7 +22,7 @@ Number of expressions: 18 - expression 16 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 17 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) = (c0 + (c1 + c2)) - Code(Expression(16, Sub)) at (prev + 1, 12) to (start + 0, 25) diff --git a/tests/coverage/abort.coverage b/tests/coverage/abort.coverage index ceef63867807..b658a6562591 100644 --- a/tests/coverage/abort.coverage +++ b/tests/coverage/abort.coverage @@ -10,6 +10,7 @@ LL| 12| } LL| 12|} LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| 11| while countdown > 0 { diff --git a/tests/coverage/abort.rs b/tests/coverage/abort.rs index 98264bdc1afe..649e8e52a490 100644 --- a/tests/coverage/abort.rs +++ b/tests/coverage/abort.rs @@ -10,6 +10,7 @@ extern "C" fn might_abort(should_abort: bool) { } } +#[rustfmt::skip] fn main() -> Result<(), u8> { let mut countdown = 10; while countdown > 0 { diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 6bdcca40ed66..e06d1676358f 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -1,20 +1,20 @@ Function name: async::c -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 25) Function name: async::c::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 07, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 09, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 7, 25) to (start + 1, 14) +- Code(Counter(0)) at (prev + 9, 25) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) @@ -22,84 +22,84 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: async::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 20) Function name: async::d::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25) Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 1) to (start + 0, 20) +- Code(Zero) at (prev + 19, 1) to (start + 0, 20) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 20) to (start + 0, 25) +- Code(Zero) at (prev + 19, 20) to (start + 0, 25) Function name: async::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 20) Function name: async::f::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 21, 20) to (start + 0, 25) Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 0, 30) +- Code(Zero) at (prev + 23, 1) to (start + 0, 30) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 1e, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 1e, 00, 2d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 30) to (start + 0, 45) +- Code(Zero) at (prev + 23, 30) to (start + 0, 45) Function name: async::g -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23) Function name: async::g::{closure#0} (unused) -Raw bytes (69): 0x[01, 01, 00, 0d, 00, 17, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 13 -- Code(Zero) at (prev + 23, 23) to (start + 1, 12) +- Code(Zero) at (prev + 25, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 17) - Code(Zero) at (prev + 0, 18) to (start + 0, 23) @@ -114,20 +114,20 @@ Number of file 0 mappings: 13 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::h -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 00, 16] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 00, 16] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 22) Function name: async::h::{closure#0} (unused) -Raw bytes (44): 0x[01, 01, 00, 08, 00, 1f, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (44): 0x[01, 01, 00, 08, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 8 -- Code(Zero) at (prev + 31, 22) to (start + 3, 12) +- Code(Zero) at (prev + 33, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 19) - Code(Zero) at (prev + 0, 20) to (start + 0, 25) @@ -137,22 +137,22 @@ Number of file 0 mappings: 8 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::i -Raw bytes (9): 0x[01, 01, 00, 01, 01, 28, 01, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2a, 01, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 40, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 42, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 28, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 2a, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(8) - expression 1 operands: lhs = Counter(6), rhs = Counter(7) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 40, 19) to (start + 4, 12) +- Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12) - Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24) @@ -169,14 +169,14 @@ Number of file 0 mappings: 14 = ((c6 + c7) + c8) Function name: async::j -Raw bytes (53): 0x[01, 01, 02, 07, 0d, 05, 09, 09, 01, 33, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 07, 0d, 05, 09, 09, 01, 35, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 51, 1) to (start + 19, 12) +- Code(Counter(0)) at (prev + 53, 1) to (start + 19, 12) - Code(Counter(1)) at (prev + 20, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) - Code(Counter(1)) at (prev + 0, 31) to (start + 0, 39) @@ -188,14 +188,14 @@ Number of file 0 mappings: 9 = ((c1 + c2) + c3) Function name: async::j::c -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 35, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 0a, 0d, 00, 0e, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 37, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 0a, 0d, 00, 0e, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 53, 5) to (start + 1, 18) +- Code(Counter(0)) at (prev + 55, 5) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 10, 13) to (start + 0, 14) = (c0 - c1) @@ -203,35 +203,35 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: async::j::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 44, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 46, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 68, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 70, 5) to (start + 0, 23) Function name: async::j::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 45, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 47, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 69, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 71, 5) to (start + 0, 23) Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 00, 4d, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 4f, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Zero) at (prev + 77, 1) to (start + 1, 12) +- Code(Zero) at (prev + 79, 1) to (start + 1, 12) - Code(Zero) at (prev + 2, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::l -Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 55, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 57, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -240,7 +240,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Expression(3, Add), rhs = Expression(0, Sub) - expression 3 operands: lhs = Counter(2), rhs = Counter(1) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 85, 1) to (start + 1, 12) +- Code(Counter(0)) at (prev + 87, 1) to (start + 1, 12) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) = (c0 - (c1 + c2)) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) @@ -249,26 +249,26 @@ Number of file 0 mappings: 5 = ((c2 + c1) + (c0 - (c1 + c2))) Function name: async::m -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5d, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5f, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 93, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 95, 1) to (start + 0, 25) Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 5d, 19, 00, 22] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 5f, 19, 00, 22] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 93, 25) to (start + 0, 34) +- Code(Zero) at (prev + 95, 25) to (start + 0, 34) Function name: async::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5f, 01, 08, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 61, 01, 08, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 95, 1) to (start + 8, 2) +- Code(Counter(0)) at (prev + 97, 1) to (start + 8, 2) diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 015e03d5165f..8408769cdc12 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -1,6 +1,8 @@ LL| |#![feature(coverage_attribute)] + LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip] LL| |#![feature(noop_waker)] LL| |#![allow(unused_assignments, dead_code)] + LL| |#![rustfmt::skip] LL| |// edition: 2018 LL| |// compile-flags: -Copt-level=1 LL| | diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index abc9e5f7f646..388cd6456316 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -1,6 +1,8 @@ #![feature(coverage_attribute)] +#![feature(custom_inner_attributes)] // for #![rustfmt::skip] #![feature(noop_waker)] #![allow(unused_assignments, dead_code)] +#![rustfmt::skip] // edition: 2018 // compile-flags: -Copt-level=1 diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index c5ac17600cd2..921ca6cf4e1a 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -1,12 +1,12 @@ Function name: closure::main -Raw bytes (128): 0x[01, 01, 02, 01, 05, 05, 02, 18, 01, 08, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 07, 01, 05, 03, 02] +Raw bytes (128): 0x[01, 01, 02, 01, 05, 05, 02, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 07, 01, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 24 -- Code(Counter(0)) at (prev + 8, 1) to (start + 15, 13) +- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13) - Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10) - Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13) - Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10) @@ -34,14 +34,14 @@ Number of file 0 mappings: 24 = (c1 + (c0 - c1)) Function name: closure::main::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 27, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 39, 5) to (start + 2, 20) +- Code(Counter(0)) at (prev + 40, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) @@ -49,46 +49,46 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#10} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 9a, 01, 07, 00, 21] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 9b, 01, 07, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 154, 7) to (start + 0, 33) +- Code(Zero) at (prev + 155, 7) to (start + 0, 33) Function name: closure::main::{closure#11} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 9e, 01, 07, 00, 21] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 9f, 01, 07, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 158, 7) to (start + 0, 33) +- Code(Zero) at (prev + 159, 7) to (start + 0, 33) Function name: closure::main::{closure#12} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, a6, 01, 01, 00, 17] +Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 166, 1) to (start + 0, 23) +- Code(Zero) at (prev + 167, 1) to (start + 0, 23) Function name: closure::main::{closure#13} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, ab, 01, 0d, 02, 0e] +Raw bytes (10): 0x[01, 01, 00, 01, 00, ac, 01, 0d, 02, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 171, 13) to (start + 2, 14) +- Code(Zero) at (prev + 172, 13) to (start + 2, 14) Function name: closure::main::{closure#14} -Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, b2, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 178, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 179, 13) to (start + 2, 27) - Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) @@ -96,7 +96,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#15} -Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] +Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, bb, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -104,7 +104,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 186, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 187, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) = (c1 + (c0 - c1)) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) @@ -115,14 +115,14 @@ Number of file 0 mappings: 6 = (c1 + (c0 - c1)) Function name: closure::main::{closure#16} -Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, c4, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 196, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 197, 13) to (start + 2, 27) - Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) @@ -130,7 +130,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#17} -Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] +Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, cd, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -138,7 +138,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 204, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 205, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) = (c1 + (c0 - c1)) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) @@ -149,14 +149,14 @@ Number of file 0 mappings: 6 = (c1 + (c0 - c1)) Function name: closure::main::{closure#18} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 18, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 24, 13) to (start + 2, 28) +- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) - Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) - Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) = (c0 - c1) @@ -164,14 +164,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#19} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 42, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 66, 13) to (start + 2, 28) +- Code(Counter(0)) at (prev + 67, 13) to (start + 2, 28) - Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) - Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) = (c0 - c1) @@ -179,14 +179,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#1} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 51, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 81, 5) to (start + 2, 20) +- Code(Counter(0)) at (prev + 82, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) @@ -194,14 +194,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#2} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 67, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 103, 5) to (start + 2, 20) +- Code(Counter(0)) at (prev + 104, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) @@ -209,61 +209,61 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#3} (unused) -Raw bytes (25): 0x[01, 01, 00, 04, 00, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Zero) at (prev + 128, 5) to (start + 1, 20) +- Code(Zero) at (prev + 129, 5) to (start + 1, 20) - Code(Zero) at (prev + 1, 21) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) - Code(Zero) at (prev + 1, 9) to (start + 1, 6) Function name: closure::main::{closure#4} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 88, 01, 35, 00, 43] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 89, 01, 35, 00, 43] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 136, 53) to (start + 0, 67) +- Code(Zero) at (prev + 137, 53) to (start + 0, 67) Function name: closure::main::{closure#5} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8b, 01, 3d, 00, 4f] +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 3d, 00, 4f] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 139, 61) to (start + 0, 79) +- Code(Counter(0)) at (prev + 140, 61) to (start + 0, 79) Function name: closure::main::{closure#6} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 41, 00, 57] +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 41, 00, 57] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 140, 65) to (start + 0, 87) +- Code(Counter(0)) at (prev + 141, 65) to (start + 0, 87) Function name: closure::main::{closure#7} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 8d, 01, 3b, 00, 51] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 3b, 00, 51] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 141, 59) to (start + 0, 81) +- Code(Zero) at (prev + 142, 59) to (start + 0, 81) Function name: closure::main::{closure#8} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 92, 01, 3b, 00, 55] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 93, 01, 3b, 00, 55] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 146, 59) to (start + 0, 85) +- Code(Zero) at (prev + 147, 59) to (start + 0, 85) Function name: closure::main::{closure#9} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 94, 01, 38, 02, 06] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 95, 01, 38, 02, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 148, 56) to (start + 2, 6) +- Code(Zero) at (prev + 149, 56) to (start + 2, 6) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 67014f792c81..58224eeaf626 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -5,6 +5,7 @@ LL| |// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by LL| |// . LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/closure.rs b/tests/coverage/closure.rs index 16a2c4e33bd4..4be78062f3f5 100644 --- a/tests/coverage/closure.rs +++ b/tests/coverage/closure.rs @@ -5,6 +5,7 @@ // `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by // . +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 90eeb1a6686f..160b348bd632 100644 --- a/tests/coverage/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map @@ -1,5 +1,5 @@ Function name: closure_bug::main -Raw bytes (201): 0x[01, 01, 26, 01, 05, 05, 02, 05, 02, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 82, 01, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 01, 06, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 97, 01, 02, 09, 00, 0a, 97, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 92, 01, 00, 17, 00, 18, 8f, 01, 02, 09, 00, 0a, 8f, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 8a, 01, 00, 17, 00, 18, 87, 01, 02, 09, 00, 0a, 87, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 82, 01, 00, 17, 00, 18, 7f, 01, 01, 00, 02] +Raw bytes (201): 0x[01, 01, 26, 01, 05, 05, 02, 05, 02, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 82, 01, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 01, 07, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 97, 01, 02, 09, 00, 0a, 97, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 92, 01, 00, 17, 00, 18, 8f, 01, 02, 09, 00, 0a, 8f, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 8a, 01, 00, 17, 00, 18, 87, 01, 02, 09, 00, 0a, 87, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 82, 01, 00, 17, 00, 18, 7f, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 38 @@ -42,7 +42,7 @@ Number of expressions: 38 - expression 36 operands: lhs = Expression(37, Add), rhs = Counter(2) - expression 37 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 17 -- Code(Counter(0)) at (prev + 6, 1) to (start + 3, 10) +- Code(Counter(0)) at (prev + 7, 1) to (start + 3, 10) - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 14) - Code(Counter(1)) at (prev + 1, 15) to (start + 0, 23) - Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 24) @@ -72,14 +72,14 @@ Number of file 0 mappings: 17 = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) Function name: closure_bug::main::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0d, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0e, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 13, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 14, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -87,14 +87,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure_bug::main::{closure#1} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 16, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 17, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 23, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -102,14 +102,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure_bug::main::{closure#2} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 1f, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 20, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 31, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 32, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -117,14 +117,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure_bug::main::{closure#3} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 29, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 40, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 41, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) diff --git a/tests/coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage index f3299834bce1..3bf19f28072f 100644 --- a/tests/coverage/closure_bug.coverage +++ b/tests/coverage/closure_bug.coverage @@ -3,6 +3,7 @@ LL| |// the coverage report. However, an unstable sort was causing them to be treated LL| |// inconsistently when preparing coverage spans. LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| let truthy = std::env::args().len() == 1; LL| 1| diff --git a/tests/coverage/closure_bug.rs b/tests/coverage/closure_bug.rs index 739bc5f0b51c..6c94b90c656e 100644 --- a/tests/coverage/closure_bug.rs +++ b/tests/coverage/closure_bug.rs @@ -3,6 +3,7 @@ // the coverage report. However, an unstable sort was causing them to be treated // inconsistently when preparing coverage spans. +#[rustfmt::skip] fn main() { let truthy = std::env::args().len() == 1; diff --git a/tests/coverage/if.cov-map b/tests/coverage/if.cov-map index 391a69e0e821..d7122f4b1a03 100644 --- a/tests/coverage/if.cov-map +++ b/tests/coverage/if.cov-map @@ -1,12 +1,12 @@ Function name: if::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 06, 00, 07, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 06, 00, 07, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 3, 1) to (start + 18, 16) +- Code(Counter(0)) at (prev + 4, 1) to (start + 18, 16) - Code(Counter(1)) at (prev + 19, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/if.coverage b/tests/coverage/if.coverage index 2e6845190aab..77db24ef51bf 100644 --- a/tests/coverage/if.coverage +++ b/tests/coverage/if.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if.rs b/tests/coverage/if.rs index 8ad5042ff7ba..e8c0e7a7a225 100644 --- a/tests/coverage/if.rs +++ b/tests/coverage/if.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if_else.cov-map b/tests/coverage/if_else.cov-map index da692ca3aa2a..7163681d3a04 100644 --- a/tests/coverage/if_else.cov-map +++ b/tests/coverage/if_else.cov-map @@ -1,5 +1,5 @@ Function name: if_else::main -Raw bytes (53): 0x[01, 01, 07, 01, 05, 05, 02, 1b, 09, 05, 02, 09, 16, 1b, 09, 05, 02, 07, 01, 03, 01, 08, 10, 05, 09, 05, 05, 06, 02, 08, 09, 02, 10, 1b, 06, 09, 00, 10, 09, 01, 05, 05, 06, 16, 07, 05, 05, 06, 13, 06, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 07, 01, 05, 05, 02, 1b, 09, 05, 02, 09, 16, 1b, 09, 05, 02, 07, 01, 04, 01, 08, 10, 05, 09, 05, 05, 06, 02, 08, 09, 02, 10, 1b, 06, 09, 00, 10, 09, 01, 05, 05, 06, 16, 07, 05, 05, 06, 13, 06, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -11,7 +11,7 @@ Number of expressions: 7 - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(2) - expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 3, 1) to (start + 8, 16) +- Code(Counter(0)) at (prev + 4, 1) to (start + 8, 16) - Code(Counter(1)) at (prev + 9, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 8, 9) to (start + 2, 16) = (c0 - c1) diff --git a/tests/coverage/if_else.coverage b/tests/coverage/if_else.coverage index 0274401f0047..2bf93487cec2 100644 --- a/tests/coverage/if_else.coverage +++ b/tests/coverage/if_else.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if_else.rs b/tests/coverage/if_else.rs index 3244e1e3afd2..a0687925d636 100644 --- a/tests/coverage/if_else.rs +++ b/tests/coverage/if_else.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map index fb893e379606..3c660551dea1 100644 --- a/tests/coverage/if_not.cov-map +++ b/tests/coverage/if_not.cov-map @@ -1,5 +1,5 @@ Function name: if_not::if_not -Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 04, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02] +Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 05, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 16 @@ -20,7 +20,7 @@ Number of expressions: 16 - expression 14 operands: lhs = Expression(15, Add), rhs = Counter(2) - expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) +- Code(Counter(0)) at (prev + 5, 1) to (start + 3, 13) - Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 6) to (start + 0, 7) diff --git a/tests/coverage/if_not.coverage b/tests/coverage/if_not.coverage index 41838b8513f6..86ff7fc4f07d 100644 --- a/tests/coverage/if_not.coverage +++ b/tests/coverage/if_not.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |// edition: 2021 LL| | + LL| |#[rustfmt::skip] LL| 12|fn if_not(cond: bool) { LL| 12| if LL| 12| ! diff --git a/tests/coverage/if_not.rs b/tests/coverage/if_not.rs index 4f45ae0b3d44..7b166662b5d0 100644 --- a/tests/coverage/if_not.rs +++ b/tests/coverage/if_not.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] // edition: 2021 +#[rustfmt::skip] fn if_not(cond: bool) { if ! diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 82582b309bfc..6d577b3d4851 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -7,14 +7,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19) Function name: ::fmt -Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 88, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 136, 5) to (start + 1, 37) +- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 37) - Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) @@ -22,15 +22,15 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: issue_84561::main -Raw bytes (10): 0x[01, 01, 00, 01, 01, b2, 01, 01, 04, 02] +Raw bytes (10): 0x[01, 01, 00, 01, 01, b4, 01, 01, 04, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 178, 1) to (start + 4, 2) +- Code(Counter(0)) at (prev + 180, 1) to (start + 4, 2) Function name: issue_84561::test1 -Raw bytes (78): 0x[01, 01, 0e, 05, 06, 01, 05, 09, 36, 03, 09, 0d, 2e, 33, 0d, 09, 36, 03, 09, 11, 26, 2b, 11, 0d, 2e, 33, 0d, 09, 36, 03, 09, 09, 01, 98, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 03, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 33, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 2b, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 23, 01, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 0e, 05, 06, 01, 05, 09, 36, 03, 09, 0d, 2e, 33, 0d, 09, 36, 03, 09, 11, 26, 2b, 11, 0d, 2e, 33, 0d, 09, 36, 03, 09, 09, 01, 9a, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 03, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 33, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 2b, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 23, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 14 @@ -49,7 +49,7 @@ Number of expressions: 14 - expression 12 operands: lhs = Counter(2), rhs = Expression(13, Sub) - expression 13 operands: lhs = Expression(0, Add), rhs = Counter(2) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 152, 1) to (start + 1, 11) +- Code(Counter(0)) at (prev + 154, 1) to (start + 1, 11) - Code(Counter(1)) at (prev + 1, 12) to (start + 0, 30) - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 11) = (c1 + (c0 - c1)) @@ -64,28 +64,28 @@ Number of file 0 mappings: 9 = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) Function name: issue_84561::test2 -Raw bytes (24): 0x[01, 01, 02, 05, 06, 01, 05, 03, 01, ae, 01, 01, 01, 10, 05, 01, 11, 00, 23, 03, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 02, 05, 06, 01, 05, 03, 01, b0, 01, 01, 01, 10, 05, 01, 11, 00, 23, 03, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(1), rhs = Expression(1, Sub) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 174, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 176, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 35) - Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: issue_84561::test2::call_print -Raw bytes (10): 0x[01, 01, 00, 01, 01, a5, 01, 09, 02, 0a] +Raw bytes (10): 0x[01, 01, 00, 01, 01, a7, 01, 09, 02, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 165, 9) to (start + 2, 10) +- Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10) Function name: issue_84561::test3 -Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 71, fe, 01, 82, 02, 71, 69, 6d, 69, 6d, 82, 02, 71, 69, 6d, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 33, 01, 06, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 71, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] +Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 71, fe, 01, 82, 02, 71, 69, 6d, 69, 6d, 82, 02, 71, 69, 6d, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 71, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 65 @@ -155,7 +155,7 @@ Number of expressions: 65 - expression 63 operands: lhs = Expression(64, Sub), rhs = Counter(28) - expression 64 operands: lhs = Counter(26), rhs = Counter(27) Number of file 0 mappings: 51 -- Code(Counter(0)) at (prev + 6, 1) to (start + 3, 28) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31) = (c1 - c2) diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index e693866e2776..9080d95eff5f 100644 --- a/tests/coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage @@ -3,6 +3,8 @@ LL| |// failure-status: 101 LL| 21|#[derive(PartialEq, Eq)] LL| |struct Foo(u32); + LL| | + LL| |#[rustfmt::skip] LL| 1|fn test3() { LL| 1| let is_true = std::env::args().len() == 1; LL| 1| let bar = Foo(1); diff --git a/tests/coverage/issue-84561.rs b/tests/coverage/issue-84561.rs index facf5b5b4cfb..9c218a37e6c4 100644 --- a/tests/coverage/issue-84561.rs +++ b/tests/coverage/issue-84561.rs @@ -3,6 +3,8 @@ // failure-status: 101 #[derive(PartialEq, Eq)] struct Foo(u32); + +#[rustfmt::skip] fn test3() { let is_true = std::env::args().len() == 1; let bar = Foo(1); diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 2d1ff24e62d5..03dbb59d26b5 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -1,5 +1,5 @@ Function name: lazy_boolean::main -Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] +Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 164 @@ -168,7 +168,7 @@ Number of expressions: 164 - expression 162 operands: lhs = Expression(163, Add), rhs = Counter(2) - expression 163 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 28 -- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6) - Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage index 2d927a083560..f058be839008 100644 --- a/tests/coverage/lazy_boolean.coverage +++ b/tests/coverage/lazy_boolean.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs index bb6219e851c8..47bfb1164490 100644 --- a/tests/coverage/lazy_boolean.rs +++ b/tests/coverage/lazy_boolean.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map index 75018442d075..d8dca8a85c38 100644 --- a/tests/coverage/loop_break_value.cov-map +++ b/tests/coverage/loop_break_value.cov-map @@ -1,8 +1,8 @@ Function name: loop_break_value::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 0a, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 01, 0a, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 10, 2) +- Code(Counter(0)) at (prev + 4, 1) to (start + 10, 2) diff --git a/tests/coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage index 1f0630636ddf..7d4533987594 100644 --- a/tests/coverage/loop_break_value.coverage +++ b/tests/coverage/loop_break_value.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| let result LL| 1| = diff --git a/tests/coverage/loop_break_value.rs b/tests/coverage/loop_break_value.rs index dbc4fad7a231..015365c2b3e1 100644 --- a/tests/coverage/loop_break_value.rs +++ b/tests/coverage/loop_break_value.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { let result = diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index f1691ffc5e6a..0a342cb3673a 100644 --- a/tests/coverage/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map @@ -1,5 +1,5 @@ Function name: simple_loop::main -Raw bytes (57): 0x[01, 01, 09, 01, 05, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 1f, 05, 0d, 02, 0e, 1a, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1a, 06, 01, 00, 02] +Raw bytes (57): 0x[01, 01, 09, 01, 05, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 07, 01, 04, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 1f, 05, 0d, 02, 0e, 1a, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1a, 06, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -13,7 +13,7 @@ Number of expressions: 9 - expression 7 operands: lhs = Expression(8, Add), rhs = Counter(2) - expression 8 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 3, 1) to (start + 9, 16) +- Code(Counter(0)) at (prev + 4, 1) to (start + 9, 16) - Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage index 691c6cd1e7dd..b6552c62ff90 100644 --- a/tests/coverage/simple_loop.coverage +++ b/tests/coverage/simple_loop.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/simple_loop.rs b/tests/coverage/simple_loop.rs index 6f7f23475b82..6776911563df 100644 --- a/tests/coverage/simple_loop.rs +++ b/tests/coverage/simple_loop.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map index 4a32745d2929..7c242e2c328d 100644 --- a/tests/coverage/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map @@ -1,5 +1,5 @@ Function name: simple_match::main -Raw bytes (78): 0x[01, 01, 0c, 01, 05, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 27, 05, 09, 00, 0d, 22, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 22, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 0c, 01, 05, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 27, 05, 09, 00, 0d, 22, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 22, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 12 @@ -16,7 +16,7 @@ Number of expressions: 12 - expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub) - expression 11 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/simple_match.coverage b/tests/coverage/simple_match.coverage index 7f5dd3bb6463..3a4fc6743f5e 100644 --- a/tests/coverage/simple_match.coverage +++ b/tests/coverage/simple_match.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/simple_match.rs b/tests/coverage/simple_match.rs index be99e59a8268..2ad4e55b4edc 100644 --- a/tests/coverage/simple_match.rs +++ b/tests/coverage/simple_match.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index a9a18a180ddd..5cfb40ce5289 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -1,12 +1,12 @@ Function name: ::get_thing_2 -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 29, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 40, 5) to (start + 1, 24) +- Code(Counter(0)) at (prev + 41, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) @@ -14,14 +14,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: ::call -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 34, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 51, 5) to (start + 1, 24) +- Code(Counter(0)) at (prev + 52, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) @@ -44,14 +44,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: try_error_result::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 70, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 73, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 112, 1) to (start + 2, 12) +- Code(Counter(0)) at (prev + 115, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) @@ -59,7 +59,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: try_error_result::test1 -Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 23, 19, 11, 15, 0b, 01, 0c, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] +Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 23, 19, 11, 15, 0b, 01, 0d, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -73,7 +73,7 @@ Number of expressions: 9 - expression 7 operands: lhs = Expression(8, Add), rhs = Counter(6) - expression 8 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 12, 1) to (start + 2, 23) +- Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23) - Code(Expression(0, Add)) at (prev + 7, 9) to (start + 0, 14) = (c0 + (c1 + c2)) - Code(Expression(5, Sub)) at (prev + 2, 9) to (start + 4, 26) @@ -91,7 +91,7 @@ Number of file 0 mappings: 11 = (((c4 + c5) + c6) + c3) Function name: try_error_result::test2 -Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] +Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3e, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 59 @@ -155,7 +155,7 @@ Number of expressions: 59 - expression 57 operands: lhs = Counter(12), rhs = Counter(13) - expression 58 operands: lhs = Counter(14), rhs = Counter(15) Number of file 0 mappings: 40 -- Code(Counter(0)) at (prev + 60, 1) to (start + 3, 23) +- Code(Counter(0)) at (prev + 62, 1) to (start + 3, 23) - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14) = (c0 + (c1 + c2)) - Code(Expression(36, Sub)) at (prev + 2, 9) to (start + 4, 26) diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 5d48cbd62f20..418efa7fcb5c 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -9,6 +9,7 @@ LL| | } LL| 6|} LL| | + LL| |#[rustfmt::skip] LL| 1|fn test1() -> Result<(), ()> { LL| 1| let mut LL| 1| countdown = 10 @@ -58,6 +59,7 @@ LL| 17| } LL| |} LL| | + LL| |#[rustfmt::skip] LL| 1|fn test2() -> Result<(), ()> { LL| 1| let thing1 = Thing1{}; LL| 1| let mut @@ -115,6 +117,7 @@ LL| 0| Ok(()) LL| 1|} LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), ()> { LL| 1| test1().expect_err("test1 should fail"); LL| 1| test2() diff --git a/tests/coverage/try_error_result.rs b/tests/coverage/try_error_result.rs index 557cbf22bfad..1acc26169123 100644 --- a/tests/coverage/try_error_result.rs +++ b/tests/coverage/try_error_result.rs @@ -9,6 +9,7 @@ fn call(return_error: bool) -> Result<(), ()> { } } +#[rustfmt::skip] fn test1() -> Result<(), ()> { let mut countdown = 10 @@ -57,6 +58,7 @@ impl Thing2 { } } +#[rustfmt::skip] fn test2() -> Result<(), ()> { let thing1 = Thing1{}; let mut @@ -109,6 +111,7 @@ fn test2() -> Result<(), ()> { Ok(()) } +#[rustfmt::skip] fn main() -> Result<(), ()> { test1().expect_err("test1 should fail"); test2() diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map index 369ebe891f12..c883eb4baf20 100644 --- a/tests/coverage/while_early_ret.cov-map +++ b/tests/coverage/while_early_ret.cov-map @@ -1,5 +1,5 @@ Function name: while_early_ret::main -Raw bytes (61): 0x[01, 01, 06, 01, 05, 03, 09, 0e, 05, 03, 09, 17, 09, 0d, 11, 09, 01, 04, 01, 01, 1b, 03, 03, 09, 02, 0a, 0e, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 13, 01, 01, 00, 02] +Raw bytes (61): 0x[01, 01, 06, 01, 05, 03, 09, 0e, 05, 03, 09, 17, 09, 0d, 11, 09, 01, 05, 01, 01, 1b, 03, 03, 09, 02, 0a, 0e, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 13, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -10,7 +10,7 @@ Number of expressions: 6 - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2) - expression 5 operands: lhs = Counter(3), rhs = Counter(4) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 2, 10) = (c0 + c1) - Code(Expression(3, Sub)) at (prev + 5, 13) to (start + 2, 14) diff --git a/tests/coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage index 49d39d366038..f4372ad282e3 100644 --- a/tests/coverage/while_early_ret.coverage +++ b/tests/coverage/while_early_ret.coverage @@ -1,6 +1,7 @@ LL| |#![allow(unused_assignments)] LL| |// failure-status: 1 LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| | while diff --git a/tests/coverage/while_early_ret.rs b/tests/coverage/while_early_ret.rs index b2f0eee2cc0f..a6421e797f61 100644 --- a/tests/coverage/while_early_ret.rs +++ b/tests/coverage/while_early_ret.rs @@ -1,6 +1,7 @@ #![allow(unused_assignments)] // failure-status: 1 +#[rustfmt::skip] fn main() -> Result<(), u8> { let mut countdown = 10; while From 1f9353ae2ca81b0a508e38751b0d3ab213526f56 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 14:12:10 +1100 Subject: [PATCH 177/297] coverage: Tweak individual tests to be unaffected by `rustfmt` Some of these tests use non-standard formatting that we can simulate by strategically adding `//` line comments. One contains `where` clauses that would be split across multiple lines, which we can keep on one line by moving the bounds to the generic type instead. --- tests/coverage/conditions.cov-map | 4 +- tests/coverage/conditions.coverage | 1 + tests/coverage/conditions.rs | 1 + tests/coverage/fn_sig_into_try.cov-map | 68 ++++++++++++------------- tests/coverage/fn_sig_into_try.coverage | 4 ++ tests/coverage/fn_sig_into_try.rs | 4 ++ tests/coverage/generics.coverage | 6 +-- tests/coverage/generics.rs | 6 +-- tests/coverage/while.cov-map | 6 +-- tests/coverage/while.coverage | 1 + tests/coverage/while.rs | 1 + 11 files changed, 57 insertions(+), 45 deletions(-) diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index cfee55ed31a4..a6a427aca007 100644 --- a/tests/coverage/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -1,5 +1,5 @@ Function name: conditions::main -Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, 31, ab, 04, 2d, 25, 29, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 03, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] +Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, 31, ab, 04, 2d, 25, 29, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 04, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 142 @@ -197,7 +197,7 @@ Number of file 0 mappings: 68 - Code(Expression(56, Add)) at (prev + 2, 12) to (start + 0, 25) = (c24 + Zero) - Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(55, Sub)) at (prev + 3, 17) to (start + 0, 30) +- Code(Expression(55, Sub)) at (prev + 4, 17) to (start + 0, 30) = ((c24 + Zero) - c25) - Code(Expression(54, Sub)) at (prev + 1, 16) to (start + 0, 29) = (((c24 + Zero) - c25) - c11) diff --git a/tests/coverage/conditions.coverage b/tests/coverage/conditions.coverage index 473335ff641a..48516217592e 100644 --- a/tests/coverage/conditions.coverage +++ b/tests/coverage/conditions.coverage @@ -49,6 +49,7 @@ LL| 1| if countdown > 7 { LL| 1| countdown -= 4; LL| 1| } + LL| | // LL| 0| else if countdown > 2 { LL| 0| if countdown < 1 || countdown > 5 || countdown != 9 { LL| 0| countdown = 0; diff --git a/tests/coverage/conditions.rs b/tests/coverage/conditions.rs index fa7f2a116c21..e18e7191e612 100644 --- a/tests/coverage/conditions.rs +++ b/tests/coverage/conditions.rs @@ -45,6 +45,7 @@ fn main() { if countdown > 7 { countdown -= 4; } + // else if countdown > 2 { if countdown < 1 || countdown > 5 || countdown != 9 { countdown = 0; diff --git a/tests/coverage/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map index 6e26c61aac9f..c3969f8ce999 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -1,53 +1,53 @@ Function name: fn_sig_into_try::a -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 04, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 4, 2) +- Code(Counter(0)) at (prev + 10, 1) to (start + 5, 2) Function name: fn_sig_into_try::b -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 10, 01, 02, 0f, 00, 02, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Zero - expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15) -- Code(Zero) at (prev + 2, 15) to (start + 0, 16) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) - = (Zero + (c0 - Zero)) - -Function name: fn_sig_into_try::c -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 16, 01, 02, 17, 00, 02, 17, 00, 18, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 23) -- Code(Zero) at (prev + 2, 23) to (start + 0, 24) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) - = (Zero + (c0 - Zero)) - -Function name: fn_sig_into_try::d -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 1c, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 28, 1) to (start + 3, 15) +- Code(Counter(0)) at (prev + 17, 1) to (start + 3, 15) - Code(Zero) at (prev + 3, 15) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = (Zero + (c0 - Zero)) +Function name: fn_sig_into_try::c +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 24, 1) to (start + 3, 23) +- Code(Zero) at (prev + 3, 23) to (start + 0, 24) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) + = (c0 - Zero) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (Zero + (c0 - Zero)) + +Function name: fn_sig_into_try::d +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 1) to (start + 4, 15) +- Code(Zero) at (prev + 4, 15) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) + = (c0 - Zero) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (Zero + (c0 - Zero)) + diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage index f1ddb1da7802..71e15fc11eb8 100644 --- a/tests/coverage/fn_sig_into_try.coverage +++ b/tests/coverage/fn_sig_into_try.coverage @@ -8,12 +8,14 @@ LL| |// signature should be handled in the same way. LL| | LL| 1|fn a() -> Option + LL| 1|// LL| 1|{ LL| 1| Some(7i32); LL| 1| Some(0) LL| 1|} LL| | LL| 1|fn b() -> Option + LL| 1|// LL| 1|{ LL| 1| Some(7i32)?; ^0 @@ -21,6 +23,7 @@ LL| 1|} LL| | LL| 1|fn c() -> Option + LL| 1|// LL| 1|{ LL| 1| let _ = Some(7i32)?; ^0 @@ -28,6 +31,7 @@ LL| 1|} LL| | LL| 1|fn d() -> Option + LL| 1|// LL| 1|{ LL| 1| let _: () = (); LL| 1| Some(7i32)?; diff --git a/tests/coverage/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs index 92850c8a188f..1f4cc67af838 100644 --- a/tests/coverage/fn_sig_into_try.rs +++ b/tests/coverage/fn_sig_into_try.rs @@ -8,24 +8,28 @@ // signature should be handled in the same way. fn a() -> Option +// { Some(7i32); Some(0) } fn b() -> Option +// { Some(7i32)?; Some(0) } fn c() -> Option +// { let _ = Some(7i32)?; Some(0) } fn d() -> Option +// { let _: () = (); Some(7i32)?; diff --git a/tests/coverage/generics.coverage b/tests/coverage/generics.coverage index 098391835663..c68c0be80b15 100644 --- a/tests/coverage/generics.coverage +++ b/tests/coverage/generics.coverage @@ -1,11 +1,11 @@ LL| |#![allow(unused_assignments)] LL| |// failure-status: 1 LL| | - LL| |struct Firework where T: Copy + std::fmt::Display { + LL| |struct Firework { LL| | strength: T, LL| |} LL| | - LL| |impl Firework where T: Copy + std::fmt::Display { + LL| |impl Firework { LL| | #[inline(always)] LL| 3| fn set_strength(&mut self, new_strength: T) { LL| 3| self.strength = new_strength; @@ -23,7 +23,7 @@ ------------------ LL| |} LL| | - LL| |impl Drop for Firework where T: Copy + std::fmt::Display { + LL| |impl Drop for Firework { LL| | #[inline(always)] LL| 2| fn drop(&mut self) { LL| 2| println!("BOOM times {}!!!", self.strength); diff --git a/tests/coverage/generics.rs b/tests/coverage/generics.rs index bf4c2d8d6853..fd3811b6937b 100644 --- a/tests/coverage/generics.rs +++ b/tests/coverage/generics.rs @@ -1,18 +1,18 @@ #![allow(unused_assignments)] // failure-status: 1 -struct Firework where T: Copy + std::fmt::Display { +struct Firework { strength: T, } -impl Firework where T: Copy + std::fmt::Display { +impl Firework { #[inline(always)] fn set_strength(&mut self, new_strength: T) { self.strength = new_strength; } } -impl Drop for Firework where T: Copy + std::fmt::Display { +impl Drop for Firework { #[inline(always)] fn drop(&mut self) { println!("BOOM times {}!!!", self.strength); diff --git a/tests/coverage/while.cov-map b/tests/coverage/while.cov-map index af250f3fb710..c6557b48e27d 100644 --- a/tests/coverage/while.cov-map +++ b/tests/coverage/while.cov-map @@ -1,5 +1,5 @@ Function name: while::main -Raw bytes (28): 0x[01, 01, 02, 01, 00, 03, 00, 04, 01, 01, 01, 01, 10, 03, 02, 0b, 00, 14, 00, 00, 15, 01, 06, 06, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 00, 03, 00, 04, 01, 01, 01, 01, 10, 03, 02, 0b, 00, 14, 00, 00, 15, 02, 06, 06, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -9,7 +9,7 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 1, 1) to (start + 1, 16) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 20) = (c0 + Zero) -- Code(Zero) at (prev + 0, 21) to (start + 1, 6) -- Code(Expression(1, Sub)) at (prev + 2, 1) to (start + 0, 2) +- Code(Zero) at (prev + 0, 21) to (start + 2, 6) +- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2) = ((c0 + Zero) - Zero) diff --git a/tests/coverage/while.coverage b/tests/coverage/while.coverage index c9d497651c9f..90c16288d668 100644 --- a/tests/coverage/while.coverage +++ b/tests/coverage/while.coverage @@ -1,6 +1,7 @@ LL| 1|fn main() { LL| 1| let num = 9; LL| 1| while num >= 10 { + LL| 0| // loop body LL| 0| } LL| 1|} diff --git a/tests/coverage/while.rs b/tests/coverage/while.rs index 781b90b35663..d60916a97981 100644 --- a/tests/coverage/while.rs +++ b/tests/coverage/while.rs @@ -1,5 +1,6 @@ fn main() { let num = 9; while num >= 10 { + // loop body } } From 40166c894ad7f3de348545da0e92d88e2ead393f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 17:37:24 +1100 Subject: [PATCH 178/297] Don't allow `.html` files in `tests/mir-opt/` HTML files were needed for testing `-Z dump-mir-spanview`, but that flag has been removed by #119566. --- src/tools/miropt-test-tools/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs index cae96f593199..7d60033c3e82 100644 --- a/src/tools/miropt-test-tools/src/lib.rs +++ b/src/tools/miropt-test-tools/src/lib.rs @@ -98,11 +98,12 @@ pub fn files_for_miropt_test( from_file = format!("{}.{}.mir", test_name, first_pass); to_file = Some(second_file); } else { - let ext_re = regex::Regex::new(r#"(\.(mir|dot|html))$"#).unwrap(); - let cap = ext_re - .captures_iter(test_name) - .next() - .expect("test_name has an invalid extension"); + // Allow-list for file extensions that can be produced by MIR dumps. + // Other extensions can be added here, as needed by new dump flags. + let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap(); + let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| { + panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}") + }); let extension = cap.get(1).unwrap().as_str(); expected_file = From a3fe3bbb2c80d155e31230bb75078b44904051bc Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 6 Nov 2022 19:26:25 +0300 Subject: [PATCH 179/297] borrowck: wf-check fn item args --- compiler/rustc_borrowck/src/type_check/mod.rs | 10 ++++ library/std/src/collections/hash/map.rs | 5 +- tests/ui/borrowck/fn-item-check-trait-ref.rs | 15 +++++ .../borrowck/fn-item-check-trait-ref.stderr | 12 ++++ .../ui/borrowck/fn-item-check-type-params.rs | 57 +++++++++++++++++++ .../borrowck/fn-item-check-type-params.stderr | 43 ++++++++++++++ .../higher-ranked/trait-bounds/issue-59311.rs | 1 + .../trait-bounds/issue-59311.stderr | 11 +++- ...=> implied-bounds-on-trait-hierarchy-1.rs} | 9 ++- ...implied-bounds-on-trait-hierarchy-1.stderr | 16 ++++++ .../implied-bounds-on-trait-hierarchy-2.rs | 45 +++++++++++++++ .../lifetimes/lifetime-errors/issue_74400.rs | 2 + .../lifetime-errors/issue_74400.stderr | 32 ++++++++++- .../wf-nested.fail.stderr | 2 +- .../wf-nested.pass_sound.stderr | 17 +++++- tests/ui/type-alias-impl-trait/wf-nested.rs | 4 +- tests/ui/wf/wf-in-fn-type-implicit.rs | 37 ------------ 17 files changed, 269 insertions(+), 49 deletions(-) create mode 100644 tests/ui/borrowck/fn-item-check-trait-ref.rs create mode 100644 tests/ui/borrowck/fn-item-check-trait-ref.stderr create mode 100644 tests/ui/borrowck/fn-item-check-type-params.rs create mode 100644 tests/ui/borrowck/fn-item-check-type-params.stderr rename tests/ui/implied-bounds/{implied-bounds-on-trait-hierarchy.rs => implied-bounds-on-trait-hierarchy-1.rs} (72%) create mode 100644 tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr create mode 100644 tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs delete mode 100644 tests/ui/wf/wf-in-fn-type-implicit.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9c0f53ddb86f..05979bfabbdc 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -406,6 +406,16 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { instantiated_predicates, locations, ); + + assert!(!matches!( + tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)), + Some(DefKind::Impl { of_trait: true }) + )); + self.cx.prove_predicates( + args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())), + locations, + ConstraintCategory::Boring, + ); } } } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 39e94902cfe5..1a416a4d10bd 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3049,8 +3049,9 @@ where #[stable(feature = "hash_extend_copy", since = "1.4.0")] impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap where - K: Eq + Hash + Copy, - V: Copy, + // FIXME(aliemjay): the bound `+ 'a` should not be necessary. + K: Eq + Hash + Copy + 'a, + V: Copy + 'a, S: BuildHasher, { #[inline] diff --git a/tests/ui/borrowck/fn-item-check-trait-ref.rs b/tests/ui/borrowck/fn-item-check-trait-ref.rs new file mode 100644 index 000000000000..bdbb52e974f6 --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-trait-ref.rs @@ -0,0 +1,15 @@ +// The method `assert_static` should be callable only for static values, +// because the impl has an implied bound `where T: 'static`. + +// check-fail + +trait AnyStatic: Sized { + fn assert_static(self) {} +} + +impl AnyStatic<&'static T> for T {} + +fn main() { + (&String::new()).assert_static(); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/borrowck/fn-item-check-trait-ref.stderr b/tests/ui/borrowck/fn-item-check-trait-ref.stderr new file mode 100644 index 000000000000..92fd67c316c9 --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-trait-ref.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/fn-item-check-trait-ref.rs:13:7 + | +LL | (&String::new()).assert_static(); + | --^^^^^^^^^^^^^------------------ temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/fn-item-check-type-params.rs b/tests/ui/borrowck/fn-item-check-type-params.rs new file mode 100644 index 000000000000..805c0d00de5d --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-type-params.rs @@ -0,0 +1,57 @@ +// Regression test for #104005. +// +// Previously, different borrowck implementations used to disagree here. +// The status of each is documented on `fn test_*`. + +// check-fail + +use std::fmt::Display; + +trait Displayable { + fn display(self) -> Box; +} + +impl Displayable for (T, Option<&'static T>) { + fn display(self) -> Box { + Box::new(self.0) + } +} + +fn extend_lt(val: T) -> Box +where + (T, Option): Displayable, +{ + Displayable::display((val, None)) +} + +// AST: fail +// HIR: pass +// MIR: pass +pub fn test_call<'a>(val: &'a str) { + extend_lt(val); + //~^ ERROR borrowed data escapes outside of function +} + +// AST: fail +// HIR: fail +// MIR: pass +pub fn test_coercion<'a>() { + let _: fn(&'a str) -> _ = extend_lt; + //~^ ERROR lifetime may not live long enough +} + +// AST: fail +// HIR: fail +// MIR: fail +pub fn test_arg() { + fn want(_: I, _: impl Fn(I) -> O) {} + want(&String::new(), extend_lt); + //~^ ERROR temporary value dropped while borrowed +} + +// An exploit of the unsoundness. +fn main() { + let val = extend_lt(&String::from("blah blah blah")); + //~^ ERROR temporary value dropped while borrowed + println!("{}", val); +} diff --git a/tests/ui/borrowck/fn-item-check-type-params.stderr b/tests/ui/borrowck/fn-item-check-type-params.stderr new file mode 100644 index 000000000000..3a29edc55c54 --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-type-params.stderr @@ -0,0 +1,43 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/fn-item-check-type-params.rs:31:5 + | +LL | pub fn test_call<'a>(val: &'a str) { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | extend_lt(val); + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/fn-item-check-type-params.rs:39:12 + | +LL | pub fn test_coercion<'a>() { + | -- lifetime `'a` defined here +LL | let _: fn(&'a str) -> _ = extend_lt; + | ^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/fn-item-check-type-params.rs:48:11 + | +LL | want(&String::new(), extend_lt); + | ------^^^^^^^^^^^^^------------- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/fn-item-check-type-params.rs:54:26 + | +LL | let val = extend_lt(&String::from("blah blah blah")); + | -----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0521, E0716. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs index 3ad548450e58..387c78a802a7 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs @@ -17,6 +17,7 @@ where v.t(|| {}); //~^ ERROR: higher-ranked lifetime error //~| ERROR: higher-ranked lifetime error + //~| ERROR: higher-ranked lifetime error } fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index e50aad876d8c..3053a2998026 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -6,6 +6,15 @@ LL | v.t(|| {}); | = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` +error: higher-ranked lifetime error + --> $DIR/issue-59311.rs:17:5 + | +LL | v.t(|| {}); + | ^^^^^^^^^^ + | + = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 | @@ -14,5 +23,5 @@ LL | v.t(|| {}); | = note: could not prove `for<'a> &'a V: 'b` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs similarity index 72% rename from tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs rename to tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs index 9c26cd59d100..b532a110a1c7 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs @@ -1,9 +1,7 @@ -// check-pass -// known-bug: #84591 +// issue: #84591 -// Should fail. Subtrait can incorrectly extend supertrait lifetimes even when -// supertrait has weaker implied bounds than subtrait. Strongly related to -// issue #25860. +// Subtrait was able to incorrectly extend supertrait lifetimes even when +// supertrait had weaker implied bounds than subtrait. trait Subtrait: Supertrait {} trait Supertrait { @@ -34,6 +32,7 @@ fn main() { { let x = "Hello World".to_string(); subs_to_soup((x.as_str(), &mut d)); + //~^ does not live long enough } println!("{}", d); } diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr new file mode 100644 index 000000000000..f44defccf589 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr @@ -0,0 +1,16 @@ +error[E0597]: `x` does not live long enough + --> $DIR/implied-bounds-on-trait-hierarchy-1.rs:34:23 + | +LL | let x = "Hello World".to_string(); + | - binding `x` declared here +LL | subs_to_soup((x.as_str(), &mut d)); + | ^ borrowed value does not live long enough +LL | +LL | } + | - `x` dropped here while still borrowed +LL | println!("{}", d); + | - borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs new file mode 100644 index 000000000000..511a9ad9a2a2 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs @@ -0,0 +1,45 @@ +// check-pass +// known-bug: #84591 + +trait Subtrait<'a, 'b, R>: Supertrait<'a, 'b> {} +trait Supertrait<'a, 'b> { + fn convert(x: &'a T) -> &'b T; +} + +fn need_hrtb_subtrait<'a_, 'b_, S, T: ?Sized>(x: &'a_ T) -> &'b_ T +where + S: for<'a, 'b> Subtrait<'a, 'b, &'b &'a ()>, +{ + need_hrtb_supertrait::(x) + // This call works and drops the implied bound `'a: 'b` + // of the where-bound. This means the where-bound can + // now be used to transmute any two lifetimes. +} + +fn need_hrtb_supertrait<'a_, 'b_, S, T: ?Sized>(x: &'a_ T) -> &'b_ T +where + S: for<'a, 'b> Supertrait<'a, 'b>, +{ + S::convert(x) +} + +struct MyStruct; +impl<'a: 'b, 'b> Supertrait<'a, 'b> for MyStruct { + fn convert(x: &'a T) -> &'b T { + x + } +} +impl<'a, 'b> Subtrait<'a, 'b, &'b &'a ()> for MyStruct {} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + need_hrtb_subtrait::(x) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = extend_lifetime(&x); + } + println!("{}", d); +} diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs index ddb8bacce8f9..f17e0a678c96 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -11,6 +11,8 @@ fn f(data: &[T], key: impl Fn(&T) -> S) { fn g(data: &[T]) { f(data, identity) //~^ ERROR the parameter type + //~| ERROR the parameter type + //~| ERROR the parameter type //~| ERROR mismatched types //~| ERROR implementation of `FnOnce` is not general } diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 677f918fe932..beb838d2ff83 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -12,6 +12,36 @@ help: consider adding an explicit lifetime bound LL | fn g(data: &[T]) { | +++++++++ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound + | +LL | fn g(data: &[T]) { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound + | +LL | fn g(data: &[T]) { + | +++++++++ + error[E0308]: mismatched types --> $DIR/issue_74400.rs:12:5 | @@ -35,7 +65,7 @@ LL | f(data, identity) = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr index dcc4b8021eac..17c1f8897bf0 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:55:27 + --> $DIR/wf-nested.rs:57:27 | LL | type InnerOpaque = impl Sized; | ^^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr index 121664bd9569..f5d3a218542c 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr @@ -12,6 +12,21 @@ help: consider adding an explicit lifetime bound LL | fn test() { | +++++++++ -error: aborting due to 1 previous error +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:46:17 + | +LL | let _ = outer.get(); + | ^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound + | +LL | fn test() { + | +++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs index de3883294891..2f90c4e00e38 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.rs +++ b/tests/ui/type-alias-impl-trait/wf-nested.rs @@ -43,7 +43,9 @@ mod pass_sound { fn test() { let outer = define::(); - let _ = outer.get(); //[pass_sound]~ ERROR `T` may not live long enough + let _ = outer.get(); + //[pass_sound]~^ ERROR `T` may not live long enough + //[pass_sound]~| ERROR `T` may not live long enough } } diff --git a/tests/ui/wf/wf-in-fn-type-implicit.rs b/tests/ui/wf/wf-in-fn-type-implicit.rs deleted file mode 100644 index c5ff92c88754..000000000000 --- a/tests/ui/wf/wf-in-fn-type-implicit.rs +++ /dev/null @@ -1,37 +0,0 @@ -// check-pass -// known-bug: #104005 - -// Should fail. Function type parameters with implicit type annotations are not -// checked for well-formedness, which allows incorrect borrowing. - -// In contrast, user annotations are always checked for well-formedness, and the -// commented code below is correctly rejected by the borrow checker. - -use std::fmt::Display; - -trait Displayable { - fn display(self) -> Box; -} - -impl Displayable for (T, Option<&'static T>) { - fn display(self) -> Box { - Box::new(self.0) - } -} - -fn extend_lt(val: T) -> Box -where - (T, Option): Displayable, -{ - Displayable::display((val, None)) -} - -fn main() { - // *incorrectly* compiles - let val = extend_lt(&String::from("blah blah blah")); - println!("{}", val); - - // *correctly* fails to compile - // let val = extend_lt::<_, &_>(&String::from("blah blah blah")); - // println!("{}", val); -} From 8d4693c0f803d87c1ea127093dab5f0499879e5c Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 7 Nov 2022 12:39:54 +0300 Subject: [PATCH 180/297] borrowck: use implied bounds from impl header --- .../src/type_check/free_region_relations.rs | 25 +++++++++- library/std/src/collections/hash/map.rs | 5 +- tests/ui/wf/wf-associated-const.rs | 42 +++++++++++++++++ tests/ui/wf/wf-associated-const.stderr | 14 ++++++ tests/ui/wf/wf-static-method.rs | 13 ++--- tests/ui/wf/wf-static-method.stderr | 47 ++----------------- 6 files changed, 89 insertions(+), 57 deletions(-) create mode 100644 tests/ui/wf/wf-associated-const.rs create mode 100644 tests/ui/wf/wf-associated-const.stderr diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 4a76d877af0f..011b5b760c23 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -1,5 +1,6 @@ use rustc_data_structures::frozen::Frozen; use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder}; +use rustc_hir::def::DefKind; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives; use rustc_infer::infer::outlives::env::RegionBoundPairs; @@ -195,7 +196,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn create(mut self) -> CreateResult<'tcx> { - let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id()); + let tcx = self.infcx.tcx; + let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local(); + let span = tcx.def_span(defining_ty_def_id); // Insert the facts we know from the predicates. Why? Why not. let param_env = self.param_env; @@ -275,6 +278,26 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { normalized_inputs_and_output.push(norm_ty); } + // Add implied bounds from impl header. + if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) { + for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) { + let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = self + .param_env + .and(type_op::normalize::Normalize::new(ty)) + .fully_perform(self.infcx, span) + else { + tcx.dcx().span_delayed_bug(span, format!("failed to normalize {ty:?}")); + continue; + }; + constraints.extend(c); + + // We currently add implied bounds from the normalized ty only. + // This is more conservative and matches wfcheck behavior. + let c = self.add_implied_bounds(norm_ty); + constraints.extend(c); + } + } + for c in constraints { self.push_region_constraints(c, span); } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 1a416a4d10bd..39e94902cfe5 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3049,9 +3049,8 @@ where #[stable(feature = "hash_extend_copy", since = "1.4.0")] impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap where - // FIXME(aliemjay): the bound `+ 'a` should not be necessary. - K: Eq + Hash + Copy + 'a, - V: Copy + 'a, + K: Eq + Hash + Copy, + V: Copy, S: BuildHasher, { #[inline] diff --git a/tests/ui/wf/wf-associated-const.rs b/tests/ui/wf/wf-associated-const.rs new file mode 100644 index 000000000000..dffa1713eff8 --- /dev/null +++ b/tests/ui/wf/wf-associated-const.rs @@ -0,0 +1,42 @@ +// check that associated consts can assume the impl header is well-formed. + +// FIXME(aliemjay): we should check the impl header is WF at the use site +// but we currently don't in some cases. This is *unsound*. + +trait Foo<'a, 'b, T>: Sized { + const EVIL: fn(u: &'b u32) -> &'a u32; +} + +struct Evil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { + const EVIL: fn(&'b u32) -> &'a u32 = { |u| u }; +} + +struct IndirectEvil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { + const EVIL: fn(&'b u32) -> &'a u32 = { |u| u }; +} + +impl<'a, 'b> Evil<'a, 'b> { + const INHERENT_EVIL: fn(&'b u32) -> &'a u32 = { |u| u }; +} + +// while static methods can *assume* this, we should still +// *check* that it holds at the use site. + +fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + <()>::EVIL(b) // FIXME: should be an error +} + +fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + ::EVIL(b) // FIXME: should be an error +} + +fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + ::INHERENT_EVIL(b) + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/wf/wf-associated-const.stderr b/tests/ui/wf/wf-associated-const.stderr new file mode 100644 index 000000000000..e025d5d468a1 --- /dev/null +++ b/tests/ui/wf/wf-associated-const.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/wf-associated-const.rs:38:5 + | +LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ::INHERENT_EVIL(b) + | ^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/wf/wf-static-method.rs b/tests/ui/wf/wf-static-method.rs index 7ff195230bfe..66546ac489df 100644 --- a/tests/ui/wf/wf-static-method.rs +++ b/tests/ui/wf/wf-static-method.rs @@ -1,8 +1,4 @@ -// check that static methods don't get to assume their trait-ref -// is well-formed. -// FIXME(#27579): this is just a bug. However, our checking with -// static inherent methods isn't quite working - need to -// fix that before removing the check. +// check that static methods can assume their trait-ref is well-formed. trait Foo<'a, 'b, T>: Sized { fn make_me() -> Self { loop {} } @@ -15,7 +11,6 @@ impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { fn make_me() -> Self { } fn static_evil(u: &'b u32) -> &'a u32 { u - //~^ ERROR lifetime may not live long enough } } @@ -25,7 +20,6 @@ impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { fn make_me() -> Self { IndirectEvil(None) } fn static_evil(u: &'b u32) -> &'a u32 { let me = Self::make_me(); - //~^ ERROR lifetime may not live long enough loop {} // (`me` could be used for the lifetime transmute). } } @@ -33,12 +27,11 @@ impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { impl<'a, 'b> Evil<'a, 'b> { fn inherent_evil(u: &'b u32) -> &'a u32 { u - //~^ ERROR lifetime may not live long enough } } -// while static methods don't get to *assume* this, we still -// *check* that they hold. +// while static methods can *assume* this, we should still +// *check* that it holds at the use site. fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { <()>::static_evil(b) diff --git a/tests/ui/wf/wf-static-method.stderr b/tests/ui/wf/wf-static-method.stderr index 161609a5f86a..6c49098aad39 100644 --- a/tests/ui/wf/wf-static-method.stderr +++ b/tests/ui/wf/wf-static-method.stderr @@ -1,44 +1,5 @@ error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:17:9 - | -LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | u - | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:27:18 - | -LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | let me = Self::make_me(); - | ^^^^^^^^^^^^^ requires that `'b` must outlive `'a` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:35:9 - | -LL | impl<'a, 'b> Evil<'a, 'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | fn inherent_evil(u: &'b u32) -> &'a u32 { -LL | u - | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:44:5 + --> $DIR/wf-static-method.rs:37:5 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -50,7 +11,7 @@ LL | <()>::static_evil(b) = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:49:5 + --> $DIR/wf-static-method.rs:42:5 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -62,7 +23,7 @@ LL | ::static_evil(b) = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:54:5 + --> $DIR/wf-static-method.rs:47:5 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -73,5 +34,5 @@ LL | ::inherent_evil(b) | = help: consider adding the following bound: `'b: 'a` -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors From aac2f84794d3122216e07a5a6b00b6facf5e9f16 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Wed, 8 Nov 2023 09:22:24 +0000 Subject: [PATCH 181/297] wf-check type annotations before normalization --- .../traits/query/type_op/ascribe_user_type.rs | 54 +++++++++++-------- tests/ui/wf/wf-associated-const.rs | 9 ++-- tests/ui/wf/wf-associated-const.stderr | 28 +++++++++- 3 files changed, 62 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 152ceeee8699..0aaeacb6a239 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -63,13 +63,16 @@ fn relate_mir_and_user_ty<'tcx>( user_ty: Ty<'tcx>, ) -> Result<(), NoSolution> { let cause = ObligationCause::dummy_with_span(span); + ocx.register_obligation(Obligation::new( + ocx.infcx.tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(user_ty.into()), + )); + let user_ty = ocx.normalize(&cause, param_env, user_ty); ocx.eq(&cause, param_env, mir_ty, user_ty)?; - // FIXME(#104764): We should check well-formedness before normalization. - let predicate = - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(user_ty.into()))); - ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate)); Ok(()) } @@ -113,31 +116,38 @@ fn relate_mir_and_user_args<'tcx>( ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate)); } + // Now prove the well-formedness of `def_id` with `substs`. + // Note for some items, proving the WF of `ty` is not sufficient because the + // well-formedness of an item may depend on the WF of gneneric args not present in the + // item's type. Currently this is true for associated consts, e.g.: + // ```rust + // impl MyTy { + // const CONST: () = { /* arbitrary code that depends on T being WF */ }; + // } + // ``` + for arg in args { + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(arg), + )); + } + if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(self_ty.into()), + )); + let self_ty = ocx.normalize(&cause, param_env, self_ty); let impl_self_ty = tcx.type_of(impl_def_id).instantiate(tcx, args); let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty); ocx.eq(&cause, param_env, self_ty, impl_self_ty)?; - let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - impl_self_ty.into(), - ))); - ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate)); } - // In addition to proving the predicates, we have to - // prove that `ty` is well-formed -- this is because - // the WF of `ty` is predicated on the args being - // well-formed, and we haven't proven *that*. We don't - // want to prove the WF of types from `args` directly because they - // haven't been normalized. - // - // FIXME(nmatsakis): Well, perhaps we should normalize - // them? This would only be relevant if some input - // type were ill-formed but did not appear in `ty`, - // which...could happen with normalization... - let predicate = - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into()))); - ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate)); Ok(()) } diff --git a/tests/ui/wf/wf-associated-const.rs b/tests/ui/wf/wf-associated-const.rs index dffa1713eff8..629d807cb7f3 100644 --- a/tests/ui/wf/wf-associated-const.rs +++ b/tests/ui/wf/wf-associated-const.rs @@ -1,8 +1,5 @@ // check that associated consts can assume the impl header is well-formed. -// FIXME(aliemjay): we should check the impl header is WF at the use site -// but we currently don't in some cases. This is *unsound*. - trait Foo<'a, 'b, T>: Sized { const EVIL: fn(u: &'b u32) -> &'a u32; } @@ -27,11 +24,13 @@ impl<'a, 'b> Evil<'a, 'b> { // *check* that it holds at the use site. fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { - <()>::EVIL(b) // FIXME: should be an error + <()>::EVIL(b) + //~^ ERROR lifetime may not live long enough } fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { - ::EVIL(b) // FIXME: should be an error + ::EVIL(b) + //~^ ERROR lifetime may not live long enough } fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { diff --git a/tests/ui/wf/wf-associated-const.stderr b/tests/ui/wf/wf-associated-const.stderr index e025d5d468a1..b0e1a118fab6 100644 --- a/tests/ui/wf/wf-associated-const.stderr +++ b/tests/ui/wf/wf-associated-const.stderr @@ -1,5 +1,29 @@ error: lifetime may not live long enough - --> $DIR/wf-associated-const.rs:38:5 + --> $DIR/wf-associated-const.rs:27:5 + | +LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | <()>::EVIL(b) + | ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-associated-const.rs:32:5 + | +LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ::EVIL(b) + | ^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-associated-const.rs:37:5 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -10,5 +34,5 @@ LL | ::INHERENT_EVIL(b) | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 3 previous errors From 66090ef7ba5f8586879f8029400a1cc851e7c57f Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 9 Nov 2023 10:12:56 +0000 Subject: [PATCH 182/297] try fast path for wf type ops --- .../src/traits/query/type_op/prove_predicate.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index e21ede47f6d6..14f14ae6e2e0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -30,6 +30,23 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { } } + if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) = + key.value.predicate.kind().skip_binder() + { + match arg.as_type()?.kind() { + ty::Param(_) + | ty::Bool + | ty::Char + | ty::Int(_) + | ty::Float(_) + | ty::Str + | ty::Uint(_) => { + return Some(()); + } + _ => {} + } + } + None } From 290651be72ef3c33c47ac73093b26f752e213f6d Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 16 Jan 2024 11:06:42 +0100 Subject: [PATCH 183/297] don't store const var origins for known vars --- .../infer/error_reporting/need_type_info.rs | 33 ++++--- compiler/rustc_infer/src/infer/freshen.rs | 10 +-- compiler/rustc_infer/src/infer/fudge.rs | 11 ++- compiler/rustc_infer/src/infer/mod.rs | 21 ++--- .../rustc_infer/src/infer/relate/combine.rs | 26 +++--- .../src/infer/relate/generalize.rs | 15 ++-- compiler/rustc_infer/src/infer/resolve.rs | 90 +------------------ compiler/rustc_middle/src/infer/unify_key.rs | 29 +++--- 8 files changed, 70 insertions(+), 165 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 4aefadf590dd..6e1889d3538d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -13,7 +13,9 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource}; use rustc_middle::hir::nested_filter; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ + ConstVariableOrigin, ConstVariableOriginKind, ConstVariableValue, +}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::{self, InferConst}; @@ -178,17 +180,23 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte } }; printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); - let const_getter = move |ct_vid| { - if infcx.probe_const_var(ct_vid).is_ok() { + let const_getter = move |ct_vid| match infcx + .inner + .borrow_mut() + .const_unification_table() + .probe_value(ct_vid) + { + ConstVariableValue::Known { value: _ } => { warn!("resolved const var in error message"); - } - if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = - infcx.inner.borrow_mut().const_unification_table().probe_value(ct_vid).origin.kind - { - return Some(name); - } else { None } + ConstVariableValue::Unknown { origin, universe: _ } => { + if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = origin.kind { + return Some(name); + } else { + None + } + } }; printer.const_infer_name_resolver = Some(Box::new(const_getter)); printer @@ -303,7 +311,12 @@ impl<'tcx> InferCtxt<'tcx> { GenericArgKind::Const(ct) => { if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { let origin = - self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; + match self.inner.borrow_mut().const_unification_table().probe_value(vid) { + ConstVariableValue::Known { value } => { + bug!("resolved infer var: {vid:?} {value}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin, + }; if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = origin.kind { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index c7cab048db1b..d256994d8d1f 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -146,14 +146,8 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(ty::InferConst::Var(v)) => { - let opt_ct = self - .infcx - .inner - .borrow_mut() - .const_unification_table() - .probe_value(v) - .val - .known(); + let opt_ct = + self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known(); self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 8ca97ae1b8e5..99033922bdf7 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -1,4 +1,4 @@ -use rustc_middle::infer::unify_key::ConstVidKey; +use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; @@ -28,10 +28,17 @@ fn const_vars_since_snapshot<'tcx>( snapshot_var_len: usize, ) -> (Range, Vec) { let range = vars_since_snapshot(table, snapshot_var_len); + ( range.start.vid..range.end.vid, (range.start.index()..range.end.index()) - .map(|index| table.probe_value(ConstVid::from_u32(index)).origin) + .map(|index| match table.probe_value(ConstVid::from_u32(index)) { + ConstVariableValue::Known { value: _ } => ConstVariableOrigin { + kind: ConstVariableOriginKind::MiscVariable, + span: rustc_span::DUMMY_SP, + }, + ConstVariableValue::Unknown { origin, universe: _ } => origin, + }) .collect(), ) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e164041c5991..002aad19c498 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -23,8 +23,8 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -1086,7 +1086,7 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }) + .new_key(ConstVariableValue::Unknown { origin, universe }) .vid; ty::Const::new_var(self.tcx, vid, ty) } @@ -1095,10 +1095,7 @@ impl<'tcx> InferCtxt<'tcx> { self.inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid } @@ -1217,10 +1214,7 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid; ty::Const::new_var( self.tcx, @@ -1410,9 +1404,9 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result, ty::UniverseIndex> { - match self.inner.borrow_mut().const_unification_table().probe_value(vid).val { + match self.inner.borrow_mut().const_unification_table().probe_value(vid) { ConstVariableValue::Known { value } => Ok(value), - ConstVariableValue::Unknown { universe } => Err(universe), + ConstVariableValue::Unknown { origin: _, universe } => Err(universe), } } @@ -1709,7 +1703,7 @@ impl<'tcx> InferCtxt<'tcx> { // `ty::ConstKind::Infer(ty::InferConst::Var(v))`. // // Not `inlined_probe_value(v)` because this call site is colder. - match self.inner.borrow_mut().const_unification_table().probe_value(v).val { + match self.inner.borrow_mut().const_unification_table().probe_value(v) { ConstVariableValue::Unknown { .. } => false, ConstVariableValue::Known { .. } => true, } @@ -1876,7 +1870,6 @@ impl<'a, 'tcx> TypeFolder> for ShallowResolver<'a, 'tcx> { .borrow_mut() .const_unification_table() .probe_value(vid) - .val .known() .unwrap_or(ct), ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 4b254fc7df51..9e1dab12b4d4 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -30,14 +30,12 @@ use super::sub::Sub; use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::infer::canonical::OriginalQueryValues; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{AliasRelationDirection, TyVar}; use rustc_middle::ty::{IntType, UintType}; -use rustc_span::DUMMY_SP; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -328,8 +326,12 @@ impl<'tcx> InferCtxt<'tcx> { ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - let span = - self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span; + let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { + ConstVariableValue::Known { value } => { + bug!("instantiating a known const var: {target_vid:?} {value} {ct}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin.span, + }; // FIXME(generic_const_exprs): Occurs check failures for unevaluated // constants and generic expressions are not yet handled correctly. let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize( @@ -340,16 +342,10 @@ impl<'tcx> InferCtxt<'tcx> { ty::Variance::Invariant, )?; - self.inner.borrow_mut().const_unification_table().union_value( - target_vid, - ConstVarValue { - origin: ConstVariableOrigin { - kind: ConstVariableOriginKind::ConstInference, - span: DUMMY_SP, - }, - val: ConstVariableValue::Known { value }, - }, - ); + self.inner + .borrow_mut() + .const_unification_table() + .union_value(target_vid, ConstVariableValue::Known { value }); Ok(value) } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 27d37fd93697..417c8695e248 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -3,7 +3,7 @@ use std::mem; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::MaxUniverse; @@ -431,22 +431,19 @@ where let mut inner = self.infcx.inner.borrow_mut(); let variable_table = &mut inner.const_unification_table(); - let var_value = variable_table.probe_value(vid); - match var_value.val { + match variable_table.probe_value(vid) { ConstVariableValue::Known { value: u } => { drop(inner); self.relate(u, u) } - ConstVariableValue::Unknown { universe } => { + ConstVariableValue::Unknown { origin, universe } => { if self.for_universe.can_name(universe) { Ok(c) } else { let new_var_id = variable_table - .new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { - universe: self.for_universe, - }, + .new_key(ConstVariableValue::Unknown { + origin, + universe: self.for_universe, }) .vid; Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index f317ccee6918..959b09031277 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,12 +1,8 @@ -use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::{FixupError, FixupResult, InferCtxt, Span}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use super::{FixupError, FixupResult, InferCtxt}; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; -use std::ops::ControlFlow; - /////////////////////////////////////////////////////////////////////////// // OPPORTUNISTIC VAR RESOLVER @@ -104,88 +100,6 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx } } -/////////////////////////////////////////////////////////////////////////// -// UNRESOLVED TYPE FINDER - -/// The unresolved type **finder** walks a type searching for -/// type variables that don't yet have a value. The first unresolved type is stored. -/// It does not construct the fully resolved type (which might -/// involve some hashing and so forth). -pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, -} - -impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - UnresolvedTypeOrConstFinder { infcx } - } -} - -impl<'a, 'tcx> TypeVisitor> for UnresolvedTypeOrConstFinder<'a, 'tcx> { - type BreakTy = (ty::Term<'tcx>, Option); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - let t = self.infcx.shallow_resolve(t); - if let ty::Infer(infer_ty) = *t.kind() { - // Since we called `shallow_resolve` above, this must - // be an (as yet...) unresolved inference variable. - let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty { - let mut inner = self.infcx.inner.borrow_mut(); - let ty_vars = &inner.type_variables(); - if let TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeParameterDefinition(_, _), - span, - } = ty_vars.var_origin(ty_vid) - { - Some(span) - } else { - None - } - } else { - None - }; - ControlFlow::Break((t.into(), ty_var_span)) - } else if !t.has_non_region_infer() { - // All const/type variables in inference types must already be resolved, - // no need to visit the contents. - ControlFlow::Continue(()) - } else { - // Otherwise, keep visiting. - t.super_visit_with(self) - } - } - - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { - let ct = self.infcx.shallow_resolve(ct); - if let ty::ConstKind::Infer(i) = ct.kind() { - // Since we called `shallow_resolve` above, this must - // be an (as yet...) unresolved inference variable. - let ct_var_span = if let ty::InferConst::Var(vid) = i { - let mut inner = self.infcx.inner.borrow_mut(); - let ct_vars = &mut inner.const_unification_table(); - if let ConstVariableOrigin { - span, - kind: ConstVariableOriginKind::ConstParameterDefinition(_, _), - } = ct_vars.probe_value(vid).origin - { - Some(span) - } else { - None - } - } else { - None - }; - ControlFlow::Break((ct.into(), ct_var_span)) - } else if !ct.has_non_region_infer() { - // All const/type variables in inference types must already be resolved, - // no need to visit the contents. - ControlFlow::Continue(()) - } else { - // Otherwise, keep visiting. - ct.super_visit_with(self) - } - } -} - /////////////////////////////////////////////////////////////////////////// // FULL TYPE RESOLUTION diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 6e50e8940464..c35799ef47f2 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -120,7 +120,7 @@ pub enum ConstVariableOriginKind { #[derive(Copy, Clone, Debug)] pub enum ConstVariableValue<'tcx> { Known { value: ty::Const<'tcx> }, - Unknown { universe: ty::UniverseIndex }, + Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex }, } impl<'tcx> ConstVariableValue<'tcx> { @@ -134,12 +134,6 @@ impl<'tcx> ConstVariableValue<'tcx> { } } -#[derive(Copy, Clone, Debug)] -pub struct ConstVarValue<'tcx> { - pub origin: ConstVariableOrigin, - pub val: ConstVariableValue<'tcx>, -} - #[derive(PartialEq, Copy, Clone, Debug)] pub struct ConstVidKey<'tcx> { pub vid: ty::ConstVid, @@ -153,7 +147,7 @@ impl<'tcx> From for ConstVidKey<'tcx> { } impl<'tcx> UnifyKey for ConstVidKey<'tcx> { - type Value = ConstVarValue<'tcx>; + type Value = ConstVariableValue<'tcx>; #[inline] fn index(&self) -> u32 { self.vid.as_u32() @@ -167,23 +161,23 @@ impl<'tcx> UnifyKey for ConstVidKey<'tcx> { } } -impl<'tcx> UnifyValue for ConstVarValue<'tcx> { +impl<'tcx> UnifyValue for ConstVariableValue<'tcx> { type Error = NoError; fn unify_values(&value1: &Self, &value2: &Self) -> Result { - Ok(match (value1.val, value2.val) { + match (value1, value2) { (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { bug!("equating two const variables, both of which have known values") } // If one side is known, prefer that one. - (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1, - (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2, + (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(value1), + (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(value2), // If both sides are *unknown*, it hardly matters, does it? ( - ConstVariableValue::Unknown { universe: universe1 }, - ConstVariableValue::Unknown { universe: universe2 }, + ConstVariableValue::Unknown { origin, universe: universe1 }, + ConstVariableValue::Unknown { origin: _, universe: universe2 }, ) => { // If we unify two unbound variables, ?T and ?U, then whatever // value they wind up taking (which must be the same value) must @@ -191,12 +185,9 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { // universe is the minimum of the two universes, because that is // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); - ConstVarValue { - val: ConstVariableValue::Unknown { universe }, - origin: value1.origin, - } + Ok(ConstVariableValue::Unknown { origin, universe }) } - }) + } } } From 3599c18874b6c8cc74ca2228fe61b17731769771 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 16 Jan 2024 10:03:29 +0000 Subject: [PATCH 184/297] Skip dead code checks on items that failed typeck --- compiler/rustc_passes/src/dead.rs | 5 ++++- tests/ui/consts/const-eval/infinite_loop.rs | 10 +++++++++- tests/ui/consts/const-eval/infinite_loop.stderr | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ac2ca23ad417..9422a5944881 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -128,7 +128,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let Some(def_id) = self.typeck_results().type_dependent_def_id(id) { self.check_def_id(def_id); } else { - bug!("no type-dependent def for method"); + assert!( + self.typeck_results().tainted_by_errors.is_some(), + "no type-dependent def for method" + ); } } diff --git a/tests/ui/consts/const-eval/infinite_loop.rs b/tests/ui/consts/const-eval/infinite_loop.rs index 217814906379..9bdb9929becd 100644 --- a/tests/ui/consts/const-eval/infinite_loop.rs +++ b/tests/ui/consts/const-eval/infinite_loop.rs @@ -1,7 +1,13 @@ +//! This test tests two things at once: +//! 1. we error if a const evaluation hits the deny-by-default lint limit +//! 2. we do not ICE on invalid follow-up code + +// compile-flags: -Z tiny-const-eval-limit + fn main() { // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). // The value of `n` will loop indefinitely (4 - 2 - 1 - 4). - let _ = [(); { + let s = [(); { let mut n = 113383; // #20 in https://oeis.org/A006884 while n != 0 { //~^ ERROR is taking a long time @@ -9,4 +15,6 @@ fn main() { } n }]; + + s.nonexistent_method(); } diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.stderr index e7a0a96a1e60..37cd94bf7b7c 100644 --- a/tests/ui/consts/const-eval/infinite_loop.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.stderr @@ -1,5 +1,5 @@ error: constant evaluation is taking a long time - --> $DIR/infinite_loop.rs:6:9 + --> $DIR/infinite_loop.rs:12:9 | LL | / while n != 0 { LL | | @@ -10,9 +10,9 @@ LL | | } = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated - --> $DIR/infinite_loop.rs:4:18 + --> $DIR/infinite_loop.rs:10:18 | -LL | let _ = [(); { +LL | let s = [(); { | __________________^ LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 LL | | while n != 0 { From 8bb1eaee64e170153d21e64cdb437f3d36acd194 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 22:14:48 +0000 Subject: [PATCH 185/297] Introduce helper that deals with moving async args into the coroutine --- compiler/rustc_ast_lowering/src/item.rs | 385 +++++++++++++----------- 1 file changed, 204 insertions(+), 181 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a3ff02f5f695..c8e639b7a966 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1082,196 +1082,219 @@ impl<'hir> LoweringContext<'_, 'hir> { let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else { return self.lower_fn_body_block(span, decl, body); }; - let closure_id = coroutine_kind.closure_id(); - self.lower_body(|this| { - let mut parameters: Vec> = Vec::new(); - let mut statements: Vec> = Vec::new(); - - // Async function parameters are lowered into the closure body so that they are - // captured and so that the drop order matches the equivalent non-async functions. - // - // from: - // - // async fn foo(: , : , : ) { - // - // } - // - // into: - // - // fn foo(__arg0: , __arg1: , __arg2: ) { - // async move { - // let __arg2 = __arg2; - // let = __arg2; - // let __arg1 = __arg1; - // let = __arg1; - // let __arg0 = __arg0; - // let = __arg0; - // drop-temps { } // see comments later in fn for details - // } - // } - // - // If `` is a simple ident, then it is lowered to a single - // `let = ;` statement as an optimization. - // - // Note that the body is embedded in `drop-temps`; an - // equivalent desugaring would be `return { - // };`. 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; - - // Check if this is a binding pattern, if so, we can optimize and avoid adding a - // `let = __argN;` statement. In this case, we do not rename the parameter. - let (ident, is_simple_parameter) = match parameter.pat.kind { - hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => { - (ident, true) - } - // For `ref mut` or wildcard arguments, we can't reuse the binding, but - // we can keep the same name for the parameter. - // This lets rustdoc render it correctly in documentation. - hir::PatKind::Binding(_, _, ident, _) => (ident, false), - hir::PatKind::Wild => { - (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false) - } - _ => { - // Replace the ident for bindings that aren't simple. - let name = format!("__arg{index}"); - let ident = Ident::from_str(&name); - - (ident, false) - } - }; - - let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None); - - // Construct a parameter representing `__argN: ` to replace the parameter of the - // async function. - // - // If this is the simple case, this parameter will end up being the same as the - // original parameter, but with a different pattern id. - let stmt_attrs = this.attrs.get(¶meter.hir_id.local_id).copied(); - let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident); - let new_parameter = hir::Param { - hir_id: parameter.hir_id, - pat: new_parameter_pat, - ty_span: this.lower_span(parameter.ty_span), - span: this.lower_span(parameter.span), - }; - - if is_simple_parameter { - // If this is the simple case, then we only insert one statement that is - // `let = ;`. We re-use the original argument's pattern so that - // `HirId`s are densely assigned. - let expr = this.expr_ident(desugared_span, ident, new_parameter_id); - let stmt = this.stmt_let_pat( - stmt_attrs, - desugared_span, - Some(expr), - parameter.pat, - hir::LocalSource::AsyncFn, - ); - statements.push(stmt); - } else { - // If this is not the simple case, then we construct two statements: - // - // ``` - // let __argN = __argN; - // let = __argN; - // ``` - // - // The first statement moves the parameter into the closure and thus ensures - // that the drop order is correct. - // - // The second statement creates the bindings that the user wrote. - - // Construct the `let mut __argN = __argN;` statement. It must be a mut binding - // because the user may have specified a `ref mut` binding in the next - // statement. - let (move_pat, move_id) = this.pat_ident_binding_mode( - desugared_span, - ident, - hir::BindingAnnotation::MUT, - ); - let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); - let move_stmt = this.stmt_let_pat( - None, - desugared_span, - Some(move_expr), - move_pat, - hir::LocalSource::AsyncFn, - ); - - // Construct the `let = __argN;` statement. We re-use the original - // parameter's pattern so that `HirId`s are densely assigned. - let pattern_expr = this.expr_ident(desugared_span, ident, move_id); - let pattern_stmt = this.stmt_let_pat( - stmt_attrs, - desugared_span, - Some(pattern_expr), - parameter.pat, - hir::LocalSource::AsyncFn, - ); - - statements.push(move_stmt); - statements.push(pattern_stmt); - }; - - parameters.push(new_parameter); - } - - let mkbody = |this: &mut LoweringContext<'_, 'hir>| { - // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); - - // Transform into `drop-temps { }`, 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, this.arena.alloc(user_body)); - - // As noted above, create the final block like - // - // ``` - // { - // let $param_pattern = $raw_param; - // ... - // drop-temps { } - // } - // ``` - let body = this.block_all( - desugared_span, - this.arena.alloc_from_iter(statements), - Some(user_body), - ); - - this.expr_block(body) - }; - let desugaring_kind = match coroutine_kind { - CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async, - CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen, - CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen, - }; - let coroutine_expr = this.make_desugared_coroutine_expr( + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + decl, + body, + coroutine_kind, CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, - body.span, - desugaring_kind, - hir::CoroutineSource::Fn, - mkbody, ); - let hir_id = this.lower_node_id(closure_id); + // FIXME(async_fn_track_caller): Can this be moved above? + let hir_id = this.lower_node_id(coroutine_kind.closure_id()); this.maybe_forward_track_caller(body.span, fn_id, hir_id); - let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) }; - (this.arena.alloc_from_iter(parameters), expr) + (parameters, expr) }) } + /// Lowers a desugared coroutine body after moving all of the arguments + /// into the body. This is to make sure that the future actually owns the + /// arguments that are passed to the function, and to ensure things like + /// drop order are stable. + fn lower_coroutine_body_with_moved_arguments( + &mut self, + decl: &FnDecl, + body: &Block, + coroutine_kind: CoroutineKind, + capture_clause: CaptureBy, + ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) { + let mut parameters: Vec> = Vec::new(); + let mut statements: Vec> = Vec::new(); + + // Async function parameters are lowered into the closure body so that they are + // captured and so that the drop order matches the equivalent non-async functions. + // + // from: + // + // async fn foo(: , : , : ) { + // + // } + // + // into: + // + // fn foo(__arg0: , __arg1: , __arg2: ) { + // async move { + // let __arg2 = __arg2; + // let = __arg2; + // let __arg1 = __arg1; + // let = __arg1; + // let __arg0 = __arg0; + // let = __arg0; + // drop-temps { } // see comments later in fn for details + // } + // } + // + // If `` is a simple ident, then it is lowered to a single + // `let = ;` statement as an optimization. + // + // Note that the body is embedded in `drop-temps`; an + // equivalent desugaring would be `return { + // };`. 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 = self.lower_param(parameter); + let span = parameter.pat.span; + + // Check if this is a binding pattern, if so, we can optimize and avoid adding a + // `let = __argN;` statement. In this case, we do not rename the parameter. + let (ident, is_simple_parameter) = match parameter.pat.kind { + hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => { + (ident, true) + } + // For `ref mut` or wildcard arguments, we can't reuse the binding, but + // we can keep the same name for the parameter. + // This lets rustdoc render it correctly in documentation. + hir::PatKind::Binding(_, _, ident, _) => (ident, false), + hir::PatKind::Wild => { + (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false) + } + _ => { + // Replace the ident for bindings that aren't simple. + let name = format!("__arg{index}"); + let ident = Ident::from_str(&name); + + (ident, false) + } + }; + + let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + + // Construct a parameter representing `__argN: ` to replace the parameter of the + // async function. + // + // If this is the simple case, this parameter will end up being the same as the + // original parameter, but with a different pattern id. + let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied(); + let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident); + let new_parameter = hir::Param { + hir_id: parameter.hir_id, + pat: new_parameter_pat, + ty_span: self.lower_span(parameter.ty_span), + span: self.lower_span(parameter.span), + }; + + if is_simple_parameter { + // If this is the simple case, then we only insert one statement that is + // `let = ;`. We re-use the original argument's pattern so that + // `HirId`s are densely assigned. + let expr = self.expr_ident(desugared_span, ident, new_parameter_id); + let stmt = self.stmt_let_pat( + stmt_attrs, + desugared_span, + Some(expr), + parameter.pat, + hir::LocalSource::AsyncFn, + ); + statements.push(stmt); + } else { + // If this is not the simple case, then we construct two statements: + // + // ``` + // let __argN = __argN; + // let = __argN; + // ``` + // + // The first statement moves the parameter into the closure and thus ensures + // that the drop order is correct. + // + // The second statement creates the bindings that the user wrote. + + // Construct the `let mut __argN = __argN;` statement. It must be a mut binding + // because the user may have specified a `ref mut` binding in the next + // statement. + let (move_pat, move_id) = + self.pat_ident_binding_mode(desugared_span, ident, hir::BindingAnnotation::MUT); + let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id); + let move_stmt = self.stmt_let_pat( + None, + desugared_span, + Some(move_expr), + move_pat, + hir::LocalSource::AsyncFn, + ); + + // Construct the `let = __argN;` statement. We re-use the original + // parameter's pattern so that `HirId`s are densely assigned. + let pattern_expr = self.expr_ident(desugared_span, ident, move_id); + let pattern_stmt = self.stmt_let_pat( + stmt_attrs, + desugared_span, + Some(pattern_expr), + parameter.pat, + hir::LocalSource::AsyncFn, + ); + + statements.push(move_stmt); + statements.push(pattern_stmt); + }; + + parameters.push(new_parameter); + } + + let mkbody = |this: &mut LoweringContext<'_, 'hir>| { + // Create a block from the user's function body: + let user_body = this.lower_block_expr(body); + + // Transform into `drop-temps { }`, 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, this.arena.alloc(user_body)); + + // As noted above, create the final block like + // + // ``` + // { + // let $param_pattern = $raw_param; + // ... + // drop-temps { } + // } + // ``` + let body = this.block_all( + desugared_span, + this.arena.alloc_from_iter(statements), + Some(user_body), + ); + + this.expr_block(body) + }; + let desugaring_kind = match coroutine_kind { + CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async, + CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen, + CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen, + }; + let closure_id = coroutine_kind.closure_id(); + let coroutine_expr = self.make_desugared_coroutine_expr( + capture_clause, + closure_id, + None, + body.span, + desugaring_kind, + hir::CoroutineSource::Fn, + mkbody, + ); + + let expr = hir::Expr { + hir_id: self.lower_node_id(closure_id), + kind: coroutine_expr, + span: self.lower_span(body.span), + }; + + (self.arena.alloc_from_iter(parameters), expr) + } + fn lower_method_sig( &mut self, generics: &Generics, From 450cb5eda6d1db8b5b45a3775cb5316bb623dc63 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 14 Jan 2024 23:23:30 +0100 Subject: [PATCH 186/297] Don't ICE if TAIT-defining fn contains a closure with `_` in return type --- .../src/collect/type_of/opaque.rs | 31 +++++++++------- .../ui/type-alias-impl-trait/closure_infer.rs | 35 +++++++++++++++++++ 2 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/closure_infer.rs diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 1f7ca48234a2..ade24259ed40 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -135,18 +135,25 @@ impl TaitConstraintLocator<'_> { return; } - if let Some(hir_sig) = self.tcx.hir_node_by_def_id(item_def_id).fn_decl() { - if hir_sig.output.get_infer_ret_ty().is_some() { - let guar = self.tcx.dcx().span_delayed_bug( - hir_sig.output.span(), - "inferring return types and opaque types do not mix well", - ); - self.found = Some(ty::OpaqueHiddenType { - span: DUMMY_SP, - ty: Ty::new_error(self.tcx, guar), - }); - return; - } + // Function items with `_` in their return type already emit an error, skip any + // "non-defining use" errors for them. + // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former + // excludes closures, which are allowed to have `_` in their return type. + let hir_node = self.tcx.hir_node_by_def_id(item_def_id); + debug_assert!( + !matches!(hir_node, Node::ForeignItem(..)), + "foreign items cannot constrain opaque types", + ); + if let Some(hir_sig) = hir_node.fn_sig() + && hir_sig.decl.output.get_infer_ret_ty().is_some() + { + let guar = self.tcx.dcx().span_delayed_bug( + hir_sig.decl.output.span(), + "inferring return types and opaque types do not mix well", + ); + self.found = + Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); + return; } // Calling `mir_borrowck` can lead to cycle errors through diff --git a/tests/ui/type-alias-impl-trait/closure_infer.rs b/tests/ui/type-alias-impl-trait/closure_infer.rs new file mode 100644 index 000000000000..04e2323ec4ae --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_infer.rs @@ -0,0 +1,35 @@ +// check-pass + +// Regression test for an ICE: https://github.com/rust-lang/rust/issues/119916 + +#![feature(impl_trait_in_assoc_type)] +#![feature(type_alias_impl_trait)] + +// `impl_trait_in_assoc_type` example from the bug report. +pub trait StreamConsumer { + type BarrierStream; + fn execute() -> Self::BarrierStream; +} + +pub struct DispatchExecutor; + +impl StreamConsumer for DispatchExecutor { + type BarrierStream = impl Sized; + fn execute() -> Self::BarrierStream { + || -> _ {} + } +} + +// Functions that constrain TAITs can contain closures with an `_` in the return type. +type Foo = impl Sized; +fn foo() -> Foo { + || -> _ {} +} + +// The `_` in the closure return type can also be the TAIT itself. +type Bar = impl Sized; +fn bar() -> impl FnOnce() -> Bar { + || -> _ {} +} + +fn main() {} From 22833c177e23c1c80e7ad1cbea33d758dcd94c28 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Mon, 15 Jan 2024 01:21:03 +0100 Subject: [PATCH 187/297] add test for non-defining use of TAIT in foreign function item --- tests/ui/type-alias-impl-trait/issue-77179.rs | 5 +++++ tests/ui/type-alias-impl-trait/issue-77179.stderr | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 093aeb4b2791..3d6c826d6ac5 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -12,3 +12,8 @@ fn test() -> Pointer<_> { fn main() { test(); } + +extern "Rust" { + fn bar() -> Pointer<_>; + //~^ ERROR: the placeholder `_` is not allowed within types +} diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index 68dd6570d00c..c5cacfd3cd35 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -7,6 +7,15 @@ LL | fn test() -> Pointer<_> { | | not allowed in type signatures | help: replace with the correct return type: `Pointer` -error: aborting due to 1 previous error +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-77179.rs:17:25 + | +LL | fn bar() -> Pointer<_>; + | ^ + | | + | not allowed in type signatures + | help: use type parameters instead: `T` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. From f1ee076f8188c02a2f4d06fc2fde2f58bdb3d6f4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 23:12:46 +0000 Subject: [PATCH 188/297] Async closures will move params into the future always --- compiler/rustc_ast_lowering/messages.ftl | 4 -- compiler/rustc_ast_lowering/src/errors.rs | 8 ---- compiler/rustc_ast_lowering/src/expr.rs | 41 ++++++++----------- compiler/rustc_ast_lowering/src/item.rs | 29 ++++++++----- .../src/error_codes/E0708.md | 6 ++- .../async-borrowck-escaping-closure-error.rs | 3 +- ...ync-borrowck-escaping-closure-error.stderr | 21 ---------- .../no-params-non-move-async-closure.rs | 2 +- .../no-params-non-move-async-closure.stderr | 11 ----- .../suggest-on-bare-closure-call.stderr | 5 --- 10 files changed, 41 insertions(+), 89 deletions(-) delete mode 100644 tests/ui/async-await/async-borrowck-escaping-closure-error.stderr delete mode 100644 tests/ui/async-await/no-params-non-move-async-closure.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index e7177402db1d..8615016cda59 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses = ast_lowering_async_coroutines_not_supported = `async` coroutines are not yet supported -ast_lowering_async_non_move_closure_not_supported = - `async` non-`move` closures with parameters are not currently supported - .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure - ast_lowering_att_syntax_only_x86 = the `att_syntax` option is only supported on x86 diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 2811fe104cd0..4843d36372dc 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -145,14 +145,6 @@ pub struct ClosureCannotBeStatic { pub fn_decl_span: Span, } -#[derive(Diagnostic, Clone, Copy)] -#[help] -#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")] -pub struct AsyncNonMoveClosureNotSupported { - #[primary_span] - pub fn_decl_span: Span, -} - #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_functional_record_update_destructuring_assignment)] pub struct FunctionalRecordUpdateDestructuringAssignment { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index e0b1a10c82e7..0920de48eb87 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,6 +1,6 @@ use super::errors::{ - AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, - BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, + AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, + ClosureCannotBeStatic, CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign, @@ -13,7 +13,6 @@ use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_middle::span_bug; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -1028,28 +1027,16 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { - let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else { - span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet"); - }; - if let &ClosureBinder::For { span, .. } = binder { self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); } let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let outer_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let body = self.with_new_scopes(fn_decl_span, |this| { - // FIXME(cramertj): allow `async` non-`move` closures with arguments. - if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { - this.dcx().emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); - } - // Transform `async |x: u8| -> X { ... }` into // `|x: u8| || -> X { ... }`. - let body_id = this.lower_fn_body(&outer_decl, |this| { + let body_id = this.lower_body(|this| { let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx))) @@ -1057,22 +1044,26 @@ impl<'hir> LoweringContext<'_, 'hir> { None }; - let async_body = this.make_desugared_coroutine_expr( - capture_clause, - inner_closure_id, - async_ret_ty, - body.span, - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure, + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + decl, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), + body.span, + coroutine_kind, + hir::CoroutineSource::Closure, + async_ret_ty, ); - let hir_id = this.lower_node_id(inner_closure_id); + + let hir_id = this.lower_node_id(coroutine_kind.closure_id()); this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); - hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) } + + (parameters, expr) }); body_id }); + let outer_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c8e639b7a966..dd3f7289a60b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1085,9 +1085,11 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_body(|this| { let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( decl, - body, + |this| this.lower_block_expr(body), + body.span, coroutine_kind, - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + hir::CoroutineSource::Fn, + None, ); // FIXME(async_fn_track_caller): Can this be moved above? @@ -1102,12 +1104,14 @@ impl<'hir> LoweringContext<'_, 'hir> { /// into the body. This is to make sure that the future actually owns the /// arguments that are passed to the function, and to ensure things like /// drop order are stable. - fn lower_coroutine_body_with_moved_arguments( + pub fn lower_coroutine_body_with_moved_arguments( &mut self, decl: &FnDecl, - body: &Block, + lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>, + body_span: Span, coroutine_kind: CoroutineKind, - capture_clause: CaptureBy, + coroutine_source: hir::CoroutineSource, + return_type_hint: Option>, ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) { let mut parameters: Vec> = Vec::new(); let mut statements: Vec> = Vec::new(); @@ -1246,7 +1250,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mkbody = |this: &mut LoweringContext<'_, 'hir>| { // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); + let user_body = lower_body(this); // Transform into `drop-temps { }`, an expression: let desugared_span = @@ -1277,19 +1281,22 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let closure_id = coroutine_kind.closure_id(); let coroutine_expr = self.make_desugared_coroutine_expr( - capture_clause, + // FIXME(async_closures): This should only move locals, + // and not upvars. Capturing closure upvars by ref doesn't + // work right now anyways, so whatever. + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, closure_id, - None, - body.span, + return_type_hint, + body_span, desugaring_kind, - hir::CoroutineSource::Fn, + coroutine_source, mkbody, ); let expr = hir::Expr { hir_id: self.lower_node_id(closure_id), kind: coroutine_expr, - span: self.lower_span(body.span), + span: self.lower_span(body_span), }; (self.arena.alloc_from_iter(parameters), expr) diff --git a/compiler/rustc_error_codes/src/error_codes/E0708.md b/compiler/rustc_error_codes/src/error_codes/E0708.md index 9287fc803d1d..61a853ac4460 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0708.md +++ b/compiler/rustc_error_codes/src/error_codes/E0708.md @@ -1,12 +1,14 @@ +#### Note: this error code is no longer emitted by the compiler. + `async` non-`move` closures with parameters are currently not supported. Erroneous code example: -```compile_fail,edition2018,E0708 +```edition2018 #![feature(async_closure)] fn main() { - let add_one = async |num: u8| { // error! + let add_one = async |num: u8| { num + 1 }; } diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs index e667b72aee53..f8ff9186842b 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -1,9 +1,10 @@ // edition:2018 +// check-pass + #![feature(async_closure)] fn foo() -> Box> { let x = 0u32; Box::new((async || x)()) - //~^ ERROR E0373 } fn main() { diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr deleted file mode 100644 index 1d8d1c67bae1..000000000000 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-closure-error.rs:5:15 - | -LL | Box::new((async || x)()) - | ^^^^^^^^ - `x` is borrowed here - | | - | may outlive borrowed value `x` - | -note: closure is returned here - --> $DIR/async-borrowck-escaping-closure-error.rs:5:5 - | -LL | Box::new((async || x)()) - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword - | -LL | Box::new((async move || x)()) - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/no-params-non-move-async-closure.rs b/tests/ui/async-await/no-params-non-move-async-closure.rs index 3b15f35c260d..1440d918c50e 100644 --- a/tests/ui/async-await/no-params-non-move-async-closure.rs +++ b/tests/ui/async-await/no-params-non-move-async-closure.rs @@ -1,8 +1,8 @@ // edition:2018 +// check-pass #![feature(async_closure)] fn main() { let _ = async |x: u8| {}; - //~^ ERROR `async` non-`move` closures with parameters are not currently supported } diff --git a/tests/ui/async-await/no-params-non-move-async-closure.stderr b/tests/ui/async-await/no-params-non-move-async-closure.stderr deleted file mode 100644 index d26595536990..000000000000 --- a/tests/ui/async-await/no-params-non-move-async-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0708]: `async` non-`move` closures with parameters are not currently supported - --> $DIR/no-params-non-move-async-closure.rs:6:13 - | -LL | let _ = async |x: u8| {}; - | ^^^^^^^^^^^^^ - | - = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0708`. diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr index e65a6eb4939d..77631b36e0f3 100644 --- a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr +++ b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -18,11 +18,6 @@ LL | let _ = async ||{}(); | ^^-- | | | call expression requires function - | -help: if you meant to create this closure and immediately call it, surround the closure with parentheses - | -LL | let _ = (async ||{})(); - | + + error: aborting due to 2 previous errors From f4e35c60b04b381395150669f1e8656dccc5f94f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Jan 2024 19:24:03 +0000 Subject: [PATCH 189/297] Fix async closure call suggestion --- compiler/rustc_hir_typeck/src/callee.rs | 82 +++++++++++-------- .../suggest-on-bare-closure-call.stderr | 5 ++ 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1a4e03d50cae..d486f069989e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -293,49 +293,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_node: &hir::ExprKind<'_>, callee_span: Span, ) { + let hir::ExprKind::Block(..) = callee_node else { + // Only calls on blocks suggested here. + return; + }; + let hir = self.tcx.hir(); - let parent_hir_id = hir.parent_id(hir_id); - let parent_node = self.tcx.hir_node(parent_hir_id); - if let ( - hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, kind, .. }), + let fn_decl_span = if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), + .. + }) = hir.get_parent(hir_id) + { + fn_decl_span + } else if let Some(( + _, + hir::Node::Expr(&hir::Expr { + hir_id: parent_hir_id, + kind: + hir::ExprKind::Closure(&hir::Closure { + kind: + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + )), + .. + }), .. }), - hir::ExprKind::Block(..), - ) = (parent_node, callee_node) + )) = hir.parent_iter(hir_id).nth(3) { - let fn_decl_span = if matches!( - kind, - hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure - ),) - ) { - // Actually need to unwrap one more layer of HIR to get to - // the _real_ closure... - let async_closure = hir.parent_id(parent_hir_id); - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), - .. - }) = self.tcx.hir_node(async_closure) - { - fn_decl_span - } else { - return; - } - } else { + // Actually need to unwrap one more layer of HIR to get to + // the _real_ closure... + let async_closure = hir.parent_id(parent_hir_id); + if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), + .. + }) = self.tcx.hir_node(async_closure) + { fn_decl_span - }; + } else { + return; + } + } else { + return; + }; - let start = fn_decl_span.shrink_to_lo(); - let end = callee_span.shrink_to_hi(); - err.multipart_suggestion( - "if you meant to create this closure and immediately call it, surround the \ + let start = fn_decl_span.shrink_to_lo(); + let end = callee_span.shrink_to_hi(); + err.multipart_suggestion( + "if you meant to create this closure and immediately call it, surround the \ closure with parentheses", - vec![(start, "(".to_string()), (end, ")".to_string())], - Applicability::MaybeIncorrect, - ); - } + vec![(start, "(".to_string()), (end, ")".to_string())], + Applicability::MaybeIncorrect, + ); } /// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr index 77631b36e0f3..e65a6eb4939d 100644 --- a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr +++ b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -18,6 +18,11 @@ LL | let _ = async ||{}(); | ^^-- | | | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (async ||{})(); + | + + error: aborting due to 2 previous errors From 04a5ee6f1d6ab1270b95c6c91a718d900a762eb8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Jan 2024 19:38:53 +0000 Subject: [PATCH 190/297] Deal with additional wrapping of async closure body in clippy --- .../clippy_lints/src/async_yields_async.rs | 98 ++++++++++++------- .../src/redundant_closure_call.rs | 20 +++- .../clippy/tests/ui/author/blocks.stdout | 6 +- 3 files changed, 82 insertions(+), 42 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index bb08ac7508bc..eeaa3de3725f 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -45,50 +45,72 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]); impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - // For functions, with explicitly defined types, don't warn. - // XXXkhuey maybe we should? - if let ExprKind::Closure(Closure { - kind: - ClosureKind::Coroutine(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - CoroutineSource::Block | CoroutineSource::Closure, - )), + let ExprKind::Closure(Closure { + kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, kind)), body: body_id, .. }) = expr.kind - { - if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() { - let typeck_results = cx.tcx.typeck_body(*body_id); - let body = cx.tcx.hir().body(*body_id); - let expr_ty = typeck_results.expr_ty(body.value); + else { + return; + }; - if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { - let return_expr_span = match &body.value.kind { - // XXXkhuey there has to be a better way. - ExprKind::Block(block, _) => block.expr.map(|e| e.span), - ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), - _ => None, - }; - if let Some(return_expr_span) = return_expr_span { - span_lint_hir_and_then( - cx, - ASYNC_YIELDS_ASYNC, - body.value.hir_id, + let body_expr = match kind { + CoroutineSource::Fn => { + // For functions, with explicitly defined types, don't warn. + // XXXkhuey maybe we should? + return; + }, + CoroutineSource::Block => cx.tcx.hir().body(*body_id).value, + CoroutineSource::Closure => { + // Like `async fn`, async closures are wrapped in an additional block + // to move all of the closure's arguments into the future. + + let async_closure_body = cx.tcx.hir().body(*body_id).value; + let ExprKind::Block(block, _) = async_closure_body.kind else { + return; + }; + let Some(block_expr) = block.expr else { + return; + }; + let ExprKind::DropTemps(body_expr) = block_expr.kind else { + return; + }; + body_expr + }, + }; + + let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() else { + return; + }; + + let typeck_results = cx.tcx.typeck_body(*body_id); + let expr_ty = typeck_results.expr_ty(body_expr); + + if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { + let return_expr_span = match &body_expr.kind { + // XXXkhuey there has to be a better way. + ExprKind::Block(block, _) => block.expr.map(|e| e.span), + ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), + _ => None, + }; + if let Some(return_expr_span) = return_expr_span { + span_lint_hir_and_then( + cx, + ASYNC_YIELDS_ASYNC, + body_expr.hir_id, + return_expr_span, + "an async construct yields a type which is itself awaitable", + |db| { + db.span_label(body_expr.span, "outer async construct"); + db.span_label(return_expr_span, "awaitable value not awaited"); + db.span_suggestion( return_expr_span, - "an async construct yields a type which is itself awaitable", - |db| { - db.span_label(body.value.span, "outer async construct"); - db.span_label(return_expr_span, "awaitable value not awaited"); - db.span_suggestion( - return_expr_span, - "consider awaiting this value", - format!("{}.await", snippet(cx, return_expr_span, "..")), - Applicability::MaybeIncorrect, - ); - }, + "consider awaiting this value", + format!("{}.await", snippet(cx, return_expr_span, "..")), + Applicability::MaybeIncorrect, ); - } - } + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index cde08dfcc748..334e6770ae40 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -5,7 +5,9 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; -use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; +use rustc_hir::{ + intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -166,10 +168,22 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if coroutine_kind.is_async() && let hir::ExprKind::Closure(closure) = body.kind { - let async_closure_body = cx.tcx.hir().body(closure.body); + // Like `async fn`, async closures are wrapped in an additional block + // to move all of the closure's arguments into the future. + + let async_closure_body = cx.tcx.hir().body(closure.body).value; + let ExprKind::Block(block, _) = async_closure_body.kind else { + return; + }; + let Some(block_expr) = block.expr else { + return; + }; + let ExprKind::DropTemps(body_expr) = block_expr.kind else { + return; + }; // `async x` is a syntax error, so it becomes `async { x }` - if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) { + if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) { hint = hint.blockify(); } diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index 62de661f8ff8..8c4d71e68f80 100644 --- a/src/tools/clippy/tests/ui/author/blocks.stdout +++ b/src/tools/clippy/tests/ui/author/blocks.stdout @@ -48,7 +48,11 @@ if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_ && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind && block.stmts.is_empty() - && block.expr.is_none() + && let Some(trailing_expr) = block.expr + && let ExprKind::DropTemps(expr3) = trailing_expr.kind + && let ExprKind::Block(block1, None) = expr3.kind + && block1.stmts.is_empty() + && block1.expr.is_none() { // report your lint here } From f91ccf9ace393a681922b145e56e7e3fb0041657 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 10 Jan 2024 11:46:17 -0800 Subject: [PATCH 191/297] Remove tcx from SMIR run macro and accept closures Simplify the `run` macro to avoid sometimes unnecessary dependency on `TyCtxt`. Instead, users can use the new internal method `tcx()`. Additionally, extend the macro to accept closures that may capture variables. These are non-backward compatible changes, but they only affect internal APIs which are provided today as helper functions until we have a stable API to start the compiler. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 122 +++++++++++++++--- tests/ui-fulldeps/stable-mir/check_abi.rs | 6 +- .../stable-mir/check_allocation.rs | 6 +- tests/ui-fulldeps/stable-mir/check_defs.rs | 6 +- .../ui-fulldeps/stable-mir/check_instance.rs | 6 +- .../ui-fulldeps/stable-mir/check_item_kind.rs | 6 +- tests/ui-fulldeps/stable-mir/check_ty_fold.rs | 6 +- .../stable-mir/compilation-result.rs | 12 +- tests/ui-fulldeps/stable-mir/crate-info.rs | 6 +- tests/ui-fulldeps/stable-mir/projections.rs | 6 +- tests/ui-fulldeps/stable-mir/smir_internal.rs | 6 +- tests/ui-fulldeps/stable-mir/smir_visitor.rs | 6 +- 12 files changed, 134 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 4bac98909add..7633739f2890 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -24,14 +24,49 @@ use std::ops::Index; mod internal; pub mod pretty; +/// Convert an internal Rust compiler item into its stable counterpart, if one exists. +/// +/// # Warning +/// +/// This function is unstable, and it's behavior may change at any point. +/// E.g.: Items that were previously supported, may no longer be supported, or its translation may +/// change. +/// +/// # Panics +/// +/// This function will panic if StableMIR has not been properly initialized. pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { with_tables(|tables| item.stable(tables)) } +/// Convert a stable item into its internal Rust compiler counterpart, if one exists. +/// +/// # Warning +/// +/// This function is unstable, and it's behavior may change at any point. +/// Not every stable item can be converted to an internal one. +/// Furthermore, items that were previously supported, may no longer be supported in newer versions. +/// +/// # Panics +/// +/// This function will panic if StableMIR has not been properly initialized. pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T { with_tables(|tables| item.internal(tables)) } +/// Retrieve the internal Rust compiler type context. +/// +/// # Warning +/// +/// This function is unstable, and it's behavior may change at any point. +/// +/// # Panics +/// +/// This function will panic if StableMIR has not been properly initialized. +pub fn tcx<'tcx>() -> TyCtxt<'tcx> { + with_tables(|tables| tables.tcx) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -190,35 +225,83 @@ where stable_mir::compiler_interface::run(&tables, || init(&tables, f)) } +/// Instantiate and run the compiler with the provided arguments and callback. +/// +/// The callback will be invoked after the compiler ran all its analysis, but before code generation. +/// Note that this macro accepts two different formats for the callback: +/// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow` +/// ```ignore(needs-extern-crate) +/// # extern crate rustc_driver; +/// # extern crate rustc_interface; +/// # #[macro_use] +/// # extern crate rustc_smir; +/// # extern crate stable_mir; +/// # +/// # fn main() { +/// # use std::ops::ControlFlow; +/// # use stable_mir::CompilerError; +/// fn analyze_code() -> ControlFlow<(), ()> { +/// // Your code goes in here. +/// # ControlFlow::Continue(()) +/// } +/// # let args = vec!["--verbose".to_string()]; +/// let result = run!(args, analyze_code); +/// # assert_eq!(result, Err(CompilerError::Skipped)) +/// # } +/// ``` +/// 2. An expression that represents the body of a closure: +/// ```ignore(needs-extern-crate) +/// # extern crate rustc_driver; +/// # extern crate rustc_interface; +/// # #[macro_use] +/// # extern crate rustc_smir; +/// # extern crate stable_mir; +/// # +/// # fn main() { +/// # use std::ops::ControlFlow; +/// # use stable_mir::CompilerError; +/// fn analyze_code(extra_args: Vec) -> ControlFlow<(), ()> { +/// # let _ = extra_args; +/// // Your code goes in here. +/// # ControlFlow::Continue(()) +/// } +/// # let args = vec!["--verbose".to_string()]; +/// # let extra_args = vec![]; +/// let result = run!(args, analyze_code(extra_args)); +/// # assert_eq!(result, Err(CompilerError::Skipped)) +/// # } +/// ``` #[macro_export] macro_rules! run { - ($args:expr, $callback:expr) => { - run!($args, tcx, $callback) + ($args:expr, $callback_fn:ident) => { + run!($args, $callback_fn()) }; - ($args:expr, $tcx:ident, $callback:expr) => {{ + ($args:expr, $callback:expr) => {{ use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use stable_mir::CompilerError; use std::ops::ControlFlow; - pub struct StableMir + pub struct StableMir ControlFlow> where B: Send, C: Send, + F: FnOnce() -> ControlFlow + Send, { args: Vec, - callback: fn(TyCtxt<'_>) -> ControlFlow, + callback: Option, result: Option>, } - impl StableMir + impl StableMir where B: Send, C: Send, + F: FnOnce() -> ControlFlow + Send, { /// Creates a new `StableMir` instance, with given test_function and arguments. - pub fn new(args: Vec, callback: fn(TyCtxt<'_>) -> ControlFlow) -> Self { - StableMir { args, callback, result: None } + pub fn new(args: Vec, callback: F) -> Self { + StableMir { args, callback: Some(callback), result: None } } /// Runs the compiler against given target and tests it with `test_function` @@ -238,10 +321,11 @@ macro_rules! run { } } - impl Callbacks for StableMir + impl Callbacks for StableMir where B: Send, C: Send, + F: FnOnce() -> ControlFlow + Send, { /// Called after analysis. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) @@ -251,20 +335,24 @@ macro_rules! run { queries: &'tcx Queries<'tcx>, ) -> Compilation { queries.global_ctxt().unwrap().enter(|tcx| { - rustc_internal::run(tcx, || { - self.result = Some((self.callback)(tcx)); - }) - .unwrap(); - if self.result.as_ref().is_some_and(|val| val.is_continue()) { - Compilation::Continue + if let Some(callback) = self.callback.take() { + rustc_internal::run(tcx, || { + self.result = Some((callback)()); + }) + .unwrap(); + if self.result.as_ref().is_some_and(|val| val.is_continue()) { + Compilation::Continue + } else { + Compilation::Stop + } } else { - Compilation::Stop + Compilation::Continue } }) } } - StableMir::new($args, |$tcx| $callback).run() + StableMir::new($args, || $callback).run() }}; } diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 30b42bc3bfaf..7d7469597afc 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -12,14 +12,12 @@ #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::abi::{ArgAbi, CallConvention, FieldsShape, PassMode, VariantsShape}; use stable_mir::mir::mono::Instance; @@ -32,7 +30,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); @@ -117,7 +115,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 93def93127c8..fb5e13eb13b1 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -14,14 +14,12 @@ #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::alloc::GlobalAlloc; @@ -40,7 +38,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap()); @@ -230,7 +228,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index e9a2599d8732..4a124adb2b60 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -20,7 +19,6 @@ extern crate stable_mir; use std::assert_matches::assert_matches; use mir::{mono::Instance, TerminatorKind::*}; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; use stable_mir::*; @@ -30,7 +28,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let entry = stable_mir::entry_fn().unwrap(); let main_fn = Instance::try_from(entry).unwrap(); assert_eq!(main_fn.name(), "main"); @@ -113,7 +111,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 5cb07eabf41d..1e039e5ae514 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -19,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use mir::{mono::Instance, TerminatorKind::*}; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind}; use stable_mir::*; @@ -29,7 +27,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let items = stable_mir::all_local_items(); // Get all items and split generic vs monomorphic items. @@ -96,7 +94,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index 72e0e09e6e36..0a7f00029f2a 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -11,14 +11,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::*; use std::io::Write; @@ -27,7 +25,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_item_kind(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_item_kind() -> ControlFlow<()> { let items = stable_mir::all_local_items(); assert_eq!(items.len(), 4); // Constructor item. @@ -59,7 +57,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_item_kind(tcx)).unwrap(); + run!(args, test_item_kind).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index b90d47d4540b..14cbf9e9f81f 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -12,14 +12,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, }; use stable_mir::mir::{Body, MirVisitor, FieldIdx, Place, ProjectionElem, visit::{Location, @@ -30,7 +28,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn(); let body = main_fn.unwrap().body(); let mut visitor = PlaceVisitor{ body: &body, tested: false}; @@ -87,7 +85,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index fc56e24814b0..c802316c1d86 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -10,14 +10,12 @@ #![feature(rustc_private)] #![feature(assert_matches)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use std::io::Write; @@ -32,7 +30,8 @@ fn main() { test_continue(args.clone()); test_break(args.clone()); test_failed(args.clone()); - test_skipped(args); + test_skipped(args.clone()); + test_captured(args) } fn test_continue(args: Vec) { @@ -59,6 +58,13 @@ fn test_failed(mut args: Vec) { assert_eq!(result, Err(stable_mir::CompilerError::CompilationFailed)); } +/// Test that we are able to pass a closure and set the return according to the captured value. +fn test_captured(args: Vec) { + let captured = "10".to_string(); + let result = run!(args, ControlFlow::Continue::<(), usize>(captured.len())); + assert_eq!(result, Ok(captured.len())); +} + fn generate_input(path: &str) -> std::io::Result<()> { let mut file = std::fs::File::create(path)?; write!( diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index c2035430a33b..8258883436f2 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -12,7 +12,6 @@ #![feature(control_flow_enum)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -20,7 +19,6 @@ extern crate rustc_interface; extern crate stable_mir; use rustc_hir::def::DefKind; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ItemKind; use stable_mir::crate_def::CrateDef; @@ -33,7 +31,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Get the local crate using stable_mir API. let local = stable_mir::local_crate(); assert_eq!(&local.name, CRATE_NAME); @@ -194,7 +192,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index 8c3fda7b6bb1..40f2d901a2b2 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -12,14 +12,12 @@ #![feature(control_flow_enum)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind}; @@ -32,7 +30,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// Tests projections within Place objects -fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_place_projections() -> ControlFlow<()> { let items = stable_mir::all_local_items(); let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body(); assert_eq!(body.blocks.len(), 4); @@ -159,7 +157,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_place_projections(tcx)).unwrap(); + run!(args, test_place_projections).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index b0596b188238..63a6a5e47e8b 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -16,17 +16,15 @@ extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; -extern crate rustc_middle; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use std::io::Write; use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_translation() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn().unwrap(); let body = main_fn.body(); let orig_ty = body.locals()[0].ty; @@ -48,7 +46,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_translation(tcx)).unwrap(); + run!(args, test_translation).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 027b0e7d9e85..d7739770b706 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -19,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use std::collections::HashSet; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::*; use stable_mir::mir::MirVisitor; @@ -28,7 +26,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_visitor(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_visitor() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn(); let main_body = main_fn.unwrap().body(); let main_visitor = TestVisitor::collect(&main_body); @@ -116,7 +114,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_visitor(tcx)).unwrap(); + run!(args, test_visitor).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { From e12101c4db03b1cd35fcc288f8e6568f552ee51c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 16 Jan 2024 21:14:39 +0100 Subject: [PATCH 192/297] Fix `rustc_abi` build on stable --- compiler/rustc_abi/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index ea194e10defd..c45a4a410f96 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -49,7 +49,14 @@ bitflags! { | ReprFlags::IS_LINEAR.bits(); } } -rustc_data_structures::external_bitflags_debug! { ReprFlags } + +// This is the same as `rustc_data_structures::external_bitflags_debug` but without the +// `rustc_data_structures` to make it build on stable. +impl std::fmt::Debug for ReprFlags { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + bitflags::parser::to_writer(self, f) + } +} #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] From ee007ab187dc3eb9587a787d1029c539d54710b0 Mon Sep 17 00:00:00 2001 From: novafacing Date: Tue, 16 Jan 2024 13:27:58 -0800 Subject: [PATCH 193/297] proc_macro_c_str_literals: Implement Literal::c_string constructor --- library/proc_macro/src/lib.rs | 8 ++++++++ .../feature-gate-proc_macro_c_str_literals.rs | 11 +++++++++++ .../feature-gate-proc_macro_c_str_literals.stderr | 13 +++++++++++++ tests/ui/proc-macro/auxiliary/api/mod.rs | 2 ++ tests/ui/proc-macro/auxiliary/api/parse.rs | 7 +++---- tests/ui/proc-macro/test.rs | 1 + 6 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs create mode 100644 tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 6e664a162df9..ca83e2be5c14 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -45,6 +45,7 @@ mod diagnostic; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +use std::ffi::CStr; use std::ops::{Range, RangeBounds}; use std::path::PathBuf; use std::str::FromStr; @@ -1351,6 +1352,13 @@ impl Literal { Literal::new(bridge::LitKind::ByteStr, &string, None) } + /// C string literal. + #[unstable(feature = "proc_macro_c_str_literals", issue = "119750")] + pub fn c_string(string: &CStr) -> Literal { + let string = string.to_bytes().escape_ascii().to_string(); + Literal::new(bridge::LitKind::CStr, &string, None) + } + /// Returns the span encompassing this literal. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn span(&self) -> Span { diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs new file mode 100644 index 000000000000..5554c8139255 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs @@ -0,0 +1,11 @@ +// edition: 2021 +// force-host +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::Literal; + +fn test() { + Literal::c_string(c"a"); //~ ERROR use of unstable library feature 'proc_macro_c_str_literals' +} diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr new file mode 100644 index 000000000000..9bba1d50ce36 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature 'proc_macro_c_str_literals' + --> $DIR/feature-gate-proc_macro_c_str_literals.rs:10:5 + | +LL | Literal::c_string(c"a"); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #119750 for more information + = help: add `#![feature(proc_macro_c_str_literals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs index 3bea5d75779a..5a533b9e17e1 100644 --- a/tests/ui/proc-macro/auxiliary/api/mod.rs +++ b/tests/ui/proc-macro/auxiliary/api/mod.rs @@ -1,10 +1,12 @@ // force-host // no-prefer-dynamic +// edition: 2021 #![crate_type = "proc-macro"] #![crate_name = "proc_macro_api_tests"] #![feature(proc_macro_span)] #![feature(proc_macro_byte_character)] +#![feature(proc_macro_c_str_literals)] #![deny(dead_code)] // catch if a test function is never called extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs index 07c9f464961a..801c616c8040 100644 --- a/tests/ui/proc-macro/auxiliary/api/parse.rs +++ b/tests/ui/proc-macro/auxiliary/api/parse.rs @@ -19,10 +19,8 @@ fn test_display_literal() { "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", ); - assert_eq!( - Literal::string("a \t ❤ ' \" \u{1}").to_string(), - "\"a \\t ❤ ' \\\" \\u{1}\"", - ); + assert_eq!(Literal::string("a \t ❤ ' \" \u{1}").to_string(), "\"a \\t ❤ ' \\\" \\u{1}\"",); + assert_eq!(Literal::c_string(c"\'\"\x7f\u{7fff}").to_string(), r#"c"\'\"\x7f\xe7\xbf\xbf""#); assert_eq!(Literal::character('a').to_string(), "'a'"); assert_eq!(Literal::character('\t').to_string(), "'\\t'"); assert_eq!(Literal::character('❤').to_string(), "'❤'"); @@ -41,6 +39,7 @@ fn test_parse_literal() { assert_eq!("b'a'".parse::().unwrap().to_string(), "b'a'"); assert_eq!("\"\n\"".parse::().unwrap().to_string(), "\"\n\""); assert_eq!("b\"\"".parse::().unwrap().to_string(), "b\"\""); + assert_eq!("c\"\"".parse::().unwrap().to_string(), "c\"\""); assert_eq!("r##\"\"##".parse::().unwrap().to_string(), "r##\"\"##"); assert_eq!("10ulong".parse::().unwrap().to_string(), "10ulong"); assert_eq!("-10ulong".parse::().unwrap().to_string(), "-10ulong"); diff --git a/tests/ui/proc-macro/test.rs b/tests/ui/proc-macro/test.rs index c96aa73175f2..2ec620720202 100644 --- a/tests/ui/proc-macro/test.rs +++ b/tests/ui/proc-macro/test.rs @@ -1,5 +1,6 @@ // check-pass // aux-build:api/mod.rs +// edition: 2021 //! This is for everything that *would* be a #[test] inside of libproc_macro, //! except for the fact that proc_macro objects are not capable of existing From 666030c51b87509a065867f99bf7317a5486470a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 20 Mar 2023 21:37:36 +0000 Subject: [PATCH 194/297] Simplify binary ops. --- compiler/rustc_mir_transform/src/gvn.rs | 111 ++++- .../mir-opt/const_prop/boolean_identities.rs | 7 +- .../boolean_identities.test.GVN.diff | 12 +- .../boxes.main.GVN.panic-abort.diff | 9 +- .../boxes.main.GVN.panic-unwind.diff | 9 +- tests/mir-opt/const_prop/boxes.rs | 2 +- tests/mir-opt/const_prop/mult_by_zero.rs | 3 +- .../const_prop/mult_by_zero.test.GVN.diff | 2 +- .../gvn.arithmetic.GVN.panic-abort.diff | 385 +++++++++++------- .../gvn.arithmetic.GVN.panic-unwind.diff | 385 +++++++++++------- ...vn.arithmetic_checked.GVN.panic-abort.diff | 101 +++-- ...n.arithmetic_checked.GVN.panic-unwind.diff | 101 +++-- .../gvn.comparison.GVN.panic-abort.diff | 10 +- .../gvn.comparison.GVN.panic-unwind.diff | 10 +- .../gvn.fn_pointers.GVN.panic-abort.diff | 18 +- .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 +- tests/mir-opt/gvn.rs | 78 ++-- .../issue_101973.inner.GVN.panic-abort.diff | 17 +- .../issue_101973.inner.GVN.panic-unwind.diff | 17 +- 19 files changed, 836 insertions(+), 459 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index dc3af038d807..3052369c3ca4 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -345,11 +345,20 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(self.insert(Value::Constant { value, disambiguator })) } + fn insert_bool(&mut self, flag: bool) -> VnIndex { + // Booleans are deterministic. + self.insert(Value::Constant { value: Const::from_bool(self.tcx, flag), disambiguator: 0 }) + } + fn insert_scalar(&mut self, scalar: Scalar, ty: Ty<'tcx>) -> VnIndex { self.insert_constant(Const::from_scalar(self.tcx, scalar, ty)) .expect("scalars are deterministic") } + fn insert_tuple(&mut self, values: Vec) -> VnIndex { + self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::from_u32(0), values)) + } + #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option> { use Value::*; @@ -785,14 +794,26 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Value::Cast { kind, value, from, to } } Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let ty = lhs.ty(self.local_decls, self.tcx); let lhs = self.simplify_operand(lhs, location); let rhs = self.simplify_operand(rhs, location); - Value::BinaryOp(op, lhs?, rhs?) + let lhs = lhs?; + let rhs = rhs?; + if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) { + return Some(value); + } + Value::BinaryOp(op, lhs, rhs) } Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let ty = lhs.ty(self.local_decls, self.tcx); let lhs = self.simplify_operand(lhs, location); let rhs = self.simplify_operand(rhs, location); - Value::CheckedBinaryOp(op, lhs?, rhs?) + let lhs = lhs?; + let rhs = rhs?; + if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) { + return Some(value); + } + Value::CheckedBinaryOp(op, lhs, rhs) } Rvalue::UnaryOp(op, ref mut arg) => { let arg = self.simplify_operand(arg, location)?; @@ -894,6 +915,92 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(self.insert(Value::Aggregate(ty, variant_index, fields))) } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_binary( + &mut self, + op: BinOp, + checked: bool, + lhs_ty: Ty<'tcx>, + lhs: VnIndex, + rhs: VnIndex, + ) -> Option { + // Floats are weird enough that none of the logic below applies. + let reasonable_ty = + lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char() || lhs_ty.is_any_ptr(); + if !reasonable_ty { + return None; + } + + let layout = self.ecx.layout_of(lhs_ty).ok()?; + + let as_bits = |value| { + let constant = self.evaluated[value].as_ref()?; + let scalar = self.ecx.read_scalar(constant).ok()?; + scalar.to_bits(constant.layout.size).ok() + }; + + // Represent the values as `Ok(bits)` or `Err(VnIndex)`. + let a = as_bits(lhs).ok_or(lhs); + let b = as_bits(rhs).ok_or(rhs); + let result = match (op, a, b) { + // Neutral elements. + (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Ok(0), Err(p)) + | ( + BinOp::Add + | BinOp::BitOr + | BinOp::BitXor + | BinOp::Sub + | BinOp::Offset + | BinOp::Shl + | BinOp::Shr, + Err(p), + Ok(0), + ) + | (BinOp::Mul, Ok(1), Err(p)) + | (BinOp::Mul | BinOp::Div, Err(p), Ok(1)) => p, + // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size. + (BinOp::BitAnd, Err(p), Ok(ones)) | (BinOp::BitAnd, Ok(ones), Err(p)) + if ones == layout.size.truncate(u128::MAX) + || (layout.ty.is_bool() && ones == 1) => + { + p + } + // Absorbing elements. + (BinOp::Mul | BinOp::BitAnd, _, Ok(0)) + | (BinOp::Rem, _, Ok(1)) + | ( + BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr, + Ok(0), + _, + ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty), + // Attempt to simplify `x | ALL_ONES` to `ALL_ONES`. + (BinOp::BitOr, _, Ok(ones)) | (BinOp::BitOr, Ok(ones), _) + if ones == layout.size.truncate(u128::MAX) + || (layout.ty.is_bool() && ones == 1) => + { + self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty) + } + // Sub/Xor with itself. + (BinOp::Sub | BinOp::BitXor, a, b) if a == b => { + self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty) + } + // Comparison: + // - if both operands can be computed as bits, just compare the bits; + // - if we proved that both operands have the same value, we can insert true/false; + // - otherwise, do nothing, as we do not try to prove inequality. + (BinOp::Eq, a, b) if (a.is_ok() && b.is_ok()) || a == b => self.insert_bool(a == b), + (BinOp::Ne, a, b) if (a.is_ok() && b.is_ok()) || a == b => self.insert_bool(a != b), + _ => return None, + }; + + if checked { + let false_val = self.insert_bool(false); + Some(self.insert_tuple(vec![result, false_val])) + } else { + Some(result) + } + } } fn op_to_prop_const<'tcx>( diff --git a/tests/mir-opt/const_prop/boolean_identities.rs b/tests/mir-opt/const_prop/boolean_identities.rs index f6575ac8e547..3b7ea25ad46e 100644 --- a/tests/mir-opt/const_prop/boolean_identities.rs +++ b/tests/mir-opt/const_prop/boolean_identities.rs @@ -5,10 +5,9 @@ pub fn test(x: bool, y: bool) -> bool { // CHECK-LABEL: fn test( // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; - // FIXME(cjgillot) simplify algebraic identity - // CHECK-NOT: [[a]] = const true; - // CHECK-NOT: [[b]] = const false; - // CHECK-NOT: _0 = const false; + // CHECK: [[a]] = const true; + // CHECK: [[b]] = const false; + // CHECK: _0 = const false; let a = (y | true); let b = (x & false); a & b diff --git a/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff index eca87af75272..0bd8413289e6 100644 --- a/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff +++ b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff @@ -24,21 +24,23 @@ StorageLive(_4); _4 = _2; - _3 = BitOr(move _4, const true); -+ _3 = BitOr(_2, const true); ++ _3 = const true; StorageDead(_4); - StorageLive(_5); + nop; StorageLive(_6); _6 = _1; - _5 = BitAnd(move _6, const false); -+ _5 = BitAnd(_1, const false); ++ _5 = const false; StorageDead(_6); StorageLive(_7); - _7 = _3; +- _7 = _3; ++ _7 = const true; StorageLive(_8); - _8 = _5; +- _8 = _5; - _0 = BitAnd(move _7, move _8); -+ _0 = BitAnd(_3, _5); ++ _8 = const false; ++ _0 = const false; StorageDead(_8); StorageDead(_7); - StorageDead(_5); diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff index b3fdaa5ee825..59ee38f5a2b9 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff @@ -20,7 +20,8 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - _4 = SizeOf(i32); - _5 = AlignOf(i32); @@ -39,8 +40,10 @@ StorageDead(_7); _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); _2 = (*_9); - _1 = Add(move _2, const 0_i32); - StorageDead(_2); +- _1 = Add(move _2, const 0_i32); +- StorageDead(_2); ++ _1 = _2; ++ nop; drop(_3) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff index d0350c97253a..9d87bd809d1f 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff @@ -20,7 +20,8 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - _4 = SizeOf(i32); - _5 = AlignOf(i32); @@ -39,8 +40,10 @@ StorageDead(_7); _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); _2 = (*_9); - _1 = Add(move _2, const 0_i32); - StorageDead(_2); +- _1 = Add(move _2, const 0_i32); +- StorageDead(_2); ++ _1 = _2; ++ nop; drop(_3) -> [return: bb2, unwind: bb3]; } diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs index 5227d7b8b8ba..d2d61f86d5eb 100644 --- a/tests/mir-opt/const_prop/boxes.rs +++ b/tests/mir-opt/const_prop/boxes.rs @@ -12,7 +12,7 @@ fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: (*{{_.*}}) = const 42_i32; // CHECK: [[tmp:_.*]] = (*{{_.*}}); - // CHECK: [[x]] = Add(move [[tmp]], const 0_i32); + // CHECK: [[x]] = [[tmp]]; let x = *(#[rustc_box] Box::new(42)) + 0; diff --git a/tests/mir-opt/const_prop/mult_by_zero.rs b/tests/mir-opt/const_prop/mult_by_zero.rs index 2fdb75c3100e..b8afaeef43fd 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.rs +++ b/tests/mir-opt/const_prop/mult_by_zero.rs @@ -3,8 +3,7 @@ // EMIT_MIR mult_by_zero.test.GVN.diff fn test(x: i32) -> i32 { // CHECK: fn test( - // FIXME(cjgillot) simplify algebraic identity - // CHECK-NOT: _0 = const 0_i32; + // CHECK: _0 = const 0_i32; x * 0 } diff --git a/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff index e9fb34749c10..6c2aab45d48b 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff +++ b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff @@ -10,7 +10,7 @@ StorageLive(_2); _2 = _1; - _0 = Mul(move _2, const 0_i32); -+ _0 = Mul(_1, const 0_i32); ++ _0 = const 0_i32; StorageDead(_2); return; } diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff index d524ad242fec..84eb6c5cfe8d 100644 --- a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff @@ -13,13 +13,13 @@ let _8: (); let mut _9: u64; let mut _10: u64; - let _11: (); - let mut _12: u64; + let mut _11: u64; + let _12: (); let mut _13: u64; - let _14: (); - let mut _15: u64; + let mut _14: u64; + let _15: (); let mut _16: u64; - let mut _17: bool; + let mut _17: u64; let _18: (); let mut _19: u64; let mut _20: u64; @@ -51,18 +51,32 @@ let _46: (); let mut _47: u64; let mut _48: u64; - let _49: (); - let mut _50: u64; + let mut _49: bool; + let _50: (); let mut _51: u64; - let _52: (); - let mut _53: u64; + let mut _52: u64; + let _53: (); let mut _54: u64; - let _55: (); - let mut _56: u64; + let mut _55: u64; + let _56: (); let mut _57: u64; - let _58: (); - let mut _59: u64; + let mut _58: u64; + let _59: (); let mut _60: u64; + let mut _61: u64; + let _62: (); + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let _69: (); + let mut _70: u64; + let mut _71: u64; + let _72: (); + let mut _73: u64; + let mut _74: u64; bb0: { StorageLive(_2); @@ -70,9 +84,10 @@ StorageLive(_4); _4 = _1; - _3 = Add(move _4, const 0_u64); -+ _3 = Add(_1, const 0_u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; +- _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::(_1) -> [return: bb1, unwind unreachable]; } bb1: { @@ -83,98 +98,101 @@ StorageLive(_7); _7 = _1; - _6 = Sub(move _7, const 0_u64); -+ _6 = Sub(_1, const 0_u64); ++ _6 = _1; StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; +- _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; ++ _5 = opaque::(_1) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_6); StorageDead(_5); StorageLive(_8); - StorageLive(_9); +- StorageLive(_9); ++ nop; StorageLive(_10); _10 = _1; -- _9 = Mul(move _10, const 0_u64); -+ _9 = Mul(_1, const 0_u64); + StorageLive(_11); + _11 = _1; +- _9 = Sub(move _10, move _11); ++ _9 = const 0_u64; + StorageDead(_11); StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; +- _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; ++ _8 = opaque::(const 0_u64) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_9); +- StorageDead(_9); ++ nop; StorageDead(_8); - StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; -- _12 = Mul(move _13, const 1_u64); -+ _12 = Mul(_1, const 1_u64); - StorageDead(_13); - _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; + StorageLive(_14); + _14 = _1; +- _13 = Mul(move _14, const 0_u64); ++ _13 = const 0_u64; + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb4, unwind unreachable]; ++ _12 = opaque::(const 0_u64) -> [return: bb4, unwind unreachable]; } bb4: { + StorageDead(_13); StorageDead(_12); - StorageDead(_11); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = Eq(const 0_u64, const 0_u64); -- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind unreachable]; -+ _17 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind unreachable]; + StorageLive(_17); + _17 = _1; +- _16 = Mul(move _17, const 1_u64); ++ _16 = _1; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb5, unwind unreachable]; ++ _15 = opaque::(_1) -> [return: bb5, unwind unreachable]; } bb5: { -- _15 = Div(move _16, const 0_u64); -+ _15 = Div(_1, const 0_u64); StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb6, unwind unreachable]; - } - - bb6: { StorageDead(_15); - StorageDead(_14); StorageLive(_18); StorageLive(_19); StorageLive(_20); _20 = _1; -- _21 = Eq(const 1_u64, const 0_u64); -- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind unreachable]; -+ _21 = const false; -+ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind unreachable]; +- _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb6, unwind unreachable]; ++ _21 = const true; ++ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb6, unwind unreachable]; + } + + bb6: { +- _19 = Div(move _20, const 0_u64); ++ _19 = Div(_1, const 0_u64); + StorageDead(_20); + _18 = opaque::(move _19) -> [return: bb7, unwind unreachable]; } bb7: { -- _19 = Div(move _20, const 1_u64); -+ _19 = Div(_1, const 1_u64); - StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb8, unwind unreachable]; - } - - bb8: { StorageDead(_19); StorageDead(_18); StorageLive(_22); StorageLive(_23); StorageLive(_24); _24 = _1; -- _25 = Eq(_24, const 0_u64); -- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; -+ _25 = Eq(_1, const 0_u64); -+ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; +- _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb8, unwind unreachable]; ++ _25 = const false; ++ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb8, unwind unreachable]; + } + + bb8: { +- _23 = Div(move _24, const 1_u64); ++ _23 = _1; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb9, unwind unreachable]; ++ _22 = opaque::(_1) -> [return: bb9, unwind unreachable]; } bb9: { -- _23 = Div(const 0_u64, move _24); -+ _23 = Div(const 0_u64, _1); - StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb10, unwind unreachable]; - } - - bb10: { StorageDead(_23); StorageDead(_22); StorageLive(_26); @@ -182,79 +200,81 @@ StorageLive(_28); _28 = _1; - _29 = Eq(_28, const 0_u64); -- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; -+ _29 = _25; -+ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; + } + + bb10: { +- _27 = Div(const 0_u64, move _28); ++ _27 = const 0_u64; + StorageDead(_28); +- _26 = opaque::(move _27) -> [return: bb11, unwind unreachable]; ++ _26 = opaque::(const 0_u64) -> [return: bb11, unwind unreachable]; } bb11: { -- _27 = Div(const 1_u64, move _28); -+ _27 = Div(const 1_u64, _1); - StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb12, unwind unreachable]; - } - - bb12: { StorageDead(_27); StorageDead(_26); StorageLive(_30); StorageLive(_31); StorageLive(_32); _32 = _1; -- _33 = Eq(const 0_u64, const 0_u64); -- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind unreachable]; -+ _33 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind unreachable]; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; ++ _33 = _29; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; + } + + bb12: { +- _31 = Div(const 1_u64, move _32); ++ _31 = Div(const 1_u64, _1); + StorageDead(_32); + _30 = opaque::(move _31) -> [return: bb13, unwind unreachable]; } bb13: { -- _31 = Rem(move _32, const 0_u64); -+ _31 = Rem(_1, const 0_u64); - StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb14, unwind unreachable]; - } - - bb14: { StorageDead(_31); StorageDead(_30); StorageLive(_34); StorageLive(_35); StorageLive(_36); _36 = _1; -- _37 = Eq(const 1_u64, const 0_u64); -- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind unreachable]; -+ _37 = const false; -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind unreachable]; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb14, unwind unreachable]; ++ _37 = const true; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb14, unwind unreachable]; + } + + bb14: { +- _35 = Rem(move _36, const 0_u64); ++ _35 = Rem(_1, const 0_u64); + StorageDead(_36); + _34 = opaque::(move _35) -> [return: bb15, unwind unreachable]; } bb15: { -- _35 = Rem(move _36, const 1_u64); -+ _35 = Rem(_1, const 1_u64); - StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb16, unwind unreachable]; - } - - bb16: { StorageDead(_35); StorageDead(_34); StorageLive(_38); StorageLive(_39); StorageLive(_40); _40 = _1; -- _41 = Eq(_40, const 0_u64); -- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; -+ _41 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb16, unwind unreachable]; ++ _41 = const false; ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb16, unwind unreachable]; + } + + bb16: { +- _39 = Rem(move _40, const 1_u64); ++ _39 = const 0_u64; + StorageDead(_40); +- _38 = opaque::(move _39) -> [return: bb17, unwind unreachable]; ++ _38 = opaque::(const 0_u64) -> [return: bb17, unwind unreachable]; } bb17: { -- _39 = Rem(const 0_u64, move _40); -+ _39 = Rem(const 0_u64, _1); - StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb18, unwind unreachable]; - } - - bb18: { StorageDead(_39); StorageDead(_38); StorageLive(_42); @@ -262,27 +282,35 @@ StorageLive(_44); _44 = _1; - _45 = Eq(_44, const 0_u64); -- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; -+ _45 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; ++ _45 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; + } + + bb18: { +- _43 = Rem(const 0_u64, move _44); ++ _43 = const 0_u64; + StorageDead(_44); +- _42 = opaque::(move _43) -> [return: bb19, unwind unreachable]; ++ _42 = opaque::(const 0_u64) -> [return: bb19, unwind unreachable]; } bb19: { -- _43 = Rem(const 1_u64, move _44); -+ _43 = Rem(const 1_u64, _1); - StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb20, unwind unreachable]; - } - - bb20: { StorageDead(_43); StorageDead(_42); StorageLive(_46); StorageLive(_47); StorageLive(_48); _48 = _1; -- _47 = BitAnd(move _48, const 0_u64); -+ _47 = BitAnd(_1, const 0_u64); +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; ++ _49 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; + } + + bb20: { +- _47 = Rem(const 1_u64, move _48); ++ _47 = Rem(const 1_u64, _1); StorageDead(_48); _46 = opaque::(move _47) -> [return: bb21, unwind unreachable]; } @@ -290,58 +318,121 @@ bb21: { StorageDead(_47); StorageDead(_46); - StorageLive(_49); StorageLive(_50); StorageLive(_51); - _51 = _1; -- _50 = BitOr(move _51, const 0_u64); -+ _50 = BitOr(_1, const 0_u64); - StorageDead(_51); - _49 = opaque::(move _50) -> [return: bb22, unwind unreachable]; + StorageLive(_52); + _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); ++ _51 = const 0_u64; + StorageDead(_52); +- _50 = opaque::(move _51) -> [return: bb22, unwind unreachable]; ++ _50 = opaque::(const 0_u64) -> [return: bb22, unwind unreachable]; } bb22: { + StorageDead(_51); StorageDead(_50); - StorageDead(_49); - StorageLive(_52); StorageLive(_53); StorageLive(_54); - _54 = _1; -- _53 = BitXor(move _54, const 0_u64); -+ _53 = BitXor(_1, const 0_u64); - StorageDead(_54); - _52 = opaque::(move _53) -> [return: bb23, unwind unreachable]; + StorageLive(_55); + _55 = _1; +- _54 = BitAnd(move _55, const _); ++ _54 = _1; + StorageDead(_55); +- _53 = opaque::(move _54) -> [return: bb23, unwind unreachable]; ++ _53 = opaque::(_1) -> [return: bb23, unwind unreachable]; } bb23: { + StorageDead(_54); StorageDead(_53); - StorageDead(_52); - StorageLive(_55); StorageLive(_56); StorageLive(_57); - _57 = _1; -- _56 = Shr(move _57, const 0_i32); -+ _56 = Shr(_1, const 0_i32); - StorageDead(_57); - _55 = opaque::(move _56) -> [return: bb24, unwind unreachable]; + StorageLive(_58); + _58 = _1; +- _57 = BitOr(move _58, const 0_u64); ++ _57 = _1; + StorageDead(_58); +- _56 = opaque::(move _57) -> [return: bb24, unwind unreachable]; ++ _56 = opaque::(_1) -> [return: bb24, unwind unreachable]; } bb24: { + StorageDead(_57); StorageDead(_56); - StorageDead(_55); - StorageLive(_58); StorageLive(_59); StorageLive(_60); - _60 = _1; -- _59 = Shl(move _60, const 0_i32); -+ _59 = Shl(_1, const 0_i32); - StorageDead(_60); - _58 = opaque::(move _59) -> [return: bb25, unwind unreachable]; + StorageLive(_61); + _61 = _1; +- _60 = BitOr(move _61, const _); ++ _60 = const u64::MAX; + StorageDead(_61); +- _59 = opaque::(move _60) -> [return: bb25, unwind unreachable]; ++ _59 = opaque::(const u64::MAX) -> [return: bb25, unwind unreachable]; } bb25: { + StorageDead(_60); StorageDead(_59); - StorageDead(_58); + StorageLive(_62); + StorageLive(_63); + StorageLive(_64); + _64 = _1; +- _63 = BitXor(move _64, const 0_u64); ++ _63 = _1; + StorageDead(_64); +- _62 = opaque::(move _63) -> [return: bb26, unwind unreachable]; ++ _62 = opaque::(_1) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); + StorageLive(_67); + _67 = _1; + StorageLive(_68); + _68 = _1; +- _66 = BitXor(move _67, move _68); ++ _66 = const 0_u64; + StorageDead(_68); + StorageDead(_67); +- _65 = opaque::(move _66) -> [return: bb27, unwind unreachable]; ++ _65 = opaque::(const 0_u64) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_69); + StorageLive(_70); + StorageLive(_71); + _71 = _1; +- _70 = Shr(move _71, const 0_i32); ++ _70 = _1; + StorageDead(_71); +- _69 = opaque::(move _70) -> [return: bb28, unwind unreachable]; ++ _69 = opaque::(_1) -> [return: bb28, unwind unreachable]; + } + + bb28: { + StorageDead(_70); + StorageDead(_69); + StorageLive(_72); + StorageLive(_73); + StorageLive(_74); + _74 = _1; +- _73 = Shl(move _74, const 0_i32); ++ _73 = _1; + StorageDead(_74); +- _72 = opaque::(move _73) -> [return: bb29, unwind unreachable]; ++ _72 = opaque::(_1) -> [return: bb29, unwind unreachable]; + } + + bb29: { + StorageDead(_73); + StorageDead(_72); _0 = const (); return; } diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff index 9d69353934c7..98e92d2a3104 100644 --- a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff @@ -13,13 +13,13 @@ let _8: (); let mut _9: u64; let mut _10: u64; - let _11: (); - let mut _12: u64; + let mut _11: u64; + let _12: (); let mut _13: u64; - let _14: (); - let mut _15: u64; + let mut _14: u64; + let _15: (); let mut _16: u64; - let mut _17: bool; + let mut _17: u64; let _18: (); let mut _19: u64; let mut _20: u64; @@ -51,18 +51,32 @@ let _46: (); let mut _47: u64; let mut _48: u64; - let _49: (); - let mut _50: u64; + let mut _49: bool; + let _50: (); let mut _51: u64; - let _52: (); - let mut _53: u64; + let mut _52: u64; + let _53: (); let mut _54: u64; - let _55: (); - let mut _56: u64; + let mut _55: u64; + let _56: (); let mut _57: u64; - let _58: (); - let mut _59: u64; + let mut _58: u64; + let _59: (); let mut _60: u64; + let mut _61: u64; + let _62: (); + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let _69: (); + let mut _70: u64; + let mut _71: u64; + let _72: (); + let mut _73: u64; + let mut _74: u64; bb0: { StorageLive(_2); @@ -70,9 +84,10 @@ StorageLive(_4); _4 = _1; - _3 = Add(move _4, const 0_u64); -+ _3 = Add(_1, const 0_u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind continue]; +- _2 = opaque::(move _3) -> [return: bb1, unwind continue]; ++ _2 = opaque::(_1) -> [return: bb1, unwind continue]; } bb1: { @@ -83,98 +98,101 @@ StorageLive(_7); _7 = _1; - _6 = Sub(move _7, const 0_u64); -+ _6 = Sub(_1, const 0_u64); ++ _6 = _1; StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb2, unwind continue]; +- _5 = opaque::(move _6) -> [return: bb2, unwind continue]; ++ _5 = opaque::(_1) -> [return: bb2, unwind continue]; } bb2: { StorageDead(_6); StorageDead(_5); StorageLive(_8); - StorageLive(_9); +- StorageLive(_9); ++ nop; StorageLive(_10); _10 = _1; -- _9 = Mul(move _10, const 0_u64); -+ _9 = Mul(_1, const 0_u64); + StorageLive(_11); + _11 = _1; +- _9 = Sub(move _10, move _11); ++ _9 = const 0_u64; + StorageDead(_11); StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb3, unwind continue]; +- _8 = opaque::(move _9) -> [return: bb3, unwind continue]; ++ _8 = opaque::(const 0_u64) -> [return: bb3, unwind continue]; } bb3: { - StorageDead(_9); +- StorageDead(_9); ++ nop; StorageDead(_8); - StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; -- _12 = Mul(move _13, const 1_u64); -+ _12 = Mul(_1, const 1_u64); - StorageDead(_13); - _11 = opaque::(move _12) -> [return: bb4, unwind continue]; + StorageLive(_14); + _14 = _1; +- _13 = Mul(move _14, const 0_u64); ++ _13 = const 0_u64; + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb4, unwind continue]; ++ _12 = opaque::(const 0_u64) -> [return: bb4, unwind continue]; } bb4: { + StorageDead(_13); StorageDead(_12); - StorageDead(_11); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = Eq(const 0_u64, const 0_u64); -- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind continue]; -+ _17 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind continue]; + StorageLive(_17); + _17 = _1; +- _16 = Mul(move _17, const 1_u64); ++ _16 = _1; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb5, unwind continue]; ++ _15 = opaque::(_1) -> [return: bb5, unwind continue]; } bb5: { -- _15 = Div(move _16, const 0_u64); -+ _15 = Div(_1, const 0_u64); StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb6, unwind continue]; - } - - bb6: { StorageDead(_15); - StorageDead(_14); StorageLive(_18); StorageLive(_19); StorageLive(_20); _20 = _1; -- _21 = Eq(const 1_u64, const 0_u64); -- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind continue]; -+ _21 = const false; -+ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind continue]; +- _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb6, unwind continue]; ++ _21 = const true; ++ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb6, unwind continue]; + } + + bb6: { +- _19 = Div(move _20, const 0_u64); ++ _19 = Div(_1, const 0_u64); + StorageDead(_20); + _18 = opaque::(move _19) -> [return: bb7, unwind continue]; } bb7: { -- _19 = Div(move _20, const 1_u64); -+ _19 = Div(_1, const 1_u64); - StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb8, unwind continue]; - } - - bb8: { StorageDead(_19); StorageDead(_18); StorageLive(_22); StorageLive(_23); StorageLive(_24); _24 = _1; -- _25 = Eq(_24, const 0_u64); -- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; -+ _25 = Eq(_1, const 0_u64); -+ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; +- _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb8, unwind continue]; ++ _25 = const false; ++ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb8, unwind continue]; + } + + bb8: { +- _23 = Div(move _24, const 1_u64); ++ _23 = _1; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb9, unwind continue]; ++ _22 = opaque::(_1) -> [return: bb9, unwind continue]; } bb9: { -- _23 = Div(const 0_u64, move _24); -+ _23 = Div(const 0_u64, _1); - StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb10, unwind continue]; - } - - bb10: { StorageDead(_23); StorageDead(_22); StorageLive(_26); @@ -182,79 +200,81 @@ StorageLive(_28); _28 = _1; - _29 = Eq(_28, const 0_u64); -- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; -+ _29 = _25; -+ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; + } + + bb10: { +- _27 = Div(const 0_u64, move _28); ++ _27 = const 0_u64; + StorageDead(_28); +- _26 = opaque::(move _27) -> [return: bb11, unwind continue]; ++ _26 = opaque::(const 0_u64) -> [return: bb11, unwind continue]; } bb11: { -- _27 = Div(const 1_u64, move _28); -+ _27 = Div(const 1_u64, _1); - StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb12, unwind continue]; - } - - bb12: { StorageDead(_27); StorageDead(_26); StorageLive(_30); StorageLive(_31); StorageLive(_32); _32 = _1; -- _33 = Eq(const 0_u64, const 0_u64); -- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind continue]; -+ _33 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind continue]; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; ++ _33 = _29; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; + } + + bb12: { +- _31 = Div(const 1_u64, move _32); ++ _31 = Div(const 1_u64, _1); + StorageDead(_32); + _30 = opaque::(move _31) -> [return: bb13, unwind continue]; } bb13: { -- _31 = Rem(move _32, const 0_u64); -+ _31 = Rem(_1, const 0_u64); - StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb14, unwind continue]; - } - - bb14: { StorageDead(_31); StorageDead(_30); StorageLive(_34); StorageLive(_35); StorageLive(_36); _36 = _1; -- _37 = Eq(const 1_u64, const 0_u64); -- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind continue]; -+ _37 = const false; -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind continue]; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb14, unwind continue]; ++ _37 = const true; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb14, unwind continue]; + } + + bb14: { +- _35 = Rem(move _36, const 0_u64); ++ _35 = Rem(_1, const 0_u64); + StorageDead(_36); + _34 = opaque::(move _35) -> [return: bb15, unwind continue]; } bb15: { -- _35 = Rem(move _36, const 1_u64); -+ _35 = Rem(_1, const 1_u64); - StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb16, unwind continue]; - } - - bb16: { StorageDead(_35); StorageDead(_34); StorageLive(_38); StorageLive(_39); StorageLive(_40); _40 = _1; -- _41 = Eq(_40, const 0_u64); -- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; -+ _41 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb16, unwind continue]; ++ _41 = const false; ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb16, unwind continue]; + } + + bb16: { +- _39 = Rem(move _40, const 1_u64); ++ _39 = const 0_u64; + StorageDead(_40); +- _38 = opaque::(move _39) -> [return: bb17, unwind continue]; ++ _38 = opaque::(const 0_u64) -> [return: bb17, unwind continue]; } bb17: { -- _39 = Rem(const 0_u64, move _40); -+ _39 = Rem(const 0_u64, _1); - StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb18, unwind continue]; - } - - bb18: { StorageDead(_39); StorageDead(_38); StorageLive(_42); @@ -262,27 +282,35 @@ StorageLive(_44); _44 = _1; - _45 = Eq(_44, const 0_u64); -- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; -+ _45 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; ++ _45 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; + } + + bb18: { +- _43 = Rem(const 0_u64, move _44); ++ _43 = const 0_u64; + StorageDead(_44); +- _42 = opaque::(move _43) -> [return: bb19, unwind continue]; ++ _42 = opaque::(const 0_u64) -> [return: bb19, unwind continue]; } bb19: { -- _43 = Rem(const 1_u64, move _44); -+ _43 = Rem(const 1_u64, _1); - StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb20, unwind continue]; - } - - bb20: { StorageDead(_43); StorageDead(_42); StorageLive(_46); StorageLive(_47); StorageLive(_48); _48 = _1; -- _47 = BitAnd(move _48, const 0_u64); -+ _47 = BitAnd(_1, const 0_u64); +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; ++ _49 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; + } + + bb20: { +- _47 = Rem(const 1_u64, move _48); ++ _47 = Rem(const 1_u64, _1); StorageDead(_48); _46 = opaque::(move _47) -> [return: bb21, unwind continue]; } @@ -290,58 +318,121 @@ bb21: { StorageDead(_47); StorageDead(_46); - StorageLive(_49); StorageLive(_50); StorageLive(_51); - _51 = _1; -- _50 = BitOr(move _51, const 0_u64); -+ _50 = BitOr(_1, const 0_u64); - StorageDead(_51); - _49 = opaque::(move _50) -> [return: bb22, unwind continue]; + StorageLive(_52); + _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); ++ _51 = const 0_u64; + StorageDead(_52); +- _50 = opaque::(move _51) -> [return: bb22, unwind continue]; ++ _50 = opaque::(const 0_u64) -> [return: bb22, unwind continue]; } bb22: { + StorageDead(_51); StorageDead(_50); - StorageDead(_49); - StorageLive(_52); StorageLive(_53); StorageLive(_54); - _54 = _1; -- _53 = BitXor(move _54, const 0_u64); -+ _53 = BitXor(_1, const 0_u64); - StorageDead(_54); - _52 = opaque::(move _53) -> [return: bb23, unwind continue]; + StorageLive(_55); + _55 = _1; +- _54 = BitAnd(move _55, const _); ++ _54 = _1; + StorageDead(_55); +- _53 = opaque::(move _54) -> [return: bb23, unwind continue]; ++ _53 = opaque::(_1) -> [return: bb23, unwind continue]; } bb23: { + StorageDead(_54); StorageDead(_53); - StorageDead(_52); - StorageLive(_55); StorageLive(_56); StorageLive(_57); - _57 = _1; -- _56 = Shr(move _57, const 0_i32); -+ _56 = Shr(_1, const 0_i32); - StorageDead(_57); - _55 = opaque::(move _56) -> [return: bb24, unwind continue]; + StorageLive(_58); + _58 = _1; +- _57 = BitOr(move _58, const 0_u64); ++ _57 = _1; + StorageDead(_58); +- _56 = opaque::(move _57) -> [return: bb24, unwind continue]; ++ _56 = opaque::(_1) -> [return: bb24, unwind continue]; } bb24: { + StorageDead(_57); StorageDead(_56); - StorageDead(_55); - StorageLive(_58); StorageLive(_59); StorageLive(_60); - _60 = _1; -- _59 = Shl(move _60, const 0_i32); -+ _59 = Shl(_1, const 0_i32); - StorageDead(_60); - _58 = opaque::(move _59) -> [return: bb25, unwind continue]; + StorageLive(_61); + _61 = _1; +- _60 = BitOr(move _61, const _); ++ _60 = const u64::MAX; + StorageDead(_61); +- _59 = opaque::(move _60) -> [return: bb25, unwind continue]; ++ _59 = opaque::(const u64::MAX) -> [return: bb25, unwind continue]; } bb25: { + StorageDead(_60); StorageDead(_59); - StorageDead(_58); + StorageLive(_62); + StorageLive(_63); + StorageLive(_64); + _64 = _1; +- _63 = BitXor(move _64, const 0_u64); ++ _63 = _1; + StorageDead(_64); +- _62 = opaque::(move _63) -> [return: bb26, unwind continue]; ++ _62 = opaque::(_1) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); + StorageLive(_67); + _67 = _1; + StorageLive(_68); + _68 = _1; +- _66 = BitXor(move _67, move _68); ++ _66 = const 0_u64; + StorageDead(_68); + StorageDead(_67); +- _65 = opaque::(move _66) -> [return: bb27, unwind continue]; ++ _65 = opaque::(const 0_u64) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_69); + StorageLive(_70); + StorageLive(_71); + _71 = _1; +- _70 = Shr(move _71, const 0_i32); ++ _70 = _1; + StorageDead(_71); +- _69 = opaque::(move _70) -> [return: bb28, unwind continue]; ++ _69 = opaque::(_1) -> [return: bb28, unwind continue]; + } + + bb28: { + StorageDead(_70); + StorageDead(_69); + StorageLive(_72); + StorageLive(_73); + StorageLive(_74); + _74 = _1; +- _73 = Shl(move _74, const 0_i32); ++ _73 = _1; + StorageDead(_74); +- _72 = opaque::(move _73) -> [return: bb29, unwind continue]; ++ _72 = opaque::(_1) -> [return: bb29, unwind continue]; + } + + bb29: { + StorageDead(_73); + StorageDead(_72); _0 = const (); return; } diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff index 6633df3ae702..a45d9920a684 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff @@ -15,11 +15,16 @@ let _10: (); let mut _11: u64; let mut _12: u64; - let mut _13: (u64, bool); - let _14: (); - let mut _15: u64; + let mut _13: u64; + let mut _14: (u64, bool); + let _15: (); let mut _16: u64; - let mut _17: (u64, bool); + let mut _17: u64; + let mut _18: (u64, bool); + let _19: (); + let mut _20: u64; + let mut _21: u64; + let mut _22: (u64, bool); bb0: { StorageLive(_2); @@ -29,13 +34,15 @@ - _5 = CheckedAdd(_4, const 0_u64); - assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable]; + _5 = CheckedAdd(_1, const 0_u64); -+ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; } bb1: { - _3 = move (_5.0: u64); +- _3 = move (_5.0: u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb2, unwind unreachable]; +- _2 = opaque::(move _3) -> [return: bb2, unwind unreachable]; ++ _2 = opaque::(_1) -> [return: bb2, unwind unreachable]; } bb2: { @@ -47,59 +54,95 @@ _8 = _1; - _9 = CheckedSub(_8, const 0_u64); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable]; -+ _9 = CheckedSub(_1, const 0_u64); -+ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; ++ _9 = _5; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; } bb3: { - _7 = move (_9.0: u64); +- _7 = move (_9.0: u64); ++ _7 = _1; StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb4, unwind unreachable]; +- _6 = opaque::(move _7) -> [return: bb4, unwind unreachable]; ++ _6 = opaque::(_1) -> [return: bb4, unwind unreachable]; } bb4: { StorageDead(_7); StorageDead(_6); StorageLive(_10); - StorageLive(_11); +- StorageLive(_11); ++ nop; StorageLive(_12); _12 = _1; -- _13 = CheckedMul(_12, const 0_u64); -- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind unreachable]; -+ _13 = CheckedMul(_1, const 0_u64); -+ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind unreachable]; + StorageLive(_13); + _13 = _1; +- _14 = CheckedSub(_12, _13); +- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind unreachable]; ++ _14 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind unreachable]; } bb5: { - _11 = move (_13.0: u64); +- _11 = move (_14.0: u64); ++ _11 = const 0_u64; + StorageDead(_13); StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb6, unwind unreachable]; +- _10 = opaque::(move _11) -> [return: bb6, unwind unreachable]; ++ _10 = opaque::(const 0_u64) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_11); +- StorageDead(_11); ++ nop; StorageDead(_10); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = CheckedMul(_16, const 1_u64); -- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind unreachable]; -+ _17 = CheckedMul(_1, const 1_u64); -+ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind unreachable]; + StorageLive(_17); + _17 = _1; +- _18 = CheckedMul(_17, const 0_u64); +- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind unreachable]; ++ _18 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind unreachable]; } bb7: { - _15 = move (_17.0: u64); - StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb8, unwind unreachable]; +- _16 = move (_18.0: u64); ++ _16 = const 0_u64; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb8, unwind unreachable]; ++ _15 = opaque::(const 0_u64) -> [return: bb8, unwind unreachable]; } bb8: { + StorageDead(_16); StorageDead(_15); - StorageDead(_14); + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); + _21 = _1; +- _22 = CheckedMul(_21, const 1_u64); +- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind unreachable]; ++ _22 = _5; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind unreachable]; + } + + bb9: { +- _20 = move (_22.0: u64); ++ _20 = _1; + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb10, unwind unreachable]; ++ _19 = opaque::(_1) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_20); + StorageDead(_19); _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ } diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff index d100a77fee5f..9033b392bd4c 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff @@ -15,11 +15,16 @@ let _10: (); let mut _11: u64; let mut _12: u64; - let mut _13: (u64, bool); - let _14: (); - let mut _15: u64; + let mut _13: u64; + let mut _14: (u64, bool); + let _15: (); let mut _16: u64; - let mut _17: (u64, bool); + let mut _17: u64; + let mut _18: (u64, bool); + let _19: (); + let mut _20: u64; + let mut _21: u64; + let mut _22: (u64, bool); bb0: { StorageLive(_2); @@ -29,13 +34,15 @@ - _5 = CheckedAdd(_4, const 0_u64); - assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue]; + _5 = CheckedAdd(_1, const 0_u64); -+ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; } bb1: { - _3 = move (_5.0: u64); +- _3 = move (_5.0: u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb2, unwind continue]; +- _2 = opaque::(move _3) -> [return: bb2, unwind continue]; ++ _2 = opaque::(_1) -> [return: bb2, unwind continue]; } bb2: { @@ -47,59 +54,95 @@ _8 = _1; - _9 = CheckedSub(_8, const 0_u64); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue]; -+ _9 = CheckedSub(_1, const 0_u64); -+ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; ++ _9 = _5; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; } bb3: { - _7 = move (_9.0: u64); +- _7 = move (_9.0: u64); ++ _7 = _1; StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb4, unwind continue]; +- _6 = opaque::(move _7) -> [return: bb4, unwind continue]; ++ _6 = opaque::(_1) -> [return: bb4, unwind continue]; } bb4: { StorageDead(_7); StorageDead(_6); StorageLive(_10); - StorageLive(_11); +- StorageLive(_11); ++ nop; StorageLive(_12); _12 = _1; -- _13 = CheckedMul(_12, const 0_u64); -- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind continue]; -+ _13 = CheckedMul(_1, const 0_u64); -+ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind continue]; + StorageLive(_13); + _13 = _1; +- _14 = CheckedSub(_12, _13); +- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind continue]; ++ _14 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind continue]; } bb5: { - _11 = move (_13.0: u64); +- _11 = move (_14.0: u64); ++ _11 = const 0_u64; + StorageDead(_13); StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb6, unwind continue]; +- _10 = opaque::(move _11) -> [return: bb6, unwind continue]; ++ _10 = opaque::(const 0_u64) -> [return: bb6, unwind continue]; } bb6: { - StorageDead(_11); +- StorageDead(_11); ++ nop; StorageDead(_10); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = CheckedMul(_16, const 1_u64); -- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind continue]; -+ _17 = CheckedMul(_1, const 1_u64); -+ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind continue]; + StorageLive(_17); + _17 = _1; +- _18 = CheckedMul(_17, const 0_u64); +- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind continue]; ++ _18 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind continue]; } bb7: { - _15 = move (_17.0: u64); - StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb8, unwind continue]; +- _16 = move (_18.0: u64); ++ _16 = const 0_u64; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb8, unwind continue]; ++ _15 = opaque::(const 0_u64) -> [return: bb8, unwind continue]; } bb8: { + StorageDead(_16); StorageDead(_15); - StorageDead(_14); + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); + _21 = _1; +- _22 = CheckedMul(_21, const 1_u64); +- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind continue]; ++ _22 = _5; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind continue]; + } + + bb9: { +- _20 = move (_22.0: u64); ++ _20 = _1; + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb10, unwind continue]; ++ _19 = opaque::(_1) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_20); + StorageDead(_19); _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ } diff --git a/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff b/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff index ee3b9da2122b..fefdf14bddcd 100644 --- a/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff @@ -30,10 +30,11 @@ StorageLive(_6); _6 = _1; - _4 = Eq(move _5, move _6); -+ _4 = Eq(_1, _1); ++ _4 = const true; StorageDead(_6); StorageDead(_5); - _3 = opaque::(move _4) -> [return: bb1, unwind unreachable]; +- _3 = opaque::(move _4) -> [return: bb1, unwind unreachable]; ++ _3 = opaque::(const true) -> [return: bb1, unwind unreachable]; } bb1: { @@ -46,10 +47,11 @@ StorageLive(_10); _10 = _1; - _8 = Ne(move _9, move _10); -+ _8 = Ne(_1, _1); ++ _8 = const false; StorageDead(_10); StorageDead(_9); - _7 = opaque::(move _8) -> [return: bb2, unwind unreachable]; +- _7 = opaque::(move _8) -> [return: bb2, unwind unreachable]; ++ _7 = opaque::(const false) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff b/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff index a1408fe3434c..9f19b2b59fa5 100644 --- a/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff @@ -30,10 +30,11 @@ StorageLive(_6); _6 = _1; - _4 = Eq(move _5, move _6); -+ _4 = Eq(_1, _1); ++ _4 = const true; StorageDead(_6); StorageDead(_5); - _3 = opaque::(move _4) -> [return: bb1, unwind continue]; +- _3 = opaque::(move _4) -> [return: bb1, unwind continue]; ++ _3 = opaque::(const true) -> [return: bb1, unwind continue]; } bb1: { @@ -46,10 +47,11 @@ StorageLive(_10); _10 = _1; - _8 = Ne(move _9, move _10); -+ _8 = Ne(_1, _1); ++ _8 = const false; StorageDead(_10); StorageDead(_9); - _7 = opaque::(move _8) -> [return: bb2, unwind continue]; +- _7 = opaque::(move _8) -> [return: bb2, unwind continue]; ++ _7 = opaque::(const false) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index d8248d22d38b..0901896af535 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:591:19: 591:21}; + let _7: {closure@$DIR/gvn.rs:585:19: 585:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:591:19: 591:21}; +- _7 = {closure@$DIR/gvn.rs:585:19: 585:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index e38a3d852092..4b95191ba82a 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:591:19: 591:21}; + let _7: {closure@$DIR/gvn.rs:585:19: 585:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:591:19: 591:21}; +- _7 = {closure@$DIR/gvn.rs:585:19: 585:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 23e33a0fa49e..8c06e3a6385a 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -169,66 +169,61 @@ fn repeated_index(x: T, idx: usize) { /// Verify symbolic integer arithmetic simplifications. fn arithmetic(x: u64) { // CHECK-LABEL: fn arithmetic( - // CHECK: [[add:_.*]] = Add(_1, const 0_u64); - // CHECK: opaque::(move [[add]]) + // CHECK: opaque::(_1) opaque(x + 0); - // CHECK: [[sub:_.*]] = Sub(_1, const 0_u64); - // CHECK: opaque::(move [[sub]]) + // CHECK: opaque::(_1) opaque(x - 0); - // CHECK: [[mul0:_.*]] = Mul(_1, const 0_u64); - // CHECK: opaque::(move [[mul0]]) + // CHECK: opaque::(const 0_u64) + opaque(x - x); + // CHECK: opaque::(const 0_u64) opaque(x * 0); - // CHECK: [[mul1:_.*]] = Mul(_1, const 1_u64); - // CHECK: opaque::(move [[mul1]]) + // CHECK: opaque::(_1) opaque(x * 1); + // CHECK: assert(!const true, "attempt to divide `{}` by zero", // CHECK: [[div0:_.*]] = Div(_1, const 0_u64); // CHECK: opaque::(move [[div0]]) opaque(x / 0); - // CHECK: [[div1:_.*]] = Div(_1, const 1_u64); - // CHECK: opaque::(move [[div1]]) + // CHECK: opaque::(_1) opaque(x / 1); - // CHECK: [[zdiv:_.*]] = Div(const 0_u64, _1); - // CHECK: opaque::(move [[zdiv]]) + // CHECK: opaque::(const 0_u64) opaque(0 / x); // CHECK: [[odiv:_.*]] = Div(const 1_u64, _1); // CHECK: opaque::(move [[odiv]]) opaque(1 / x); + // CHECK: assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero" // CHECK: [[rem0:_.*]] = Rem(_1, const 0_u64); // CHECK: opaque::(move [[rem0]]) opaque(x % 0); - // CHECK: [[rem1:_.*]] = Rem(_1, const 1_u64); - // CHECK: opaque::(move [[rem1]]) + // CHECK: opaque::(const 0_u64) opaque(x % 1); - // CHECK: [[zrem:_.*]] = Rem(const 0_u64, _1); - // CHECK: opaque::(move [[zrem]]) + // CHECK: opaque::(const 0_u64) opaque(0 % x); // CHECK: [[orem:_.*]] = Rem(const 1_u64, _1); // CHECK: opaque::(move [[orem]]) opaque(1 % x); - // CHECK: [[and:_.*]] = BitAnd(_1, const 0_u64); - // CHECK: opaque::(move [[and]]) + // CHECK: opaque::(const 0_u64) opaque(x & 0); - // CHECK: [[or:_.*]] = BitOr(_1, const 0_u64); - // CHECK: opaque::(move [[or]]) + // CHECK: opaque::(_1) + opaque(x & u64::MAX); + // CHECK: opaque::(_1) opaque(x | 0); - // CHECK: [[xor:_.*]] = BitXor(_1, const 0_u64); - // CHECK: opaque::(move [[xor]]) + // CHECK: opaque::(const u64::MAX) + opaque(x | u64::MAX); + // CHECK: opaque::(_1) opaque(x ^ 0); - // CHECK: [[shr:_.*]] = Shr(_1, const 0_i32); - // CHECK: opaque::(move [[shr]]) + // CHECK: opaque::(const 0_u64) + opaque(x ^ x); + // CHECK: opaque::(_1) opaque(x >> 0); - // CHECK: [[shl:_.*]] = Shl(_1, const 0_i32); - // CHECK: opaque::(move [[shl]]) + // CHECK: opaque::(_1) opaque(x << 0); } fn comparison(x: u64, y: u64) { // CHECK-LABEL: fn comparison( - // CHECK: [[eqxx:_.*]] = Eq(_1, _1); - // CHECK: opaque::(move [[eqxx]]) + // CHECK: opaque::(const true) opaque(x == x); - // CHECK: [[nexx:_.*]] = Ne(_1, _1); - // CHECK: opaque::(move [[nexx]]) + // CHECK: opaque::(const false) opaque(x != x); // CHECK: [[eqxy:_.*]] = Eq(_1, _2); // CHECK: opaque::(move [[eqxy]]) @@ -242,21 +237,20 @@ fn comparison(x: u64, y: u64) { #[rustc_inherit_overflow_checks] fn arithmetic_checked(x: u64) { // CHECK-LABEL: fn arithmetic_checked( - // CHECK: [[cadd:_.*]] = CheckedAdd(_1, const 0_u64); - // CHECK: [[add:_.*]] = move ([[cadd]].0: u64); - // CHECK: opaque::(move [[add]]) + // CHECK: assert(!const false, + // CHECK: opaque::(_1) opaque(x + 0); - // CHECK: [[csub:_.*]] = CheckedSub(_1, const 0_u64); - // CHECK: [[sub:_.*]] = move ([[csub]].0: u64); - // CHECK: opaque::(move [[sub]]) + // CHECK: assert(!const false, + // CHECK: opaque::(_1) opaque(x - 0); - // CHECK: [[cmul0:_.*]] = CheckedMul(_1, const 0_u64); - // CHECK: [[mul0:_.*]] = move ([[cmul0]].0: u64); - // CHECK: opaque::(move [[mul0]]) + // CHECK: assert(!const false, + // CHECK: opaque::(const 0_u64) + opaque(x - x); + // CHECK: assert(!const false, + // CHECK: opaque::(const 0_u64) opaque(x * 0); - // CHECK: [[cmul1:_.*]] = CheckedMul(_1, const 1_u64); - // CHECK: [[mul1:_.*]] = move ([[cmul1]].0: u64); - // CHECK: opaque::(move [[mul1]]) + // CHECK: assert(!const false, + // CHECK: opaque::(_1) opaque(x * 1); } diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index b04728a9b0f5..187290785c03 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -19,7 +19,6 @@ scope 1 (inlined imm8) { debug x => _5; let mut _14: u32; - let mut _15: u32; scope 2 { debug out => _4; } @@ -36,14 +35,14 @@ StorageLive(_5); _5 = _1; _4 = const 0_u32; - StorageLive(_15); - StorageLive(_14); -- _14 = Shr(_5, const 0_i32); -+ _14 = Shr(_1, const 0_i32); - _15 = BitAnd(move _14, const 255_u32); - StorageDead(_14); - _4 = BitOr(const 0_u32, move _15); - StorageDead(_15); +- StorageLive(_14); +- _14 = BitAnd(_5, const 255_u32); +- _4 = BitOr(const 0_u32, move _14); +- StorageDead(_14); ++ nop; ++ _14 = BitAnd(_1, const 255_u32); ++ _4 = _14; ++ nop; StorageDead(_5); StorageLive(_6); StorageLive(_7); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index fcf99ac6918d..99350bac478d 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -19,7 +19,6 @@ scope 1 (inlined imm8) { debug x => _5; let mut _14: u32; - let mut _15: u32; scope 2 { debug out => _4; } @@ -36,14 +35,14 @@ StorageLive(_5); _5 = _1; _4 = const 0_u32; - StorageLive(_15); - StorageLive(_14); -- _14 = Shr(_5, const 0_i32); -+ _14 = Shr(_1, const 0_i32); - _15 = BitAnd(move _14, const 255_u32); - StorageDead(_14); - _4 = BitOr(const 0_u32, move _15); - StorageDead(_15); +- StorageLive(_14); +- _14 = BitAnd(_5, const 255_u32); +- _4 = BitOr(const 0_u32, move _14); +- StorageDead(_14); ++ nop; ++ _14 = BitAnd(_1, const 255_u32); ++ _4 = _14; ++ nop; StorageDead(_5); StorageLive(_6); StorageLive(_7); From 5fc23ad8e6b7a5ef0b5a6936cb043bd85f8bed59 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 25 Mar 2023 22:33:35 +0000 Subject: [PATCH 195/297] Simplify unary operations. --- compiler/rustc_mir_transform/src/gvn.rs | 20 +++ .../gvn.fn_pointers.GVN.panic-abort.diff | 18 +-- .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 +-- tests/mir-opt/gvn.rs | 27 ++++ tests/mir-opt/gvn.unary.GVN.panic-abort.diff | 153 ++++++++++++++++++ tests/mir-opt/gvn.unary.GVN.panic-unwind.diff | 153 ++++++++++++++++++ 6 files changed, 371 insertions(+), 18 deletions(-) create mode 100644 tests/mir-opt/gvn.unary.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.unary.GVN.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 3052369c3ca4..699b218d46d5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -817,6 +817,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } Rvalue::UnaryOp(op, ref mut arg) => { let arg = self.simplify_operand(arg, location)?; + if let Some(value) = self.simplify_unary(op, arg) { + return Some(value); + } Value::UnaryOp(op, arg) } Rvalue::Discriminant(ref mut place) => { @@ -916,6 +919,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(self.insert(Value::Aggregate(ty, variant_index, fields))) } + #[instrument(level = "trace", skip(self), ret)] + fn simplify_unary(&mut self, op: UnOp, value: VnIndex) -> Option { + let value = match (op, self.get(value)) { + (UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner), + (UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner), + (UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => { + Value::BinaryOp(BinOp::Ne, *lhs, *rhs) + } + (UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => { + Value::BinaryOp(BinOp::Eq, *lhs, *rhs) + } + _ => return None, + }; + + Some(self.insert(value)) + } + #[instrument(level = "trace", skip(self), ret)] fn simplify_binary( &mut self, diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 0901896af535..02bf95840daf 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21}; + let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21}; + let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:585:19: 585:21}; + let _7: {closure@$DIR/gvn.rs:610:19: 610:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:585:19: 585:21}; +- _7 = {closure@$DIR/gvn.rs:610:19: 610:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index 4b95191ba82a..c5dcc8a8ec9d 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21}; + let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21}; + let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:585:19: 585:21}; + let _7: {closure@$DIR/gvn.rs:610:19: 610:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:585:19: 585:21}; +- _7 = {closure@$DIR/gvn.rs:610:19: 610:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 8c06e3a6385a..f8f4fdcd7323 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -166,6 +166,31 @@ fn repeated_index(x: T, idx: usize) { opaque(a[idx]); } +fn unary(x: i64) { + // CHECK-LABEL: fn unary( + // CHECK: opaque::(_1) + opaque(--x); // This is `x`. + + // CHECK: [[b:_.*]] = Lt(_1, const 13_i64); + // CHECK: opaque::([[b]]) + let b = x < 13; + opaque(!!b); // This is `b`. + + // Both lines should test the same thing. + // CHECK: [[c:_.*]] = Ne(_1, const 15_i64); + // CHECK: opaque::([[c]]) + // CHECK: opaque::([[c]]) + opaque(x != 15); + opaque(!(x == 15)); + + // Both lines should test the same thing. + // CHECK: [[d:_.*]] = Eq(_1, const 35_i64); + // CHECK: opaque::([[d]]) + // CHECK: opaque::([[d]]) + opaque(x == 35); + opaque(!(x != 35)); +} + /// Verify symbolic integer arithmetic simplifications. fn arithmetic(x: u64) { // CHECK-LABEL: fn arithmetic( @@ -623,6 +648,7 @@ fn main() { subexpression_elimination(2, 4, 5); wrap_unwrap(5); repeated_index::(5, 3); + unary(i64::MIN); arithmetic(5); comparison(5, 6); arithmetic_checked(5); @@ -651,6 +677,7 @@ fn identity(x: T) -> T { // EMIT_MIR gvn.subexpression_elimination.GVN.diff // EMIT_MIR gvn.wrap_unwrap.GVN.diff // EMIT_MIR gvn.repeated_index.GVN.diff +// EMIT_MIR gvn.unary.GVN.diff // EMIT_MIR gvn.arithmetic.GVN.diff // EMIT_MIR gvn.comparison.GVN.diff // EMIT_MIR gvn.arithmetic_checked.GVN.diff diff --git a/tests/mir-opt/gvn.unary.GVN.panic-abort.diff b/tests/mir-opt/gvn.unary.GVN.panic-abort.diff new file mode 100644 index 000000000000..9469032f294e --- /dev/null +++ b/tests/mir-opt/gvn.unary.GVN.panic-abort.diff @@ -0,0 +1,153 @@ +- // MIR for `unary` before GVN ++ // MIR for `unary` after GVN + + fn unary(_1: i64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i64; + let mut _4: i64; + let mut _5: i64; + let _6: bool; + let mut _7: i64; + let _8: (); + let mut _9: bool; + let mut _10: bool; + let mut _11: bool; + let _12: (); + let mut _13: bool; + let mut _14: i64; + let _15: (); + let mut _16: bool; + let mut _17: bool; + let mut _18: i64; + let _19: (); + let mut _20: bool; + let mut _21: i64; + let _22: (); + let mut _23: bool; + let mut _24: bool; + let mut _25: i64; + scope 1 { + debug b => _6; + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = Neg(move _5); ++ _4 = Neg(_1); + StorageDead(_5); +- _3 = Neg(move _4); ++ _3 = _1; + StorageDead(_4); +- _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); +- StorageLive(_6); ++ nop; + StorageLive(_7); + _7 = _1; +- _6 = Lt(move _7, const 13_i64); ++ _6 = Lt(_1, const 13_i64); + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = _6; +- _10 = Not(move _11); ++ _10 = Not(_6); + StorageDead(_11); +- _9 = Not(move _10); ++ _9 = _6; + StorageDead(_10); +- _8 = opaque::(move _9) -> [return: bb2, unwind unreachable]; ++ _8 = opaque::(_6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); ++ nop; + StorageLive(_14); + _14 = _1; +- _13 = Ne(move _14, const 15_i64); ++ _13 = Ne(_1, const 15_i64); + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb3, unwind unreachable]; ++ _12 = opaque::(_13) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_13); ++ nop; + StorageDead(_12); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + _18 = _1; +- _17 = Eq(move _18, const 15_i64); ++ _17 = Eq(_1, const 15_i64); + StorageDead(_18); +- _16 = Not(move _17); ++ _16 = _13; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb4, unwind unreachable]; ++ _15 = opaque::(_13) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_16); + StorageDead(_15); + StorageLive(_19); +- StorageLive(_20); ++ nop; + StorageLive(_21); + _21 = _1; +- _20 = Eq(move _21, const 35_i64); ++ _20 = Eq(_1, const 35_i64); + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb5, unwind unreachable]; ++ _19 = opaque::(_20) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_20); ++ nop; + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); + StorageLive(_25); + _25 = _1; +- _24 = Ne(move _25, const 35_i64); ++ _24 = Ne(_1, const 35_i64); + StorageDead(_25); +- _23 = Not(move _24); ++ _23 = _20; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb6, unwind unreachable]; ++ _22 = opaque::(_20) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_23); + StorageDead(_22); + _0 = const (); +- StorageDead(_6); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff b/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff new file mode 100644 index 000000000000..e672f6fb6ba7 --- /dev/null +++ b/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff @@ -0,0 +1,153 @@ +- // MIR for `unary` before GVN ++ // MIR for `unary` after GVN + + fn unary(_1: i64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i64; + let mut _4: i64; + let mut _5: i64; + let _6: bool; + let mut _7: i64; + let _8: (); + let mut _9: bool; + let mut _10: bool; + let mut _11: bool; + let _12: (); + let mut _13: bool; + let mut _14: i64; + let _15: (); + let mut _16: bool; + let mut _17: bool; + let mut _18: i64; + let _19: (); + let mut _20: bool; + let mut _21: i64; + let _22: (); + let mut _23: bool; + let mut _24: bool; + let mut _25: i64; + scope 1 { + debug b => _6; + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = Neg(move _5); ++ _4 = Neg(_1); + StorageDead(_5); +- _3 = Neg(move _4); ++ _3 = _1; + StorageDead(_4); +- _2 = opaque::(move _3) -> [return: bb1, unwind continue]; ++ _2 = opaque::(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); +- StorageLive(_6); ++ nop; + StorageLive(_7); + _7 = _1; +- _6 = Lt(move _7, const 13_i64); ++ _6 = Lt(_1, const 13_i64); + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = _6; +- _10 = Not(move _11); ++ _10 = Not(_6); + StorageDead(_11); +- _9 = Not(move _10); ++ _9 = _6; + StorageDead(_10); +- _8 = opaque::(move _9) -> [return: bb2, unwind continue]; ++ _8 = opaque::(_6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); ++ nop; + StorageLive(_14); + _14 = _1; +- _13 = Ne(move _14, const 15_i64); ++ _13 = Ne(_1, const 15_i64); + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb3, unwind continue]; ++ _12 = opaque::(_13) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_13); ++ nop; + StorageDead(_12); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + _18 = _1; +- _17 = Eq(move _18, const 15_i64); ++ _17 = Eq(_1, const 15_i64); + StorageDead(_18); +- _16 = Not(move _17); ++ _16 = _13; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb4, unwind continue]; ++ _15 = opaque::(_13) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_16); + StorageDead(_15); + StorageLive(_19); +- StorageLive(_20); ++ nop; + StorageLive(_21); + _21 = _1; +- _20 = Eq(move _21, const 35_i64); ++ _20 = Eq(_1, const 35_i64); + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb5, unwind continue]; ++ _19 = opaque::(_20) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_20); ++ nop; + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); + StorageLive(_25); + _25 = _1; +- _24 = Ne(move _25, const 35_i64); ++ _24 = Ne(_1, const 35_i64); + StorageDead(_25); +- _23 = Not(move _24); ++ _23 = _20; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb6, unwind continue]; ++ _22 = opaque::(_20) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_23); + StorageDead(_22); + _0 = const (); +- StorageDead(_6); ++ nop; + return; + } + } + From 3c48243b6fd28aeb27c856f8d23433e9f3ebaa0d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 20 Mar 2023 20:15:59 +0000 Subject: [PATCH 196/297] Simplify Len. --- compiler/rustc_mir_transform/src/gvn.rs | 38 +++++++++++++++++-- ...rray_index.main.GVN.32bit.panic-abort.diff | 7 ++-- ...ray_index.main.GVN.32bit.panic-unwind.diff | 7 ++-- ...rray_index.main.GVN.64bit.panic-abort.diff | 7 ++-- ...ray_index.main.GVN.64bit.panic-unwind.diff | 7 ++-- ...rray_index.main.GVN.32bit.panic-abort.diff | 7 ++-- ...ray_index.main.GVN.32bit.panic-unwind.diff | 7 ++-- ...rray_index.main.GVN.64bit.panic-abort.diff | 7 ++-- ...ray_index.main.GVN.64bit.panic-unwind.diff | 7 ++-- .../repeat.main.GVN.32bit.panic-abort.diff | 7 ++-- .../repeat.main.GVN.32bit.panic-unwind.diff | 7 ++-- .../repeat.main.GVN.64bit.panic-abort.diff | 7 ++-- .../repeat.main.GVN.64bit.panic-unwind.diff | 7 ++-- .../gvn.repeated_index.GVN.panic-abort.diff | 13 ++++--- .../gvn.repeated_index.GVN.panic-unwind.diff | 13 ++++--- 15 files changed, 96 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 699b218d46d5..afc75ff1313d 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -776,10 +776,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } // Operations. - Rvalue::Len(ref mut place) => { - let place = self.simplify_place_value(place, location)?; - Value::Len(place) - } + Rvalue::Len(ref mut place) => return self.simplify_len(place, location), Rvalue::Cast(kind, ref mut value, to) => { let from = value.ty(self.local_decls, self.tcx); let value = self.simplify_operand(value, location)?; @@ -1021,6 +1018,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(result) } } + + fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option { + // Trivial case: we are fetching a statically known length. + let place_ty = place.ty(self.local_decls, self.tcx).ty; + if let ty::Array(_, len) = place_ty.kind() { + return self.insert_constant(Const::from_ty_const(*len, self.tcx)); + } + + let mut inner = self.simplify_place_value(place, location)?; + + // The length information is stored in the fat pointer. + // Reborrowing copies length information from one pointer to the other. + while let Value::Address { place: borrowed, .. } = self.get(inner) + && let [PlaceElem::Deref] = borrowed.projection[..] + && let Some(borrowed) = self.locals[borrowed.local] + { + inner = borrowed; + } + + // We have an unsizing cast, which assigns the length to fat pointer metadata. + if let Value::Cast { kind, from, to, .. } = self.get(inner) + && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind + && let Some(from) = from.builtin_deref(true) + && let ty::Array(_, len) = from.ty.kind() + && let Some(to) = to.builtin_deref(true) + && let ty::Slice(..) = to.ty.kind() + { + return self.insert_constant(Const::from_ty_const(*len, self.tcx)); + } + + // Fallback: a symbolic `Len`. + Some(self.insert(Value::Len(inner))) + } } fn op_to_prop_const<'tcx>( diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff index f9537661e8ca..6d00dd5b2126 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff index 07886779fead..7e2f72ab31bc 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff index f9537661e8ca..6d00dd5b2126 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index 07886779fead..7e2f72ab31bc 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff index cf36109fdcbd..bd987c01ab16 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff index 40ed96971800..e9ebef84ae04 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff index cf36109fdcbd..bd987c01ab16 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff index 40ed96971800..e9ebef84ae04 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff index a52e6e35483d..71635b8e9c3e 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff index fe0acee71ebe..84205028d6d2 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff index a52e6e35483d..71635b8e9c3e 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff index fe0acee71ebe..84205028d6d2 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff index d937902e8913..8ce05c9b340f 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff @@ -32,11 +32,12 @@ StorageLive(_6); StorageLive(_7); _7 = const 0_usize; - _8 = Len(_3); +- _8 = Len(_3); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind unreachable]; -+ _9 = Lt(const 0_usize, _8); -+ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind unreachable]; ++ _8 = const N; ++ _9 = Lt(const 0_usize, const N); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable]; } bb1: { @@ -57,9 +58,9 @@ - _13 = Len(_3); - _14 = Lt(_12, _13); - assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind unreachable]; -+ _13 = _8; -+ _14 = Lt(_2, _8); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind unreachable]; ++ _13 = const N; ++ _14 = Lt(_2, const N); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff index dd4d24b12ea6..7ed547eeb4ad 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff @@ -32,11 +32,12 @@ StorageLive(_6); StorageLive(_7); _7 = const 0_usize; - _8 = Len(_3); +- _8 = Len(_3); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind continue]; -+ _9 = Lt(const 0_usize, _8); -+ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind continue]; ++ _8 = const N; ++ _9 = Lt(const 0_usize, const N); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue]; } bb1: { @@ -57,9 +58,9 @@ - _13 = Len(_3); - _14 = Lt(_12, _13); - assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind continue]; -+ _13 = _8; -+ _14 = Lt(_2, _8); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind continue]; ++ _13 = const N; ++ _14 = Lt(_2, const N); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind continue]; } bb3: { From 22ed51e136c8ad3a07d181b90e7610501ea69816 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 19:29:08 +0000 Subject: [PATCH 197/297] Do not read a scalar on a non-scalar layout. --- compiler/rustc_mir_transform/src/gvn.rs | 9 +- tests/mir-opt/gvn.rs | 23 ++ .../gvn.wide_ptr_ops.GVN.panic-abort.diff | 386 ++++++++++++++++++ .../gvn.wide_ptr_ops.GVN.panic-unwind.diff | 386 ++++++++++++++++++ 4 files changed, 802 insertions(+), 2 deletions(-) create mode 100644 tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index afc75ff1313d..fc14ea2696ff 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -953,8 +953,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let as_bits = |value| { let constant = self.evaluated[value].as_ref()?; - let scalar = self.ecx.read_scalar(constant).ok()?; - scalar.to_bits(constant.layout.size).ok() + if layout.abi.is_scalar() { + let scalar = self.ecx.read_scalar(constant).ok()?; + scalar.to_bits(constant.layout.size).ok() + } else { + // `constant` is a wide pointer. Do not evaluate to bits. + None + } }; // Represent the values as `Ok(bits)` or `Err(VnIndex)`. diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index f8f4fdcd7323..31ea237cbec8 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -644,6 +644,27 @@ fn constant_index_overflow(x: &[T]) { opaque(b) } +fn wide_ptr_ops() { + let a: *const dyn Send = &1 as &dyn Send; + let b: *const dyn Send = &1 as &dyn Send; + let _val = a == b; + let _val = a != b; + let _val = a < b; + let _val = a <= b; + let _val = a > b; + let _val = a >= b; + + let a: *const [u8] = unsafe { transmute((1usize, 1usize)) }; + let b: *const [u8] = unsafe { transmute((1usize, 2usize)) }; + + opaque(!(a == b)); + opaque(a != b); + opaque(a <= b); + opaque(a < b); + opaque(!(a >= b)); + opaque(!(a > b)); +} + fn main() { subexpression_elimination(2, 4, 5); wrap_unwrap(5); @@ -664,6 +685,7 @@ fn main() { fn_pointers(); indirect_static(); constant_index_overflow(&[5, 3]); + wide_ptr_ops(); } #[inline(never)] @@ -692,3 +714,4 @@ fn identity(x: T) -> T { // EMIT_MIR gvn.fn_pointers.GVN.diff // EMIT_MIR gvn.indirect_static.GVN.diff // EMIT_MIR gvn.constant_index_overflow.GVN.diff +// EMIT_MIR gvn.wide_ptr_ops.GVN.diff diff --git a/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff new file mode 100644 index 000000000000..e49d759b8fc3 --- /dev/null +++ b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff @@ -0,0 +1,386 @@ +- // MIR for `wide_ptr_ops` before GVN ++ // MIR for `wide_ptr_ops` after GVN + + fn wide_ptr_ops() -> () { + let mut _0: (); + let _1: *const dyn std::marker::Send; + let mut _2: *const dyn std::marker::Send; + let _3: &dyn std::marker::Send; + let mut _4: &i32; + let _5: &i32; + let _6: i32; + let mut _8: *const dyn std::marker::Send; + let _9: &dyn std::marker::Send; + let mut _10: &i32; + let _11: &i32; + let _12: i32; + let mut _14: *const dyn std::marker::Send; + let mut _15: *const dyn std::marker::Send; + let mut _16: *const dyn std::marker::Send; + let mut _18: *const dyn std::marker::Send; + let mut _19: *const dyn std::marker::Send; + let mut _20: *const dyn std::marker::Send; + let mut _22: *const dyn std::marker::Send; + let mut _23: *const dyn std::marker::Send; + let mut _24: *const dyn std::marker::Send; + let mut _26: *const dyn std::marker::Send; + let mut _27: *const dyn std::marker::Send; + let mut _28: *const dyn std::marker::Send; + let mut _30: *const dyn std::marker::Send; + let mut _31: *const dyn std::marker::Send; + let mut _32: *const dyn std::marker::Send; + let mut _34: *const dyn std::marker::Send; + let mut _35: *const dyn std::marker::Send; + let mut _36: *const dyn std::marker::Send; + let mut _38: (usize, usize); + let mut _40: (usize, usize); + let _41: (); + let mut _42: bool; + let mut _43: bool; + let mut _44: *const [u8]; + let mut _45: *const [u8]; + let _46: (); + let mut _47: bool; + let mut _48: *const [u8]; + let mut _49: *const [u8]; + let _50: (); + let mut _51: bool; + let mut _52: *const [u8]; + let mut _53: *const [u8]; + let _54: (); + let mut _55: bool; + let mut _56: *const [u8]; + let mut _57: *const [u8]; + let _58: (); + let mut _59: bool; + let mut _60: bool; + let mut _61: *const [u8]; + let mut _62: *const [u8]; + let _63: (); + let mut _64: bool; + let mut _65: bool; + let mut _66: *const [u8]; + let mut _67: *const [u8]; + let mut _69: &i32; + scope 1 { + debug a => _1; + let _7: *const dyn std::marker::Send; + let mut _68: &i32; + scope 2 { + debug b => _7; + let _13: bool; + scope 3 { + debug _val => _13; + let _17: bool; + scope 4 { + debug _val => _17; + let _21: bool; + scope 5 { + debug _val => _21; + let _25: bool; + scope 6 { + debug _val => _25; + let _29: bool; + scope 7 { + debug _val => _29; + let _33: bool; + scope 8 { + debug _val => _33; + let _37: *const [u8]; + scope 9 { + debug a => _37; + let _39: *const [u8]; + scope 11 { + debug b => _39; + } + scope 12 { + } + } + scope 10 { + } + } + } + } + } + } + } + } + } + + bb0: { +- StorageLive(_1); ++ nop; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _69 = const _; + _5 = &(*_69); + _4 = &(*_5); + _3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_4); + _2 = &raw const (*_3); + _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_2); + StorageDead(_5); + StorageDead(_3); +- StorageLive(_7); ++ nop; + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _68 = const _; + _11 = &(*_68); + _10 = &(*_11); + _9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_10); + _8 = &raw const (*_9); + _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_8); + StorageDead(_11); + StorageDead(_9); + StorageLive(_13); + StorageLive(_14); + _14 = _1; +- StorageLive(_15); ++ nop; + StorageLive(_16); + _16 = _7; +- _15 = move _16 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _15 = _7 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_16); +- _13 = Eq(move _14, move _15); +- StorageDead(_15); ++ _13 = Eq(_1, _15); ++ nop; + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); + _18 = _1; + StorageLive(_19); + StorageLive(_20); + _20 = _7; +- _19 = move _20 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _19 = _15; + StorageDead(_20); +- _17 = Ne(move _18, move _19); ++ _17 = Ne(_1, _15); + StorageDead(_19); + StorageDead(_18); + StorageLive(_21); + StorageLive(_22); + _22 = _1; + StorageLive(_23); + StorageLive(_24); + _24 = _7; +- _23 = move _24 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _23 = _15; + StorageDead(_24); +- _21 = Lt(move _22, move _23); ++ _21 = Lt(_1, _15); + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); + StorageLive(_26); + _26 = _1; + StorageLive(_27); + StorageLive(_28); + _28 = _7; +- _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _27 = _15; + StorageDead(_28); +- _25 = Le(move _26, move _27); ++ _25 = Le(_1, _15); + StorageDead(_27); + StorageDead(_26); + StorageLive(_29); + StorageLive(_30); + _30 = _1; + StorageLive(_31); + StorageLive(_32); + _32 = _7; +- _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _31 = _15; + StorageDead(_32); +- _29 = Gt(move _30, move _31); ++ _29 = Gt(_1, _15); + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); + _34 = _1; + StorageLive(_35); + StorageLive(_36); + _36 = _7; +- _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _35 = _15; + StorageDead(_36); +- _33 = Ge(move _34, move _35); ++ _33 = Ge(_1, _15); + StorageDead(_35); + StorageDead(_34); +- StorageLive(_37); ++ nop; + StorageLive(_38); +- _38 = (const 1_usize, const 1_usize); +- _37 = move _38 as *const [u8] (Transmute); ++ _38 = const (1_usize, 1_usize); ++ _37 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_38); +- StorageLive(_39); ++ nop; + StorageLive(_40); +- _40 = (const 1_usize, const 2_usize); +- _39 = move _40 as *const [u8] (Transmute); ++ _40 = const (1_usize, 2_usize); ++ _39 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_40); + StorageLive(_41); +- StorageLive(_42); ++ nop; + StorageLive(_43); + StorageLive(_44); +- _44 = _37; ++ _44 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_45); +- _45 = _39; +- _43 = Eq(move _44, move _45); ++ _45 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _43 = Eq(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_45); + StorageDead(_44); + _42 = Not(move _43); + StorageDead(_43); +- _41 = opaque::(move _42) -> [return: bb1, unwind unreachable]; ++ _41 = opaque::(_42) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_42); ++ nop; + StorageDead(_41); + StorageLive(_46); + StorageLive(_47); + StorageLive(_48); +- _48 = _37; ++ _48 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_49); +- _49 = _39; +- _47 = Ne(move _48, move _49); ++ _49 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _47 = _42; + StorageDead(_49); + StorageDead(_48); +- _46 = opaque::(move _47) -> [return: bb2, unwind unreachable]; ++ _46 = opaque::(_42) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); + StorageLive(_52); +- _52 = _37; ++ _52 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_53); +- _53 = _39; +- _51 = Le(move _52, move _53); ++ _53 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _51 = Le(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_53); + StorageDead(_52); + _50 = opaque::(move _51) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_54); + StorageLive(_55); + StorageLive(_56); +- _56 = _37; ++ _56 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_57); +- _57 = _39; +- _55 = Lt(move _56, move _57); ++ _57 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _55 = Lt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_57); + StorageDead(_56); + _54 = opaque::(move _55) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_55); + StorageDead(_54); + StorageLive(_58); + StorageLive(_59); + StorageLive(_60); + StorageLive(_61); +- _61 = _37; ++ _61 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_62); +- _62 = _39; +- _60 = Ge(move _61, move _62); ++ _62 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _60 = Ge(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_62); + StorageDead(_61); + _59 = Not(move _60); + StorageDead(_60); + _58 = opaque::(move _59) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_59); + StorageDead(_58); + StorageLive(_63); + StorageLive(_64); + StorageLive(_65); + StorageLive(_66); +- _66 = _37; ++ _66 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_67); +- _67 = _39; +- _65 = Gt(move _66, move _67); ++ _67 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _65 = Gt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_67); + StorageDead(_66); + _64 = Not(move _65); + StorageDead(_65); + _63 = opaque::(move _64) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_64); + StorageDead(_63); + _0 = const (); +- StorageDead(_39); +- StorageDead(_37); ++ nop; ++ nop; + StorageDead(_33); + StorageDead(_29); + StorageDead(_25); + StorageDead(_21); + StorageDead(_17); + StorageDead(_13); +- StorageDead(_7); +- StorageDead(_1); ++ nop; ++ nop; + return; + } ++ } ++ ++ ALLOC1 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff new file mode 100644 index 000000000000..4e5608a4425f --- /dev/null +++ b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff @@ -0,0 +1,386 @@ +- // MIR for `wide_ptr_ops` before GVN ++ // MIR for `wide_ptr_ops` after GVN + + fn wide_ptr_ops() -> () { + let mut _0: (); + let _1: *const dyn std::marker::Send; + let mut _2: *const dyn std::marker::Send; + let _3: &dyn std::marker::Send; + let mut _4: &i32; + let _5: &i32; + let _6: i32; + let mut _8: *const dyn std::marker::Send; + let _9: &dyn std::marker::Send; + let mut _10: &i32; + let _11: &i32; + let _12: i32; + let mut _14: *const dyn std::marker::Send; + let mut _15: *const dyn std::marker::Send; + let mut _16: *const dyn std::marker::Send; + let mut _18: *const dyn std::marker::Send; + let mut _19: *const dyn std::marker::Send; + let mut _20: *const dyn std::marker::Send; + let mut _22: *const dyn std::marker::Send; + let mut _23: *const dyn std::marker::Send; + let mut _24: *const dyn std::marker::Send; + let mut _26: *const dyn std::marker::Send; + let mut _27: *const dyn std::marker::Send; + let mut _28: *const dyn std::marker::Send; + let mut _30: *const dyn std::marker::Send; + let mut _31: *const dyn std::marker::Send; + let mut _32: *const dyn std::marker::Send; + let mut _34: *const dyn std::marker::Send; + let mut _35: *const dyn std::marker::Send; + let mut _36: *const dyn std::marker::Send; + let mut _38: (usize, usize); + let mut _40: (usize, usize); + let _41: (); + let mut _42: bool; + let mut _43: bool; + let mut _44: *const [u8]; + let mut _45: *const [u8]; + let _46: (); + let mut _47: bool; + let mut _48: *const [u8]; + let mut _49: *const [u8]; + let _50: (); + let mut _51: bool; + let mut _52: *const [u8]; + let mut _53: *const [u8]; + let _54: (); + let mut _55: bool; + let mut _56: *const [u8]; + let mut _57: *const [u8]; + let _58: (); + let mut _59: bool; + let mut _60: bool; + let mut _61: *const [u8]; + let mut _62: *const [u8]; + let _63: (); + let mut _64: bool; + let mut _65: bool; + let mut _66: *const [u8]; + let mut _67: *const [u8]; + let mut _69: &i32; + scope 1 { + debug a => _1; + let _7: *const dyn std::marker::Send; + let mut _68: &i32; + scope 2 { + debug b => _7; + let _13: bool; + scope 3 { + debug _val => _13; + let _17: bool; + scope 4 { + debug _val => _17; + let _21: bool; + scope 5 { + debug _val => _21; + let _25: bool; + scope 6 { + debug _val => _25; + let _29: bool; + scope 7 { + debug _val => _29; + let _33: bool; + scope 8 { + debug _val => _33; + let _37: *const [u8]; + scope 9 { + debug a => _37; + let _39: *const [u8]; + scope 11 { + debug b => _39; + } + scope 12 { + } + } + scope 10 { + } + } + } + } + } + } + } + } + } + + bb0: { +- StorageLive(_1); ++ nop; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _69 = const _; + _5 = &(*_69); + _4 = &(*_5); + _3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_4); + _2 = &raw const (*_3); + _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_2); + StorageDead(_5); + StorageDead(_3); +- StorageLive(_7); ++ nop; + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _68 = const _; + _11 = &(*_68); + _10 = &(*_11); + _9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_10); + _8 = &raw const (*_9); + _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_8); + StorageDead(_11); + StorageDead(_9); + StorageLive(_13); + StorageLive(_14); + _14 = _1; +- StorageLive(_15); ++ nop; + StorageLive(_16); + _16 = _7; +- _15 = move _16 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _15 = _7 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_16); +- _13 = Eq(move _14, move _15); +- StorageDead(_15); ++ _13 = Eq(_1, _15); ++ nop; + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); + _18 = _1; + StorageLive(_19); + StorageLive(_20); + _20 = _7; +- _19 = move _20 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _19 = _15; + StorageDead(_20); +- _17 = Ne(move _18, move _19); ++ _17 = Ne(_1, _15); + StorageDead(_19); + StorageDead(_18); + StorageLive(_21); + StorageLive(_22); + _22 = _1; + StorageLive(_23); + StorageLive(_24); + _24 = _7; +- _23 = move _24 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _23 = _15; + StorageDead(_24); +- _21 = Lt(move _22, move _23); ++ _21 = Lt(_1, _15); + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); + StorageLive(_26); + _26 = _1; + StorageLive(_27); + StorageLive(_28); + _28 = _7; +- _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _27 = _15; + StorageDead(_28); +- _25 = Le(move _26, move _27); ++ _25 = Le(_1, _15); + StorageDead(_27); + StorageDead(_26); + StorageLive(_29); + StorageLive(_30); + _30 = _1; + StorageLive(_31); + StorageLive(_32); + _32 = _7; +- _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _31 = _15; + StorageDead(_32); +- _29 = Gt(move _30, move _31); ++ _29 = Gt(_1, _15); + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); + _34 = _1; + StorageLive(_35); + StorageLive(_36); + _36 = _7; +- _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _35 = _15; + StorageDead(_36); +- _33 = Ge(move _34, move _35); ++ _33 = Ge(_1, _15); + StorageDead(_35); + StorageDead(_34); +- StorageLive(_37); ++ nop; + StorageLive(_38); +- _38 = (const 1_usize, const 1_usize); +- _37 = move _38 as *const [u8] (Transmute); ++ _38 = const (1_usize, 1_usize); ++ _37 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_38); +- StorageLive(_39); ++ nop; + StorageLive(_40); +- _40 = (const 1_usize, const 2_usize); +- _39 = move _40 as *const [u8] (Transmute); ++ _40 = const (1_usize, 2_usize); ++ _39 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_40); + StorageLive(_41); +- StorageLive(_42); ++ nop; + StorageLive(_43); + StorageLive(_44); +- _44 = _37; ++ _44 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_45); +- _45 = _39; +- _43 = Eq(move _44, move _45); ++ _45 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _43 = Eq(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_45); + StorageDead(_44); + _42 = Not(move _43); + StorageDead(_43); +- _41 = opaque::(move _42) -> [return: bb1, unwind continue]; ++ _41 = opaque::(_42) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_42); ++ nop; + StorageDead(_41); + StorageLive(_46); + StorageLive(_47); + StorageLive(_48); +- _48 = _37; ++ _48 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_49); +- _49 = _39; +- _47 = Ne(move _48, move _49); ++ _49 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _47 = _42; + StorageDead(_49); + StorageDead(_48); +- _46 = opaque::(move _47) -> [return: bb2, unwind continue]; ++ _46 = opaque::(_42) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); + StorageLive(_52); +- _52 = _37; ++ _52 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_53); +- _53 = _39; +- _51 = Le(move _52, move _53); ++ _53 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _51 = Le(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_53); + StorageDead(_52); + _50 = opaque::(move _51) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_54); + StorageLive(_55); + StorageLive(_56); +- _56 = _37; ++ _56 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_57); +- _57 = _39; +- _55 = Lt(move _56, move _57); ++ _57 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _55 = Lt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_57); + StorageDead(_56); + _54 = opaque::(move _55) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_55); + StorageDead(_54); + StorageLive(_58); + StorageLive(_59); + StorageLive(_60); + StorageLive(_61); +- _61 = _37; ++ _61 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_62); +- _62 = _39; +- _60 = Ge(move _61, move _62); ++ _62 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _60 = Ge(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_62); + StorageDead(_61); + _59 = Not(move _60); + StorageDead(_60); + _58 = opaque::(move _59) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_59); + StorageDead(_58); + StorageLive(_63); + StorageLive(_64); + StorageLive(_65); + StorageLive(_66); +- _66 = _37; ++ _66 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_67); +- _67 = _39; +- _65 = Gt(move _66, move _67); ++ _67 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _65 = Gt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_67); + StorageDead(_66); + _64 = Not(move _65); + StorageDead(_65); + _63 = opaque::(move _64) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_64); + StorageDead(_63); + _0 = const (); +- StorageDead(_39); +- StorageDead(_37); ++ nop; ++ nop; + StorageDead(_33); + StorageDead(_29); + StorageDead(_25); + StorageDead(_21); + StorageDead(_17); + StorageDead(_13); +- StorageDead(_7); +- StorageDead(_1); ++ nop; ++ nop; + return; + } ++ } ++ ++ ALLOC1 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ + } + From 166fe54eba4b691b9c69b2a3a24e5b82bd9848e3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 8 Jan 2024 22:44:38 +0000 Subject: [PATCH 198/297] Explain side-effects from simplify_operand. --- compiler/rustc_mir_transform/src/gvn.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index fc14ea2696ff..7a8e3b87b9bf 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -794,6 +794,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let ty = lhs.ty(self.local_decls, self.tcx); let lhs = self.simplify_operand(lhs, location); let rhs = self.simplify_operand(rhs, location); + // Only short-circuit options after we called `simplify_operand` + // on both operands for side effect. let lhs = lhs?; let rhs = rhs?; if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) { @@ -805,6 +807,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let ty = lhs.ty(self.local_decls, self.tcx); let lhs = self.simplify_operand(lhs, location); let rhs = self.simplify_operand(rhs, location); + // Only short-circuit options after we called `simplify_operand` + // on both operands for side effect. let lhs = lhs?; let rhs = rhs?; if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) { From 0cc2102c4a615fa8f259de491675d9e64606b022 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 8 Jan 2024 22:54:05 +0000 Subject: [PATCH 199/297] Expand match over binops. --- compiler/rustc_mir_transform/src/gvn.rs | 33 ++++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 7a8e3b87b9bf..390ec3e1a36a 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -966,12 +966,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } }; - // Represent the values as `Ok(bits)` or `Err(VnIndex)`. - let a = as_bits(lhs).ok_or(lhs); - let b = as_bits(rhs).ok_or(rhs); + // Represent the values as `Left(bits)` or `Right(VnIndex)`. + use Either::{Left, Right}; + let a = as_bits(lhs).map_or(Right(lhs), Left); + let b = as_bits(rhs).map_or(Right(rhs), Left); let result = match (op, a, b) { // Neutral elements. - (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Ok(0), Err(p)) + (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p)) | ( BinOp::Add | BinOp::BitOr @@ -980,28 +981,28 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { | BinOp::Offset | BinOp::Shl | BinOp::Shr, - Err(p), - Ok(0), + Right(p), + Left(0), ) - | (BinOp::Mul, Ok(1), Err(p)) - | (BinOp::Mul | BinOp::Div, Err(p), Ok(1)) => p, + | (BinOp::Mul, Left(1), Right(p)) + | (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p, // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size. - (BinOp::BitAnd, Err(p), Ok(ones)) | (BinOp::BitAnd, Ok(ones), Err(p)) + (BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p)) if ones == layout.size.truncate(u128::MAX) || (layout.ty.is_bool() && ones == 1) => { p } // Absorbing elements. - (BinOp::Mul | BinOp::BitAnd, _, Ok(0)) - | (BinOp::Rem, _, Ok(1)) + (BinOp::Mul | BinOp::BitAnd, _, Left(0)) + | (BinOp::Rem, _, Left(1)) | ( BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr, - Ok(0), + Left(0), _, ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty), // Attempt to simplify `x | ALL_ONES` to `ALL_ONES`. - (BinOp::BitOr, _, Ok(ones)) | (BinOp::BitOr, Ok(ones), _) + (BinOp::BitOr, _, Left(ones)) | (BinOp::BitOr, Left(ones), _) if ones == layout.size.truncate(u128::MAX) || (layout.ty.is_bool() && ones == 1) => { @@ -1015,8 +1016,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // - if both operands can be computed as bits, just compare the bits; // - if we proved that both operands have the same value, we can insert true/false; // - otherwise, do nothing, as we do not try to prove inequality. - (BinOp::Eq, a, b) if (a.is_ok() && b.is_ok()) || a == b => self.insert_bool(a == b), - (BinOp::Ne, a, b) if (a.is_ok() && b.is_ok()) || a == b => self.insert_bool(a != b), + (BinOp::Eq, Left(a), Left(b)) => self.insert_bool(a == b), + (BinOp::Eq, a, b) if a == b => self.insert_bool(true), + (BinOp::Ne, Left(a), Left(b)) => self.insert_bool(a != b), + (BinOp::Ne, a, b) if a == b => self.insert_bool(false), _ => return None, }; From 2564811e7b7464d4e2ab8cd5a826bf7c2f9f7d8b Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 16 Jan 2024 14:31:25 -0800 Subject: [PATCH 200/297] Remove tcx function and make `internal` fn safer I added `tcx` argument to `internal` to force 'tcx to be the same lifetime as TyCtxt. The only other solution I could think is to change this function to be `unsafe`. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 78 ++++++++++++------- compiler/rustc_smir/src/rustc_smir/context.rs | 5 +- .../stable-mir/check_trait_queries.rs | 4 +- .../stable-mir/compilation-result.rs | 10 +-- tests/ui-fulldeps/stable-mir/smir_internal.rs | 8 +- 5 files changed, 66 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 7633739f2890..873bd94e88fb 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -28,7 +28,7 @@ pub mod pretty; /// /// # Warning /// -/// This function is unstable, and it's behavior may change at any point. +/// This function is unstable, and its behavior may change at any point. /// E.g.: Items that were previously supported, may no longer be supported, or its translation may /// change. /// @@ -50,23 +50,12 @@ pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { /// # Panics /// /// This function will panic if StableMIR has not been properly initialized. -pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T { +pub fn internal<'tcx, S: RustcInternal<'tcx>>(tcx: TyCtxt<'tcx>, item: S) -> S::T { + // The tcx argument ensures that the item won't outlive the type context. + let _ = tcx; with_tables(|tables| item.internal(tables)) } -/// Retrieve the internal Rust compiler type context. -/// -/// # Warning -/// -/// This function is unstable, and it's behavior may change at any point. -/// -/// # Panics -/// -/// This function will panic if StableMIR has not been properly initialized. -pub fn tcx<'tcx>() -> TyCtxt<'tcx> { - with_tables(|tables| tables.tcx) -} - impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -227,7 +216,7 @@ where /// Instantiate and run the compiler with the provided arguments and callback. /// -/// The callback will be invoked after the compiler ran all its analysis, but before code generation. +/// The callback will be invoked after the compiler ran all its analyses, but before code generation. /// Note that this macro accepts two different formats for the callback: /// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow` /// ```ignore(needs-extern-crate) @@ -249,7 +238,7 @@ where /// # assert_eq!(result, Err(CompilerError::Skipped)) /// # } /// ``` -/// 2. An expression that represents the body of a closure: +/// 2. A closure expression: /// ```ignore(needs-extern-crate) /// # extern crate rustc_driver; /// # extern crate rustc_interface; @@ -267,26 +256,63 @@ where /// } /// # let args = vec!["--verbose".to_string()]; /// # let extra_args = vec![]; -/// let result = run!(args, analyze_code(extra_args)); +/// let result = run!(args, || analyze_code(extra_args)); /// # assert_eq!(result, Err(CompilerError::Skipped)) /// # } /// ``` #[macro_export] macro_rules! run { ($args:expr, $callback_fn:ident) => { - run!($args, $callback_fn()) + run_driver!($args, || $callback_fn()) }; - ($args:expr, $callback:expr) => {{ + ($args:expr, $callback:expr) => { + run_driver!($args, $callback) + }; +} + +/// Instantiate and run the compiler with the provided arguments and callback. +/// +/// This is similar to `run` but it invokes the callback with the compiler's `TyCtxt`, +/// which can be used to invoke internal APIs. +#[macro_export] +macro_rules! run_with_tcx { + ($args:expr, $callback_fn:ident) => { + run_driver!($args, |tcx| $callback_fn(tcx), with_tcx) + }; + ($args:expr, $callback:expr) => { + run_driver!($args, $callback, with_tcx) + }; +} + +/// Optionally include an ident. This is needed due to macro hygiene. +#[macro_export] +#[doc(hidden)] +macro_rules! optional { + (with_tcx $ident:ident) => { + $ident + }; +} + +/// Prefer using [run] and [run_with_tcx] instead. +/// +/// This macro implements the instantiation of a StableMIR driver, and it will invoke +/// the given callback after the compiler analyses. +/// +/// The third argument determines whether the callback requires `tcx` as an argument. +#[macro_export] +#[doc(hidden)] +macro_rules! run_driver { + ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{ use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use stable_mir::CompilerError; use std::ops::ControlFlow; - pub struct StableMir ControlFlow> + pub struct StableMir ControlFlow> where B: Send, C: Send, - F: FnOnce() -> ControlFlow + Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { args: Vec, callback: Option, @@ -297,7 +323,7 @@ macro_rules! run { where B: Send, C: Send, - F: FnOnce() -> ControlFlow + Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Creates a new `StableMir` instance, with given test_function and arguments. pub fn new(args: Vec, callback: F) -> Self { @@ -325,7 +351,7 @@ macro_rules! run { where B: Send, C: Send, - F: FnOnce() -> ControlFlow + Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Called after analysis. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) @@ -337,7 +363,7 @@ macro_rules! run { queries.global_ctxt().unwrap().enter(|tcx| { if let Some(callback) = self.callback.take() { rustc_internal::run(tcx, || { - self.result = Some((callback)()); + self.result = Some(callback($(optional!($with_tcx tcx))?)); }) .unwrap(); if self.result.as_ref().is_some_and(|val| val.is_continue()) { @@ -352,7 +378,7 @@ macro_rules! run { } } - StableMir::new($args, || $callback).run() + StableMir::new($args, $callback).run() }}; } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index fffc454804d2..2a2626654a01 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -29,7 +29,7 @@ use stable_mir::{Crate, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, S use std::cell::RefCell; use std::iter; -use crate::rustc_internal::{internal, RustcInternal}; +use crate::rustc_internal::RustcInternal; use crate::rustc_smir::builder::BodyBuilder; use crate::rustc_smir::{alloc, new_item_kind, smir_crate, Stable, Tables}; @@ -322,7 +322,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { } fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String { - internal(cnst).to_string() + let mut tables = self.0.borrow_mut(); + cnst.internal(&mut *tables).to_string() } fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index fb1197e4ecc4..c9fbe15ffb03 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -11,14 +11,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::CrateDef; use std::collections::HashSet; @@ -83,7 +81,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, test_traits()).unwrap(); + run!(args, test_traits).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index c802316c1d86..e6dd9fa132d8 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -35,33 +35,33 @@ fn main() { } fn test_continue(args: Vec) { - let result = run!(args, ControlFlow::Continue::<(), bool>(true)); + let result = run!(args, || ControlFlow::Continue::<(), bool>(true)); assert_eq!(result, Ok(true)); } fn test_break(args: Vec) { - let result = run!(args, ControlFlow::Break::(false)); + let result = run!(args, || ControlFlow::Break::(false)); assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false))); } #[allow(unreachable_code)] fn test_skipped(mut args: Vec) { args.push("--version".to_string()); - let result = run!(args, unreachable!() as ControlFlow<()>); + let result = run!(args, || unreachable!() as ControlFlow<()>); assert_eq!(result, Err(stable_mir::CompilerError::Skipped)); } #[allow(unreachable_code)] fn test_failed(mut args: Vec) { args.push("--cfg=broken".to_string()); - let result = run!(args, unreachable!() as ControlFlow<()>); + let result = run!(args, || unreachable!() as ControlFlow<()>); assert_eq!(result, Err(stable_mir::CompilerError::CompilationFailed)); } /// Test that we are able to pass a closure and set the return according to the captured value. fn test_captured(args: Vec) { let captured = "10".to_string(); - let result = run!(args, ControlFlow::Continue::<(), usize>(captured.len())); + let result = run!(args, || ControlFlow::Continue::<(), usize>(captured.len())); assert_eq!(result, Ok(captured.len())); } diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index 63a6a5e47e8b..b0811364c09f 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -16,19 +16,21 @@ extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; +extern crate rustc_middle; extern crate stable_mir; +use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use std::io::Write; use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_translation() -> ControlFlow<()> { +fn test_translation(tcx: TyCtxt) -> ControlFlow<()> { let main_fn = stable_mir::entry_fn().unwrap(); let body = main_fn.body(); let orig_ty = body.locals()[0].ty; - let rustc_ty = rustc_internal::internal(&orig_ty); + let rustc_ty = rustc_internal::internal(tcx, &orig_ty); assert!(rustc_ty.is_unit()); ControlFlow::Continue(()) } @@ -46,7 +48,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, test_translation).unwrap(); + run_with_tcx!(args, test_translation).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { From 7e1e61a4478b690113c86bf7b547e829969fe29d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 16 Jan 2024 18:34:44 -0500 Subject: [PATCH 201/297] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 84976cd699f4..1cff2ee6b92e 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 84976cd699f4aea56cb3a90ce3eedeed9e20d5a5 +Subproject commit 1cff2ee6b92e0ad3f87c44b70b28f788b2528b3c From b99c3ae6d66762b9faf863fa8078f5aad8b36205 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 15 Jan 2024 22:31:02 +0000 Subject: [PATCH 202/297] Get rid of the hir_owner query. --- compiler/rustc_hir/src/hir.rs | 2 +- .../rustc_incremental/src/assert_dep_graph.rs | 8 ++- .../src/persist/dirty_clean.rs | 3 +- compiler/rustc_middle/src/hir/map/mod.rs | 58 +++++++++---------- compiler/rustc_middle/src/hir/mod.rs | 35 +++-------- compiler/rustc_middle/src/query/erase.rs | 5 -- compiler/rustc_middle/src/query/mod.rs | 8 --- 7 files changed, 42 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6b347f7035a3..309850d04d36 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -841,7 +841,7 @@ pub struct OwnerNodes<'tcx> { } impl<'tcx> OwnerNodes<'tcx> { - fn node(&self) -> OwnerNode<'tcx> { + pub fn node(&self) -> OwnerNode<'tcx> { use rustc_index::Idx; let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 7b8d91702b39..6f909a0cc9db 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -128,9 +128,11 @@ impl<'tcx> IfThisChanged<'tcx> { if attr.has_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => { - DepNode::from_def_path_hash(self.tcx, def_path_hash, dep_kinds::hir_owner) - } + None => DepNode::from_def_path_hash( + self.tcx, + def_path_hash, + dep_kinds::hir_owner_nodes, + ), Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index f6acc60190a8..842cc9fae9b4 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -57,8 +57,7 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ - // hir_owner and hir_owner_nodes should be computed for all nodes - label_strs::hir_owner, + // hir_owner_nodes should be computed for all nodes label_strs::hir_owner_nodes, ]; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1574f0f1b31f..949b786e3a7d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,4 +1,4 @@ -use crate::hir::{ModuleItems, Owner}; +use crate::hir::ModuleItems; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; @@ -108,7 +108,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { if self.current_id.local_id.index() != 0 { self.current_id.local_id = ItemLocalId::new(0); if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node.node)); + return Some((self.current_id.owner, node)); } } if self.current_id == CRATE_HIR_ID { @@ -126,23 +126,23 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node.node)); + return Some((self.current_id.owner, node)); } } } } impl<'tcx> TyCtxt<'tcx> { + #[inline] + fn hir_owner(self, owner: OwnerId) -> Option> { + Some(self.hir_owner_nodes(owner).as_owner()?.node()) + } + /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. pub fn opt_hir_node(self, id: HirId) -> Option> { - if id.local_id == ItemLocalId::from_u32(0) { - let owner = self.hir_owner(id.owner)?; - Some(owner.node.into()) - } else { - let owner = self.hir_owner_nodes(id.owner).as_owner()?; - let node = owner.nodes[id.local_id].as_ref()?; - Some(node.node) - } + let owner = self.hir_owner_nodes(id.owner).as_owner()?; + let node = owner.nodes[id.local_id].as_ref()?; + Some(node.node) } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. @@ -174,7 +174,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { - match self.tcx.hir_owner(CRATE_OWNER_ID).map(|o| o.node) { + match self.tcx.hir_owner(CRATE_OWNER_ID) { Some(OwnerNode::Crate(item)) => item, _ => bug!(), } @@ -242,27 +242,27 @@ impl<'hir> Map<'hir> { pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { let node = self.tcx.hir_owner(OwnerId { def_id: id })?; - node.node.generics() + node.generics() } pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> { - self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node + self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)) } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_item() } pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_trait_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_trait_item() } pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_impl_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_impl_item() } pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_foreign_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_foreign_item() } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { @@ -436,7 +436,7 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); - match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) { + match self.tcx.hir_owner(hir_id.owner) { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id), Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), @@ -726,11 +726,10 @@ impl<'hir> Map<'hir> { pub fn get_foreign_abi(self, hir_id: HirId) -> Abi { let parent = self.get_parent_item(hir_id); - if let Some(node) = self.tcx.hir_owner(parent) { - if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node.node - { - return *abi; - } + if let Some(node) = self.tcx.hir_owner(parent) + && let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node + { + return *abi; } bug!( "expected foreign mod or inlined parent, found {}", @@ -742,33 +741,32 @@ impl<'hir> Map<'hir> { self.tcx .hir_owner(OwnerId { def_id }) .unwrap_or_else(|| bug!("expected owner for {:?}", def_id)) - .node } pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(Owner { node: OwnerNode::Item(item), .. }) => item, + Some(OwnerNode::Item(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, + Some(OwnerNode::ImplItem(item)) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, + Some(OwnerNode::TraitItem(item)) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> { match self.tcx.hir_owner(OwnerId { def_id }) { - Some(Owner { node, .. }) => node.fn_decl().map(|fn_decl| &fn_decl.output), + Some(node) => node.fn_decl().map(|fn_decl| &fn_decl.output), _ => None, } } @@ -782,7 +780,7 @@ impl<'hir> Map<'hir> { pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner(id) { - Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, + Some(OwnerNode::ForeignItem(item)) => item, _ => { bug!( "expected foreign item, found {}", diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index af99c7d55c37..2d4d5deaefa9 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -8,34 +8,12 @@ pub mod place; use crate::query::Providers; use crate::ty::{EarlyBinder, ImplSubject, TyCtxt}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; -use rustc_query_system::ich::StableHashingContext; use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP}; -/// Top-level HIR node for current owner. This only contains the node for which -/// `HirId::local_id == 0`, and excludes bodies. -/// -/// This struct exists to encapsulate all access to the hir_owner query in this module, and to -/// implement HashStable without hashing bodies. -#[derive(Copy, Clone, Debug)] -pub struct Owner<'tcx> { - node: OwnerNode<'tcx>, -} - -impl<'a, 'tcx> HashStable> for Owner<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - // Perform a shallow hash instead using the deep hash saved in `OwnerNodes`. This lets us - // differentiate queries that depend on the full HIR tree from those that only depend on - // the item signature. - hcx.without_hir_bodies(|hcx| self.node.hash_stable(hcx, hasher)); - } -} - /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable, Encodable, Decodable)] @@ -149,11 +127,6 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; - providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?; - let node = owner.node(); - Some(Owner { node }) - }; providers.opt_local_def_id_to_hir_id = |tcx, id| { let owner = tcx.hir_crate(()).owners[id].map(|_| ()); Some(match owner { @@ -162,7 +135,13 @@ pub fn provide(providers: &mut Providers) { MaybeOwner::NonOwner(hir_id) => hir_id, }) }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes); + providers.hir_owner_nodes = |tcx, id| { + if let Some(i) = tcx.hir_crate(()).owners.get(id.def_id) { + i.map(|i| &i.nodes) + } else { + MaybeOwner::Phantom + } + }; providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b9200f1abf16..168e7affe99b 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -160,10 +160,6 @@ impl EraseType for Option<&'_ [T]> { type Result = [u8; size_of::>()]; } -impl EraseType for Option> { - type Result = [u8; size_of::>>()]; -} - impl EraseType for Option> { type Result = [u8; size_of::>>()]; } @@ -320,7 +316,6 @@ macro_rules! tcx_lifetime { } tcx_lifetime! { - rustc_middle::hir::Owner, rustc_middle::middle::exported_symbols::ExportedSymbol, rustc_middle::mir::Const, rustc_middle::mir::DestructuredConstant, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1dc772208810..89e712d47f5f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -174,14 +174,6 @@ rustc_queries! { cache_on_disk_if { true } } - /// Gives access to the HIR node for the HIR owner `key`. - /// - /// This can be conveniently accessed by methods on `tcx.hir()`. - /// Avoid calling this query directly. - query hir_owner(key: hir::OwnerId) -> Option> { - desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key) } - } - /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any. /// /// Definitions that were generated with no HIR, would be fed to return `None`. From 20a8a23cb33fbc59fe89d64fa5dd51ccf33df415 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 16 Jan 2024 23:46:07 +0000 Subject: [PATCH 203/297] Bless incremental tests. --- tests/incremental/dirty_clean.rs | 5 +- tests/incremental/hash-module-order.rs | 4 +- tests/incremental/hashes/consts.rs | 10 +- tests/incremental/hashes/enum_constructors.rs | 36 +- tests/incremental/hashes/enum_defs.rs | 134 +++--- tests/incremental/hashes/extern_mods.rs | 12 +- .../incremental/hashes/function_interfaces.rs | 76 ++-- tests/incremental/hashes/if_expressions.rs | 16 +- .../hashes/indexing_expressions.rs | 12 +- tests/incremental/hashes/inherent_impls.rs | 128 +++--- tests/incremental/hashes/match_expressions.rs | 28 +- tests/incremental/hashes/statics.rs | 22 +- .../incremental/hashes/struct_constructors.rs | 24 +- tests/incremental/hashes/struct_defs.rs | 66 +-- tests/incremental/hashes/trait_defs.rs | 398 +++++++++--------- tests/incremental/hashes/trait_impls.rs | 100 ++--- tests/incremental/hashes/type_defs.rs | 32 +- 17 files changed, 533 insertions(+), 570 deletions(-) diff --git a/tests/incremental/dirty_clean.rs b/tests/incremental/dirty_clean.rs index 11d999ab3285..87a8696b1899 100644 --- a/tests/incremental/dirty_clean.rs +++ b/tests/incremental/dirty_clean.rs @@ -26,12 +26,11 @@ mod y { use x; #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", cfg="cfail2", )] pub fn y() { - //[cfail2]~^ ERROR `hir_owner(y)` should be dirty but is not - //[cfail2]~| ERROR `hir_owner_nodes(y)` should be dirty but is not + //[cfail2]~^ ERROR `hir_owner_nodes(y)` should be dirty but is not //[cfail2]~| ERROR `generics_of(y)` should be dirty but is not //[cfail2]~| ERROR `predicates_of(y)` should be dirty but is not //[cfail2]~| ERROR `type_of(y)` should be dirty but is not diff --git a/tests/incremental/hash-module-order.rs b/tests/incremental/hash-module-order.rs index fe9af9eeb370..f9244d8adbf3 100644 --- a/tests/incremental/hash-module-order.rs +++ b/tests/incremental/hash-module-order.rs @@ -12,14 +12,14 @@ #![feature(rustc_attrs)] #[cfg(rpass1)] -#[rustc_clean(cfg="rpass1",except="hir_owner")] +#[rustc_clean(cfg="rpass1",except="hir_owner_nodes")] mod foo { struct First; struct Second; } #[cfg(rpass2)] -#[rustc_clean(cfg="rpass2",except="hir_owner")] +#[rustc_clean(cfg="rpass2",except="hir_owner_nodes")] mod foo { struct Second; struct First; diff --git a/tests/incremental/hashes/consts.rs b/tests/incremental/hashes/consts.rs index eaef63386ffd..7cba3c159e60 100644 --- a/tests/incremental/hashes/consts.rs +++ b/tests/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,7 +39,7 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/enum_constructors.rs b/tests/incremental/hashes/enum_constructors.rs index f685fe46d70d..0a88dd4e1553 100644 --- a/tests/incremental/hashes/enum_constructors.rs +++ b/tests/incremental/hashes/enum_constructors.rs @@ -148,17 +148,9 @@ pub mod change_constructor_path_indirectly_struct_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Struct { @@ -261,17 +253,9 @@ pub mod change_constructor_path_indirectly_tuple_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Tuple(0, 1, 2) @@ -350,17 +334,9 @@ pub mod change_constructor_path_indirectly_c_like { #[cfg(not(any(cfail1,cfail4)))] use super::Clike2 as TheEnum; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::B diff --git a/tests/incremental/hashes/enum_defs.rs b/tests/incremental/hashes/enum_defs.rs index bc83723a908f..cb7a4e61e4f5 100644 --- a/tests/incremental/hashes/enum_defs.rs +++ b/tests/incremental/hashes/enum_defs.rs @@ -31,7 +31,7 @@ enum EnumVisibility { A } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub enum EnumVisibility { A } @@ -45,9 +45,9 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameCStyleVariant { Variant1, @@ -64,9 +64,9 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -83,9 +83,9 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -118,9 +118,9 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -136,9 +136,9 @@ enum EnumAddCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddCStyleVariant { Variant1, @@ -155,9 +155,9 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveCStyleVariant { Variant1, @@ -172,9 +172,9 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTupleStyleVariant { Variant1, @@ -191,9 +191,9 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -208,9 +208,9 @@ enum EnumAddStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddStructStyleVariant { Variant1, @@ -227,9 +227,9 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveStructStyleVariant { Variant1, @@ -244,9 +244,9 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -263,9 +263,9 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -284,9 +284,9 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -301,9 +301,9 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -320,9 +320,9 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -337,9 +337,9 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -354,9 +354,9 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -411,9 +411,9 @@ enum EnumChangeNameOfTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfTypeParameter { Variant1(T), @@ -429,9 +429,9 @@ enum EnumAddTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTypeParameter { Variant1(S), @@ -447,9 +447,9 @@ enum EnumChangeNameOfLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfLifetimeParameter<'b> { Variant1(&'b u32), @@ -465,9 +465,9 @@ enum EnumAddLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameter<'a, 'b> { Variant1(&'a u32), @@ -484,9 +484,9 @@ enum EnumAddLifetimeParameterBound<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBound<'a, 'b: 'a> { Variant1(&'a u32), @@ -501,9 +501,9 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), @@ -519,9 +519,9 @@ enum EnumAddTraitBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBound { Variant1(T), @@ -537,9 +537,9 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { Variant1(&'a u32), @@ -556,9 +556,9 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), @@ -574,9 +574,9 @@ enum EnumAddTraitBoundWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBoundWhere where T: Sync { Variant1(T), @@ -592,9 +592,9 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -615,9 +615,9 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -642,9 +642,9 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum TupleStyle { Variant1( @@ -662,9 +662,9 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum StructStyle { Variant1 { @@ -687,9 +687,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum { Variant1(T) @@ -705,9 +705,9 @@ mod change_trait_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum where T: Trait { Variant1(T) diff --git a/tests/incremental/hashes/extern_mods.rs b/tests/incremental/hashes/extern_mods.rs index 1906843c7a24..93a8fcfea321 100644 --- a/tests/incremental/hashes/extern_mods.rs +++ b/tests/incremental/hashes/extern_mods.rs @@ -24,9 +24,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_function_name2(c: i64) -> i32; @@ -129,9 +129,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "rust-call" { pub fn change_calling_convention(c: (i32,)); @@ -159,9 +159,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_function1(c: i32); diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 23b81705f9aa..2aaaf94492c2 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -25,12 +25,12 @@ pub fn add_parameter() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn add_parameter(p: i32) {} @@ -41,9 +41,9 @@ pub fn add_parameter(p: i32) {} pub fn add_return_type() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn add_return_type() -> () {} @@ -55,12 +55,12 @@ pub fn type_of_parameter(p: i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter(p: i64) {} @@ -73,12 +73,12 @@ pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter_ref(p: &mut i32) {} @@ -91,12 +91,12 @@ pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn order_of_parameters(p2: i64, p1: i32) {} @@ -109,12 +109,12 @@ pub fn make_unsafe() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub unsafe fn make_unsafe() {} @@ -125,9 +125,9 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail6")] pub extern "C" fn make_extern() {} @@ -139,12 +139,12 @@ pub fn type_parameter () {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail6")] pub fn type_parameter() {} @@ -155,9 +155,9 @@ pub fn type_parameter() {} pub fn lifetime_parameter () {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_parameter<'a>() {} @@ -167,7 +167,7 @@ pub fn lifetime_parameter<'a>() {} pub fn trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} @@ -177,9 +177,9 @@ pub fn trait_bound() {} pub fn builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn builtin_bound() {} @@ -191,12 +191,12 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" )] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -207,7 +207,7 @@ pub fn lifetime_bound<'a, T: 'a>() {} pub fn second_trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} @@ -217,9 +217,9 @@ pub fn second_trait_bound() {} pub fn second_builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn second_builtin_bound() {} @@ -231,12 +231,12 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a >() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} @@ -302,9 +302,9 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn return_impl_trait() -> impl Clone { 0 @@ -339,12 +339,12 @@ pub mod change_return_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_return_type() -> ReturnType { @@ -362,12 +362,12 @@ pub mod change_parameter_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_parameter_type(p: ParameterType) {} @@ -384,9 +384,9 @@ pub mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound(p: T) {} } @@ -399,9 +399,9 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound_where(p: T) where diff --git a/tests/incremental/hashes/if_expressions.rs b/tests/incremental/hashes/if_expressions.rs index 937fd3ac879a..cd80f8aa00a5 100644 --- a/tests/incremental/hashes/if_expressions.rs +++ b/tests/incremental/hashes/if_expressions.rs @@ -27,9 +27,9 @@ pub fn change_condition(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_condition(x: bool) -> u32 { if !x { @@ -103,9 +103,9 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -156,9 +156,9 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -209,9 +209,9 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/tests/incremental/hashes/indexing_expressions.rs b/tests/incremental/hashes/indexing_expressions.rs index b1ac6f6fa6c2..4bccec61a7ce 100644 --- a/tests/incremental/hashes/indexing_expressions.rs +++ b/tests/incremental/hashes/indexing_expressions.rs @@ -74,9 +74,9 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] @@ -91,9 +91,9 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] @@ -125,9 +125,9 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index 285f857c9cbc..853fbc79fc87 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -26,9 +26,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -115,7 +115,7 @@ impl Foo { impl Foo { //-------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- pub fn method_privacy() { } } @@ -128,7 +128,7 @@ impl Foo { impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] fn method_privacy() { } } @@ -138,31 +138,31 @@ impl Foo { impl Foo { //------------ //--------------- - //--------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //--------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------- // //-------------------------- pub fn method_selfness() { } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail6")] pub fn method_selfness(&self) { } @@ -171,9 +171,9 @@ impl Foo { // Change Method Selfmutness --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn method_selfmutness(& self) { } } @@ -184,9 +184,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn method_selfmutness(&mut self) { } } @@ -200,9 +200,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -221,9 +221,9 @@ impl Foo { // Add Method Parameter -------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn add_method_parameter(&self ) { } } @@ -234,9 +234,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_method_parameter(&self, _: i32) { } } @@ -271,9 +271,9 @@ impl Foo { // Change Method Return Type --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn change_method_return_type(&self) -> u16 { 0 } } @@ -284,9 +284,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_method_return_type(&self) -> u32 { 0 } } @@ -348,9 +348,9 @@ impl Foo { // Make method unsafe ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn make_method_unsafe(&self) { } } @@ -361,9 +361,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub unsafe fn make_method_unsafe(&self) { } } @@ -373,9 +373,9 @@ impl Foo { // Make method extern ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- pub fn make_method_extern(&self) { } } @@ -386,9 +386,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "C" fn make_method_extern(&self) { } } @@ -398,9 +398,9 @@ impl Foo { // Change method calling convention -------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- pub extern "C" fn change_method_calling_convention(&self) { } } @@ -411,9 +411,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -432,9 +432,9 @@ impl Foo { // ---------------------------------------------------------- // ----------------------------------------------------------- // ---------------------------------------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- pub fn add_lifetime_parameter_to_method (&self) { } } @@ -454,9 +454,9 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,generics_of")] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -477,12 +477,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------- + // ------------------------------------------------------------ // // ------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------- + // ------------------------------------------------------------ // // ------------------------- pub fn add_type_parameter_to_method (&self) { } @@ -505,12 +505,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + except="hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + except="hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail6")] pub fn add_type_parameter_to_method(&self) { } @@ -523,12 +523,12 @@ impl Foo { impl Foo { //------------ //--------------- - //----------------------------------------------------------------------------- + //------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //----------------------------------------------------------------------------- + //------------------------------------------------------------------- // //-------------------------- pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { } @@ -542,12 +542,12 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -569,12 +569,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------------- + // ------------------------------------------------------------------ // // ------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------------- + // ------------------------------------------------------------------ // // ------------------------- pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { } @@ -597,12 +597,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -622,9 +622,9 @@ impl Foo { // ------------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -644,9 +644,9 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -689,9 +689,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean( @@ -716,9 +716,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")] @@ -737,9 +737,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -758,9 +758,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/match_expressions.rs b/tests/incremental/hashes/match_expressions.rs index ecb19480d654..ebcf1708a7aa 100644 --- a/tests/incremental/hashes/match_expressions.rs +++ b/tests/incremental/hashes/match_expressions.rs @@ -28,9 +28,9 @@ pub fn add_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_arm(x: u32) -> u32 { match x { @@ -79,9 +79,9 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -104,9 +104,9 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -129,9 +129,9 @@ pub fn add_at_binding(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_at_binding(x: u32) -> u32 { match x { @@ -178,9 +178,9 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -273,9 +273,9 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { @@ -322,9 +322,9 @@ pub fn add_alternative_to_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { diff --git a/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs index bb83f8300d06..2adf05390bc4 100644 --- a/tests/incremental/hashes/statics.rs +++ b/tests/incremental/hashes/statics.rs @@ -26,7 +26,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub static STATIC_VISIBILITY: u8 = 0; @@ -36,9 +36,9 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static mut STATIC_MUTABILITY: u8 = 0; @@ -87,9 +87,9 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -99,9 +99,9 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_2: Option = None; @@ -169,15 +169,15 @@ mod static_change_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/struct_constructors.rs b/tests/incremental/hashes/struct_constructors.rs index e50e5674c661..eabb8683e029 100644 --- a/tests/incremental/hashes/struct_constructors.rs +++ b/tests/incremental/hashes/struct_constructors.rs @@ -90,9 +90,9 @@ pub fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -185,15 +185,9 @@ pub mod change_constructor_path_indirectly_regular_struct { #[cfg(not(any(cfail1,cfail4)))] use super::RegularStruct2 as Struct; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Struct { Struct { @@ -251,15 +245,9 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[cfg(not(any(cfail1,cfail4)))] use super::TupleStruct2 as Struct; - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { Struct(0, 1, 2) diff --git a/tests/incremental/hashes/struct_defs.rs b/tests/incremental/hashes/struct_defs.rs index 4a2706b4f010..6ea4d890e4d5 100644 --- a/tests/incremental/hashes/struct_defs.rs +++ b/tests/incremental/hashes/struct_defs.rs @@ -51,9 +51,9 @@ struct LayoutC; struct TupleStructFieldType(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -68,9 +68,9 @@ struct TupleStructFieldType( struct TupleStructAddField(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStructAddField( i32, @@ -86,7 +86,7 @@ struct TupleStructFieldVisibility( char); #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct TupleStructFieldVisibility(pub char); @@ -97,9 +97,9 @@ struct TupleStructFieldVisibility(pub char); struct RecordStructFieldType { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -114,9 +114,9 @@ struct RecordStructFieldType { struct RecordStructFieldName { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldName { y: f32 } @@ -127,9 +127,9 @@ struct RecordStructFieldName { y: f32 } struct RecordStructAddField { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructAddField { x: f32, @@ -144,7 +144,7 @@ struct RecordStructFieldVisibility { x: f32 } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldVisibility { pub x: f32 } @@ -155,9 +155,9 @@ struct RecordStructFieldVisibility { pub x: f32 } struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); @@ -168,9 +168,9 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBound<'a, 'b: 'a>( &'a f32, @@ -181,9 +181,9 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>( struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBoundWhereClause<'a, 'b>( &'a f32, @@ -197,9 +197,9 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( struct AddTypeParameter(T1, T1); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameter( // The field contains the parent's Generics, so it's dirty even though its @@ -215,9 +215,9 @@ struct AddTypeParameter( struct AddTypeParameterBound(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBound( T @@ -228,9 +228,9 @@ struct AddTypeParameterBound( struct AddTypeParameterBoundWhereClause(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBoundWhereClause( T @@ -257,7 +257,7 @@ struct Visibility; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub struct Visibility; @@ -271,9 +271,9 @@ mod tuple_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStruct( FieldType @@ -288,9 +288,9 @@ mod record_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStruct { _x: FieldType @@ -310,9 +310,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T); } @@ -324,9 +324,9 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T) where T : Trait; } diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index 7b8c6245d2d4..0a5eba739772 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -30,7 +30,7 @@ trait TraitVisibility { } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub trait TraitVisibility { } @@ -41,9 +41,9 @@ pub trait TraitVisibility { } trait TraitUnsafety { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe trait TraitUnsafety { } @@ -55,9 +55,9 @@ trait TraitAddMethod { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait TraitAddMethod { fn method(); @@ -72,9 +72,9 @@ trait TraitChangeMethodName { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodName { fn methodChanged(); @@ -85,9 +85,9 @@ trait TraitChangeMethodName { // Add return type to method #[cfg(any(cfail1,cfail4))] trait TraitAddReturnType { - //--------------------------------------------------------------------- + //----------------------------------------------------------- //-------------------------- - //--------------------------------------------------------------------- + //----------------------------------------------------------- //-------------------------- fn method() ; } @@ -98,9 +98,9 @@ trait TraitAddReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddReturnType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u32; } @@ -110,9 +110,9 @@ trait TraitAddReturnType { // Change return type of method #[cfg(any(cfail1,cfail4))] trait TraitChangeReturnType { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method() -> u32; } @@ -123,9 +123,9 @@ trait TraitChangeReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u64; } @@ -135,9 +135,9 @@ trait TraitChangeReturnType { // Add parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddParameterToMethod { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method( ); } @@ -148,9 +148,9 @@ trait TraitAddParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddParameterToMethod { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: u32); } @@ -161,9 +161,9 @@ trait TraitAddParameterToMethod { #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterName { //------------------------------------------------------ - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- fn method(a: u32); @@ -181,9 +181,9 @@ trait TraitChangeMethodParameterName { #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: u32); @@ -199,9 +199,9 @@ trait TraitChangeMethodParameterName { // Change type of method parameter (i32 => i64) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterType { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(a: i32); } @@ -212,9 +212,9 @@ trait TraitChangeMethodParameterType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: i64); } @@ -224,9 +224,9 @@ trait TraitChangeMethodParameterType { // Change type of method parameter (&i32 => &mut i32) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterTypeRef { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(a: & i32); } @@ -237,9 +237,9 @@ trait TraitChangeMethodParameterTypeRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterTypeRef { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: &mut i32); } @@ -249,9 +249,9 @@ trait TraitChangeMethodParameterTypeRef { // Change order of method parameters #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParametersOrder { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(a: i32, b: i64); } @@ -262,9 +262,9 @@ trait TraitChangeMethodParametersOrder { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParametersOrder { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: i64, a: i32); } @@ -274,22 +274,22 @@ trait TraitChangeMethodParametersOrder { // Add default implementation to method #[cfg(any(cfail1,cfail4))] trait TraitAddMethodAutoImplementation { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- fn method() ; } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddMethodAutoImplementation { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() {} } @@ -304,9 +304,9 @@ trait TraitChangeOrderOfMethods { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeOrderOfMethods { fn method1(); @@ -318,9 +318,9 @@ trait TraitChangeOrderOfMethods { // Change mode of self parameter #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfRefToMut { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(& self); } @@ -331,9 +331,9 @@ trait TraitChangeModeSelfRefToMut { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfRefToMut { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&mut self); } @@ -342,9 +342,9 @@ trait TraitChangeModeSelfRefToMut { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToMut: Sized { - // ---------------------------------------------------------------------------------- + // ------------------------------------------------------------------------ // ------------------------- - // ---------------------------------------------------------------------------------- + // ------------------------------------------------------------------------ // ------------------------- fn method( self) {} } @@ -355,9 +355,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(mut self) {} } @@ -366,9 +366,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToRef { - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- fn method( self); } @@ -379,9 +379,9 @@ trait TraitChangeModeSelfOwnToRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToRef { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&self); } @@ -391,22 +391,22 @@ trait TraitChangeModeSelfOwnToRef { // Add unsafe modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddUnsafeModifier { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - fn method() ; + fn method(); } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddUnsafeModifier { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe fn method(); } @@ -416,9 +416,9 @@ trait TraitAddUnsafeModifier { // Add extern modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddExternModifier { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(); } @@ -429,9 +429,9 @@ trait TraitAddExternModifier { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddExternModifier { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "C" fn method(); } @@ -441,9 +441,9 @@ trait TraitAddExternModifier { // Change extern "C" to extern "stdcall" #[cfg(any(cfail1,cfail4))] trait TraitChangeExternCToRustIntrinsic { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- extern "C" fn method(); } @@ -454,9 +454,9 @@ trait TraitChangeExternCToRustIntrinsic { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeExternCToRustIntrinsic { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "stdcall" fn method(); } @@ -466,10 +466,10 @@ trait TraitChangeExternCToRustIntrinsic { // Add type parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddTypeParameterToMethod { - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // --------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // --------------- // ------------------------- fn method (); @@ -481,10 +481,10 @@ trait TraitAddTypeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToMethod { - #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); @@ -495,9 +495,9 @@ trait TraitAddTypeParameterToMethod { // Add lifetime parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeParameterToMethod { - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- fn method (); } @@ -508,9 +508,9 @@ trait TraitAddLifetimeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToMethod { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method<'a>(); } @@ -524,9 +524,9 @@ trait ReferencedTrait1 { } // Add trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -537,9 +537,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -549,9 +549,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { // Add builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -562,9 +562,9 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -575,12 +575,12 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToMethodLifetimeParameter { // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- @@ -594,12 +594,12 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -611,9 +611,9 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { // Add second trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -624,9 +624,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -636,9 +636,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { // Add second builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -649,9 +649,9 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -662,12 +662,12 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- @@ -681,12 +681,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -710,9 +710,9 @@ trait TraitAddAssociatedType { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedType { #[rustc_clean(cfg="cfail3")] @@ -731,9 +731,9 @@ trait TraitAddAssociatedType { // Add trait bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToAssociatedType { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- type Associated ; @@ -749,9 +749,9 @@ trait TraitAddTraitBoundToAssociatedType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToAssociatedType { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: ReferencedTrait0; @@ -763,9 +763,9 @@ trait TraitAddTraitBoundToAssociatedType { // Add lifetime bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToAssociatedType<'a> { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- type Associated ; @@ -778,9 +778,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToAssociatedType<'a> { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: 'a; @@ -792,9 +792,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { // Add default to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddDefaultToAssociatedType { - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- type Associated ; @@ -802,14 +802,14 @@ trait TraitAddDefaultToAssociatedType { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddDefaultToAssociatedType { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated = ReferenceType0; @@ -825,9 +825,9 @@ trait TraitAddAssociatedConstant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedConstant { const Value: u32; @@ -840,9 +840,9 @@ trait TraitAddAssociatedConstant { // Add initializer to associated constant #[cfg(any(cfail1,cfail4))] trait TraitAddInitializerToAssociatedConstant { - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- const Value: u32 ; @@ -854,14 +854,14 @@ trait TraitAddInitializerToAssociatedConstant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: u32 = 1; @@ -877,9 +877,9 @@ trait TraitAddInitializerToAssociatedConstant { // Change type of associated constant #[cfg(any(cfail1,cfail4))] trait TraitChangeTypeOfAssociatedConstant { - // --------------------------------------------------------------------- + // ----------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------- + // ----------------------------------------------------------- // ------------------------- const Value: u32; @@ -896,9 +896,9 @@ trait TraitChangeTypeOfAssociatedConstant { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTypeOfAssociatedConstant { - #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: f64; @@ -916,9 +916,9 @@ trait TraitChangeTypeOfAssociatedConstant { trait TraitAddSuperTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSuperTrait : ReferencedTrait0 { } @@ -929,9 +929,9 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } trait TraitAddBuiltiBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltiBound : Send { } @@ -942,9 +942,9 @@ trait TraitAddBuiltiBound : Send { } trait TraitAddStaticLifetimeBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticLifetimeBound : 'static { } @@ -955,9 +955,9 @@ trait TraitAddStaticLifetimeBound : 'static { } trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } @@ -965,9 +965,9 @@ trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } @@ -978,9 +978,9 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } @@ -988,9 +988,9 @@ trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } @@ -1001,9 +1001,9 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } @@ -1011,9 +1011,9 @@ trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } @@ -1024,9 +1024,9 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } trait TraitAddTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToTrait { } @@ -1037,9 +1037,9 @@ trait TraitAddTypeParameterToTrait { } trait TraitAddLifetimeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToTrait<'a> { } @@ -1050,9 +1050,9 @@ trait TraitAddLifetimeParameterToTrait<'a> { } trait TraitAddTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -1063,9 +1063,9 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -1076,9 +1076,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } @@ -1089,9 +1089,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } trait TraitAddBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -1102,9 +1102,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } trait TraitAddSecondTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTypeParameterToTrait { } @@ -1115,9 +1115,9 @@ trait TraitAddSecondTypeParameterToTrait { } trait TraitAddSecondLifetimeParameterToTrait<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } @@ -1128,9 +1128,9 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -1141,9 +1141,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -1154,9 +1154,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } @@ -1167,9 +1167,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -1185,9 +1185,9 @@ struct ReferenceType1 {} trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -1198,9 +1198,9 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -1211,9 +1211,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } @@ -1224,9 +1224,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -1237,9 +1237,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } @@ -1251,9 +1251,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } @@ -1264,9 +1264,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } @@ -1277,9 +1277,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } @@ -1296,9 +1296,9 @@ mod change_return_type_of_method_indirectly_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> ReturnType; } @@ -1318,9 +1318,9 @@ mod change_method_parameter_type_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeArgType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: ArgType); } @@ -1340,9 +1340,9 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T); } @@ -1363,9 +1363,9 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameterWhere { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T) where T: Bound; } @@ -1380,9 +1380,9 @@ mod change_method_type_parameter_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBound { fn method(a: T); @@ -1399,9 +1399,9 @@ mod change_method_type_parameter_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index 3b2e18d17a96..028598244de7 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -32,9 +32,9 @@ impl ChangeMethodNameTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeMethodNameTrait { #[rustc_clean(cfg="cfail3")] @@ -43,9 +43,9 @@ pub trait ChangeMethodNameTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodNameTrait for Foo { #[rustc_clean(cfg="cfail3")] @@ -141,18 +141,18 @@ pub trait ChangeMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -179,18 +179,18 @@ pub trait RemoveMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -206,9 +206,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[cfg(any(cfail1,cfail4))] impl ChangeMethodSelfmutnessTrait for Foo { - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- fn method_name(& self) {} } @@ -224,9 +224,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfmutnessTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&mut self) {} } @@ -249,9 +249,9 @@ pub trait ChangeItemKindTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeItemKindTrait for Foo { type name = (); @@ -277,9 +277,9 @@ pub trait RemoveItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveItemTrait for Foo { type TypeName = (); @@ -304,9 +304,9 @@ pub trait AddItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddItemTrait for Foo { type TypeName = (); @@ -317,9 +317,9 @@ impl AddItemTrait for Foo { #[cfg(any(cfail1,cfail4))] pub trait ChangeHasValueTrait { - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- fn method_name() ; } @@ -330,14 +330,14 @@ impl ChangeHasValueTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeHasValueTrait { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { } } @@ -359,9 +359,9 @@ pub trait AddDefaultTrait { #[cfg(any(cfail1,cfail4))] impl AddDefaultTrait for Foo { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- fn method_name() { } } @@ -372,9 +372,9 @@ impl AddDefaultTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddDefaultTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] default fn method_name() { } } @@ -388,9 +388,9 @@ pub trait AddArgumentTrait { #[cfg(any(cfail1,cfail4))] impl AddArgumentTrait for Foo { - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- fn method_name(&self ) { } } @@ -406,9 +406,9 @@ pub trait AddArgumentTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddArgumentTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: u32) { } } @@ -422,9 +422,9 @@ pub trait ChangeArgumentTypeTrait { #[cfg(any(cfail1,cfail4))] impl ChangeArgumentTypeTrait for Foo { - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- fn method_name(&self, _x: u32 ) { } } @@ -440,9 +440,9 @@ pub trait ChangeArgumentTypeTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeArgumentTypeTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: char) { } } @@ -462,18 +462,18 @@ impl AddTypeParameterToImpl for Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTypeParameterToImpl for Bar { #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -493,9 +493,9 @@ impl ChangeSelfTypeOfImpl for u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeSelfTypeOfImpl for u64 { #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")] @@ -518,9 +518,9 @@ impl AddLifetimeBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddLifetimeBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] @@ -543,9 +543,9 @@ impl AddTraitBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTraitBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/type_defs.rs b/tests/incremental/hashes/type_defs.rs index 79398eb07fe4..206c0595d546 100644 --- a/tests/incremental/hashes/type_defs.rs +++ b/tests/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } From d59968b5f65c8b703f66913181d30d31df113d70 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 16 Jan 2024 23:23:31 +0000 Subject: [PATCH 204/297] Simplify BodyId hashing. --- compiler/rustc_ast_lowering/src/lib.rs | 6 ++-- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir/src/stable_hash_impls.rs | 7 ---- compiler/rustc_query_system/src/ich/hcx.rs | 35 ------------------- .../rustc_query_system/src/ich/impls_hir.rs | 22 ------------ .../src/ich/impls_syntax.rs | 2 ++ compiler/rustc_query_system/src/ich/mod.rs | 1 - 7 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 compiler/rustc_query_system/src/ich/impls_hir.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5387880b6e62..057fe65d0afa 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -662,9 +662,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() { self.tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); + node.hash_stable(&mut hcx, &mut stable_hasher); + // Bodies are stored out of line, so we need to pull them explicitly in the hash. + bodies.hash_stable(&mut hcx, &mut stable_hasher); let h1 = stable_hasher.finish(); let mut stable_hasher = StableHasher::new(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 309850d04d36..6773f7a4c669 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1302,7 +1302,7 @@ pub enum UnsafeSource { UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct BodyId { pub hir_id: HirId, } diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 97fa710b3549..baa1635f7313 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -12,7 +12,6 @@ use rustc_span::def_id::DefPathHash; pub trait HashStableContext: rustc_ast::HashStableContext + rustc_target::HashStableContext { - fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher); } impl ToStableHashKey for HirId { @@ -80,12 +79,6 @@ impl ToStableHashKey for ForeignItemId } } -impl HashStable for BodyId { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_body_id(*self, hasher) - } -} - // The following implementations of HashStable for `ItemId`, `TraitItemId`, and // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index eec0433ae68d..e7eb9694f473 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,10 +1,8 @@ use crate::ich; use rustc_ast as ast; -use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; use rustc_session::cstore::Untracked; @@ -23,7 +21,6 @@ pub struct StableHashingContext<'a> { // The value of `-Z incremental-ignore-spans`. // This field should only be used by `unstable_opts_incremental_ignore_span` incremental_ignore_spans: bool, - pub(super) body_resolver: BodyResolver<'a>, // Very often, we are hashing something that does not need the // `CachingSourceMapView`, so we initialize it lazily. raw_source_map: &'a SourceMap, @@ -31,26 +28,12 @@ pub struct StableHashingContext<'a> { hashing_controls: HashingControls, } -/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. -/// We could also just store a plain reference to the `hir::Crate` but we want -/// to avoid that the crate is used to get untracked access to all of the HIR. -#[derive(Clone, Copy)] -pub(super) enum BodyResolver<'tcx> { - Forbidden, - Ignore, - Traverse { - owner: hir::OwnerId, - bodies: &'tcx SortedMap>, - }, -} - impl<'a> StableHashingContext<'a> { #[inline] pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self { let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans; StableHashingContext { - body_resolver: BodyResolver::Forbidden, untracked, incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans, caching_source_map: None, @@ -59,24 +42,6 @@ impl<'a> StableHashingContext<'a> { } } - #[inline] - pub fn without_hir_bodies(&mut self, f: impl FnOnce(&mut StableHashingContext<'_>)) { - f(&mut StableHashingContext { body_resolver: BodyResolver::Ignore, ..self.clone() }); - } - - #[inline] - pub fn with_hir_bodies( - &mut self, - owner: hir::OwnerId, - bodies: &SortedMap>, - f: impl FnOnce(&mut StableHashingContext<'_>), - ) { - f(&mut StableHashingContext { - body_resolver: BodyResolver::Traverse { owner, bodies }, - ..self.clone() - }); - } - #[inline] pub fn while_hashing_spans(&mut self, hash_spans: bool, f: F) { let prev_hash_spans = self.hashing_controls.hash_spans; diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs deleted file mode 100644 index aa008d404c3e..000000000000 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! This module contains `HashStable` implementations for various HIR data -//! types in no particular order. - -use crate::ich::hcx::BodyResolver; -use crate::ich::StableHashingContext; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir as hir; - -impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { - #[inline] - fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { - let hcx = self; - match hcx.body_resolver { - BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."), - BodyResolver::Ignore => {} - BodyResolver::Traverse { owner, bodies } => { - assert_eq!(id.hir_id.owner, owner); - bodies[&id.hir_id.local_id].hash_stable(hcx, hasher); - } - } - } -} diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index d170cd36ca6a..5bd4fe04848f 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -57,6 +57,8 @@ impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> { } } +impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {} + impl<'a> HashStable> for SourceFile { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let SourceFile { diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 0a1c350b2db1..86e3ecb1eddb 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -4,7 +4,6 @@ pub use self::hcx::StableHashingContext; use rustc_span::symbol::{sym, Symbol}; mod hcx; -mod impls_hir; mod impls_syntax; pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ From 37a5464bc8e630beee4377ec7ccc0ee912291907 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 02:00:45 +0000 Subject: [PATCH 205/297] Eagerly instantiate closure ty --- compiler/rustc_hir_typeck/src/closure.rs | 146 +++++++++--------- ...re-print-generic-trim-off-verbose-2.stderr | 2 +- .../closure-print-generic-verbose-2.stderr | 2 +- .../print/closure-print-verbose.stderr | 2 +- 4 files changed, 73 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 57fdfa4ecb6e..d11198d7fd4e 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -68,12 +68,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?bound_sig, ?liberated_sig); + let parent_args = + GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id())); + + let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + // FIXME: We could probably actually just unify this further -- // instead of having a `FnSig` and a `Option`, // we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`, // similar to how `ty::GenSig` is a distinct data structure. - let coroutine_types = match closure.kind { - hir::ClosureKind::Closure => None, + let (closure_ty, coroutine_types) = match closure.kind { + hir::ClosureKind::Closure => { + // Tuple up the arguments and insert the resulting function type into + // the `closures` table. + let sig = bound_sig.map_bound(|sig| { + tcx.mk_fn_sig( + [Ty::new_tup(tcx, sig.inputs())], + sig.output(), + sig.c_variadic, + sig.unsafety, + sig.abi, + ) + }); + + debug!(?sig, ?expected_kind); + + let closure_kind_ty = match expected_kind { + Some(kind) => Ty::from_closure_kind(tcx, kind), + + // Create a type variable (for now) to represent the closure kind. + // It will be unified during the upvar inference phase (`upvar.rs`) + None => self.next_root_ty_var(TypeVariableOrigin { + // FIXME(eddyb) distinguish closure kind inference variables from the rest. + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }), + }; + + let closure_args = ty::ClosureArgs::new( + tcx, + ty::ClosureArgsParts { + parent_args, + closure_kind_ty, + closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig), + tupled_upvars_ty, + }, + ); + + (Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None) + } hir::ClosureKind::Coroutine(kind) => { let yield_ty = match kind { hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) @@ -119,74 +165,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resume type defaults to `()` if the coroutine has no argument. let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); - Some(CoroutineTypes { resume_ty, yield_ty }) - } - }; - - check_fn( - &mut FnCtxt::new(self, self.param_env, closure.def_id), - liberated_sig, - coroutine_types, - closure.fn_decl, - expr_def_id, - body, - // Closure "rust-call" ABI doesn't support unsized params - false, - ); - - let parent_args = - GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id())); - - let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::ClosureSynthetic, - span: expr_span, - }); - - match closure.kind { - hir::ClosureKind::Closure => { - assert_eq!(coroutine_types, None); - // Tuple up the arguments and insert the resulting function type into - // the `closures` table. - let sig = bound_sig.map_bound(|sig| { - tcx.mk_fn_sig( - [Ty::new_tup(tcx, sig.inputs())], - sig.output(), - sig.c_variadic, - sig.unsafety, - sig.abi, - ) - }); - - debug!(?sig, ?expected_kind); - - let closure_kind_ty = match expected_kind { - Some(kind) => Ty::from_closure_kind(tcx, kind), - - // Create a type variable (for now) to represent the closure kind. - // It will be unified during the upvar inference phase (`upvar.rs`) - None => self.next_root_ty_var(TypeVariableOrigin { - // FIXME(eddyb) distinguish closure kind inference variables from the rest. - kind: TypeVariableOriginKind::ClosureSynthetic, - span: expr_span, - }), - }; - - let closure_args = ty::ClosureArgs::new( - tcx, - ty::ClosureArgsParts { - parent_args, - closure_kind_ty, - closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig), - tupled_upvars_ty, - }, - ); - - Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args) - } - hir::ClosureKind::Coroutine(_) => { - let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else { - bug!("expected coroutine to have yield/resume types"); - }; let interior = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: body.value.span, @@ -209,9 +187,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ); - Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args) + ( + Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args), + Some(CoroutineTypes { resume_ty, yield_ty }), + ) } - } + }; + + check_fn( + &mut FnCtxt::new(self, self.param_env, closure.def_id), + liberated_sig, + coroutine_types, + closure.fn_decl, + expr_def_id, + body, + // Closure "rust-call" ABI doesn't support unsized params + false, + ); + + closure_ty } /// Given the expected type, figures out what it can about this closure we @@ -683,10 +677,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } // All `gen {}` and `async gen {}` must return unit. - hir::ClosureKind::Coroutine( - hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) - | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _), - ) => self.tcx.types.unit, + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen, + _, + )) => self.tcx.types.unit, // For async blocks, we just fall back to `_` here. // For closures/coroutines, we know nothing about the return diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index 1a13255429f0..02d75ff1228d 100644 --- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `{mod1::f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}` + found closure `{mod1::f::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr index 8553817247d5..a53676889898 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `{f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}` + found closure `{f::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr index 3d0af5eb171c..fca8f25792ac 100644 --- a/tests/ui/closures/print/closure-print-verbose.stderr +++ b/tests/ui/closures/print/closure-print-verbose.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]}` + found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?4t]}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-print-verbose.rs:10:39 | From b82d1d32b4c4a998c0a88ea7156edc2c5b4e1439 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 18:07:49 +1100 Subject: [PATCH 206/297] Inline `create_dump_file_with_basename` --- compiler/rustc_middle/src/mir/pretty.rs | 35 +++++++++---------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 239929a2c0ef..5144c9b8c13f 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -205,26 +205,6 @@ fn dump_path(tcx: TyCtxt<'_>, basename: &str, extension: &str) -> PathBuf { file_path } -/// Attempts to open the MIR dump file with the given name and extension. -fn create_dump_file_with_basename( - tcx: TyCtxt<'_>, - file_basename: &str, - extension: &str, -) -> io::Result> { - let file_path = dump_path(tcx, file_basename, extension); - if let Some(parent) = file_path.parent() { - fs::create_dir_all(parent).map_err(|e| { - io::Error::new( - e.kind(), - format!("IO error creating MIR dump directory: {parent:?}; {e}"), - ) - })?; - } - Ok(io::BufWriter::new(fs::File::create(&file_path).map_err(|e| { - io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) - })?)) -} - /// Attempts to open a file where we should dump a given MIR or other /// bit of MIR-related data. Used by `mir-dump`, but also by other /// bits of code (e.g., NLL inference) that dump graphviz data or @@ -237,11 +217,22 @@ pub fn create_dump_file<'tcx>( disambiguator: &dyn Display, body: &Body<'tcx>, ) -> io::Result> { - create_dump_file_with_basename( + let file_path = dump_path( tcx, &dump_file_basename(tcx, pass_num, pass_name, disambiguator, body), extension, - ) + ); + if let Some(parent) = file_path.parent() { + fs::create_dir_all(parent).map_err(|e| { + io::Error::new( + e.kind(), + format!("IO error creating MIR dump directory: {parent:?}; {e}"), + ) + })?; + } + Ok(io::BufWriter::new(fs::File::create(&file_path).map_err(|e| { + io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) + })?)) } /////////////////////////////////////////////////////////////////////////// From 1ec567b99aa961435ee9b825d70d1f471ac7388b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 18:14:44 +1100 Subject: [PATCH 207/297] Inline `dump_file_basename` into `dump_path` --- compiler/rustc_middle/src/mir/pretty.rs | 29 +++++++++---------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5144c9b8c13f..2cf6410990e8 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -142,15 +142,17 @@ fn dump_matched_mir_node<'tcx, F>( } } -/// Returns the file basename portion (without extension) of a filename path -/// where we should dump a MIR representation output files. -fn dump_file_basename<'tcx>( +/// Returns the path to the filename where we should dump a given MIR. +/// Also used by other bits of code (e.g., NLL inference) that dump +/// graphviz data or other things. +fn dump_path<'tcx>( tcx: TyCtxt<'tcx>, + extension: &str, pass_num: bool, pass_name: &str, disambiguator: &dyn Display, body: &Body<'tcx>, -) -> String { +) -> PathBuf { let source = body.source; let promotion_id = match source.promoted { Some(id) => format!("-{id:?}"), @@ -186,19 +188,12 @@ fn dump_file_basename<'tcx>( _ => String::new(), }; - format!( - "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}", - ) -} - -/// Returns the path to the filename where we should dump a given MIR. -/// Also used by other bits of code (e.g., NLL inference) that dump -/// graphviz data or other things. -fn dump_path(tcx: TyCtxt<'_>, basename: &str, extension: &str) -> PathBuf { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir)); - let file_name = format!("{basename}.{extension}",); + let file_name = format!( + "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}.{extension}", + ); file_path.push(&file_name); @@ -217,11 +212,7 @@ pub fn create_dump_file<'tcx>( disambiguator: &dyn Display, body: &Body<'tcx>, ) -> io::Result> { - let file_path = dump_path( - tcx, - &dump_file_basename(tcx, pass_num, pass_name, disambiguator, body), - extension, - ); + let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, body); if let Some(parent) = file_path.parent() { fs::create_dir_all(parent).map_err(|e| { io::Error::new( From 19d6f068ee75d258a5f14d609894af49943f907e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 17 Jan 2024 02:59:47 +0100 Subject: [PATCH 208/297] Don't rely on contiguous `VariantId`s outside of rustc --- Cargo.lock | 1 + compiler/rustc_pattern_analysis/Cargo.toml | 1 + .../rustc_pattern_analysis/src/constructor.rs | 11 +++-- compiler/rustc_pattern_analysis/src/lib.rs | 42 ++++++++++++++++++- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f85d523fc1bc..0df01e5e29af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4355,6 +4355,7 @@ name = "rustc_pattern_analysis" version = "0.0.0" dependencies = [ "derivative", + "rustc-hash", "rustc_apfloat", "rustc_arena", "rustc_data_structures", diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index 7cc585bea3af..1d0e1cb7e6a5 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start derivative = "2.2.0" +rustc-hash = "1.1.0" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index c1042d5b66ec..76098505b794 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -155,13 +155,13 @@ use std::iter::once; use smallvec::SmallVec; use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS}; -use rustc_index::bit_set::{BitSet, GrowableBitSet}; -use rustc_index::IndexVec; +use rustc_index::bit_set::GrowableBitSet; use self::Constructor::*; use self::MaybeInfiniteInt::*; use self::SliceKind::*; +use crate::index; use crate::usefulness::PlaceCtxt; use crate::TypeCx; @@ -804,7 +804,10 @@ pub enum ConstructorSet { Struct { empty: bool }, /// This type has the following list of constructors. If `variants` is empty and /// `non_exhaustive` is false, don't use this; use `NoConstructors` instead. - Variants { variants: IndexVec, non_exhaustive: bool }, + Variants { + variants: index::IdxContainer, + non_exhaustive: bool, + }, /// The type is `&T`. Ref, /// The type is a union. @@ -904,7 +907,7 @@ impl ConstructorSet { } } ConstructorSet::Variants { variants, non_exhaustive } => { - let mut seen_set: BitSet<_> = BitSet::new_empty(variants.len()); + let mut seen_set = index::IdxSet::new_empty(variants.len()); for idx in seen.iter().map(|c| c.as_variant().unwrap()) { seen_set.insert(idx); } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index ed10a5155084..867924180dd3 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -21,7 +21,45 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } use std::fmt; -use rustc_index::Idx; +#[cfg(feature = "rustc")] +pub mod index { + // Faster version when the indices of variants are `0..variants.len()`. + pub use rustc_index::bit_set::BitSet as IdxSet; + pub use rustc_index::Idx; + pub use rustc_index::IndexVec as IdxContainer; +} +#[cfg(not(feature = "rustc"))] +pub mod index { + // Slower version when the indices of variants are something else. + pub trait Idx: Copy + PartialEq + Eq + std::hash::Hash {} + impl Idx for T {} + + #[derive(Debug)] + pub struct IdxContainer(pub rustc_hash::FxHashMap); + impl IdxContainer { + pub fn len(&self) -> usize { + self.0.len() + } + pub fn iter_enumerated(&self) -> impl Iterator { + self.0.iter().map(|(k, v)| (*k, v)) + } + } + + #[derive(Debug)] + pub struct IdxSet(pub rustc_hash::FxHashSet); + impl IdxSet { + pub fn new_empty(_len: usize) -> Self { + Self(Default::default()) + } + pub fn contains(&self, elem: T) -> bool { + self.0.contains(&elem) + } + pub fn insert(&mut self, elem: T) { + self.0.insert(elem); + } + } +} + #[cfg(feature = "rustc")] use rustc_middle::ty::Ty; #[cfg(feature = "rustc")] @@ -50,7 +88,7 @@ pub trait TypeCx: Sized + fmt::Debug { /// Errors that can abort analysis. type Error: fmt::Debug; /// The index of an enum variant. - type VariantIdx: Clone + Idx; + type VariantIdx: Clone + index::Idx + fmt::Debug; /// A string literal type StrLit: Clone + PartialEq + fmt::Debug; /// Extra data to store in a match arm. From 7889e99b553840de211482e4c86b2a145a968432 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Wed, 17 Jan 2024 03:14:16 +0100 Subject: [PATCH 209/297] Add `PatKind::Err` --- compiler/rustc_ast/src/ast.rs | 6 +++++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/pat.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 5 +++++ compiler/rustc_hir/src/hir.rs | 7 +++++-- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/check/region.rs | 3 ++- compiler/rustc_hir_pretty/src/lib.rs | 5 +++++ compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 10 +++++++--- compiler/rustc_hir_typeck/src/mem_categorization.rs | 3 ++- compiler/rustc_hir_typeck/src/pat.rs | 7 +++++-- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 2 ++ compiler/rustc_passes/src/hir_stats.rs | 6 ++++-- src/librustdoc/clean/utils.rs | 4 +++- src/tools/clippy/clippy_lints/src/equatable_if_let.rs | 3 ++- .../clippy/clippy_lints/src/matches/match_same_arms.rs | 5 ++++- .../clippy/clippy_lints/src/unnested_or_patterns.rs | 2 +- src/tools/clippy/clippy_lints/src/utils/author.rs | 1 + src/tools/clippy/clippy_utils/src/hir_utils.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/rustfmt/src/patterns.rs | 9 ++++++--- 23 files changed, 66 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 21077c312bdc..d0d98eb3d62d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -625,7 +625,8 @@ impl Pat { | PatKind::Range(..) | PatKind::Ident(..) | PatKind::Path(..) - | PatKind::MacCall(_) => {} + | PatKind::MacCall(_) + | PatKind::Err(_) => {} } } @@ -809,6 +810,9 @@ pub enum PatKind { /// A macro pattern; pre-expansion. MacCall(P), + + /// Placeholder for a pattern that wasn't syntactically well formed in some way. + Err(ErrorGuaranteed), } /// Whether the `..` is present in a struct fields pattern. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 450555d0cb56..90677151d250 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1267,7 +1267,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { let Pat { id, kind, span, tokens } = pat.deref_mut(); vis.visit_id(id); match kind { - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 3617df931e2a..89f50d3a0a7b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -568,7 +568,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 1c405fac7e40..0af141ff99a2 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -109,6 +109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // return inner to be processed in next loop PatKind::Paren(inner) => pattern = inner, PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), + PatKind::Err(guar) => break hir::PatKind::Err(*guar), } }; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f4b424259dee..c2fd4558fd76 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1519,6 +1519,11 @@ impl<'a> State<'a> { self.pclose(); } PatKind::MacCall(m) => self.print_mac(m), + PatKind::Err(_) => { + self.popen(); + self.word("/*ERROR*/"); + self.pclose(); + } } self.ann.post(self, AnnNode::Pat(pat)) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6b347f7035a3..6d5917c7b99f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1015,7 +1015,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, + Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true, Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), @@ -1042,7 +1042,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {} + Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {} Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1205,6 +1205,9 @@ pub enum PatKind<'hir> { /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)]) /// ``` Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), + + /// A placeholder for a pattern that wasn't well formed in some way. + Err(ErrorGuaranteed), } /// A statement. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index adc090258093..116de6fb04d9 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -655,7 +655,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } - PatKind::Never | PatKind::Wild => (), + PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); walk_list!(visitor, visit_pat, slice_pattern); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 5d5a4789734a..1c0a1a695139 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -681,7 +681,8 @@ fn resolve_local<'tcx>( | PatKind::Never | PatKind::Path(_) | PatKind::Lit(_) - | PatKind::Range(_, _, _) => false, + | PatKind::Range(_, _, _) + | PatKind::Err(_) => false, } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d36e0892d19d..e76303bc6dfa 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1838,6 +1838,11 @@ impl<'a> State<'a> { self.commasep(Inconsistent, after, |s, p| s.print_pat(p)); self.word("]"); } + PatKind::Err(_) => { + self.popen(); + self.word("/*ERROR*/"); + self.pclose(); + } } self.ann.post(self, AnnNode::Pat(pat)) } diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ed3dd1e39dfc..3ecf6c5e428b 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -458,11 +458,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { needs_to_be_read = true; } } - PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => { + PatKind::Or(_) + | PatKind::Box(_) + | PatKind::Ref(..) + | PatKind::Wild + | PatKind::Err(_) => { // If the PatKind is Or, Box, or Ref, the decision is made later // as these patterns contains subpatterns - // If the PatKind is Wild, the decision is made based on the other patterns being - // examined + // If the PatKind is Wild or Err, the decision is made based on the other patterns + // being examined } } })? diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index ce3a4b4c80ce..1ce0240f7b83 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -767,7 +767,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | PatKind::Lit(..) | PatKind::Range(..) | PatKind::Never - | PatKind::Wild => { + | PatKind::Wild + | PatKind::Err(_) => { // always ok } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 95813cb68a66..fe8c36dbe069 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin }; let ty = match pat.kind { - PatKind::Wild => expected, + PatKind::Wild | PatKind::Err(_) => expected, // FIXME(never_patterns): check the type is uninhabited. If that is not possible within // typeck, do that in a later phase. PatKind::Never => expected, @@ -325,6 +325,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Ref(..) => AdjustMode::Reset, // A `_` pattern works with any expected type, so there's no need to do anything. PatKind::Wild + // A malformed pattern doesn't have an expected type, so let's just accept any type. + | PatKind::Err(_) // Bindings also work with whatever the expected type is, // and moreover if we peel references off, that will give us the wrong binding type. // Also, we can have a subpattern `binding @ pat`. @@ -754,7 +756,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Box(..) | PatKind::Ref(..) | PatKind::Lit(..) - | PatKind::Range(..) => break 'block None, + | PatKind::Range(..) + | PatKind::Err(_) => break 'block None, }, // Don't provide suggestions in other cases diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0f4528d1d5c2..39decf1faabf 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1166,7 +1166,7 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, + | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index c4987634b78b..ff7e985bdfdc 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -345,6 +345,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) }, + + hir::PatKind::Err(guar) => PatKind::Error(guar), }; Box::new(Pat { span, ty, kind }) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index ff29fc5929c7..528a52f42255 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -303,7 +303,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Ref, Lit, Range, - Slice + Slice, + Err ] ); hir_visit::walk_pat(self, p) @@ -576,7 +577,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Rest, Never, Paren, - MacCall + MacCall, + Err ] ); ast_visit::walk_pat(self, p) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 437517598ac4..b2b20c95a7e6 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -312,7 +312,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { Symbol::intern(&match p.kind { // FIXME(never_patterns): does this make sense? - PatKind::Wild | PatKind::Never | PatKind::Struct(..) => return kw::Underscore, + PatKind::Wild | PatKind::Err(_) | PatKind::Never | PatKind::Struct(..) => { + return kw::Underscore; + } PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::Or(pats) => { diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 3c4352942526..4e728d61b853 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -51,7 +51,8 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { | PatKind::Binding(..) | PatKind::Wild | PatKind::Never - | PatKind::Or(_) => false, + | PatKind::Or(_) + | PatKind::Err(_) => false, PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index c823d07e2bd3..5ca161e93096 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -11,7 +11,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, P use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; use super::MATCH_SAME_ARMS; @@ -167,6 +167,8 @@ enum NormalizedPat<'a> { /// contains everything afterwards. Note that either side, or both sides, may contain zero /// patterns. Slice(&'a [Self], Option<&'a [Self]>), + /// A placeholder for a pattern that wasn't well formed in some way. + Err(ErrorGuaranteed), } #[derive(Clone, Copy)] @@ -329,6 +331,7 @@ impl<'a> NormalizedPat<'a> { arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))), wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))), ), + PatKind::Err(guar) => Self::Err(guar), } } diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 77adcdd0e6bf..7246214f9bf8 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, // which we would want to join with other `C(p_j)`s. - Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_) + Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_) // Skip immutable refs, as grouping them saves few characters, // and almost always requires adding parens (increasing noisiness). // In the case of only two patterns, replacement adds net characters. diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 8d38b87e1d79..b26ebe5cee32 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -710,6 +710,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.slice(start, |pat| self.pat(pat)); self.slice(end, |pat| self.pat(pat)); }, + PatKind::Err(_) => kind!("Err"), } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 482eaed77d1d..979b117db256 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } e.hash(&mut self.s); }, - PatKind::Never | PatKind::Wild => {}, + PatKind::Never | PatKind::Wild | PatKind::Err(_) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index cdf8528f48a2..2e54690d123c 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1733,6 +1733,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { }, } }, + PatKind::Err(_) => true, } } diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 0fa6edaa5d78..7f5762794320 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -40,9 +40,11 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { fn is_short_pattern_inner(pat: &ast::Pat) -> bool { match pat.kind { - ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Lit(_) => { - true - } + ast::PatKind::Rest + | ast::PatKind::Never + | ast::PatKind::Wild + | ast::PatKind::Err(_) + | ast::PatKind::Lit(_) => true, ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) | ast::PatKind::MacCall(..) @@ -274,6 +276,7 @@ impl Rewrite for Pat { PatKind::Paren(ref pat) => pat .rewrite(context, shape.offset_left(1)?.sub_width(1)?) .map(|inner_pat| format!("({})", inner_pat)), + PatKind::Err(_) => None, } } } From db7125f008cfd72e8951c9a863178956e2cbacc3 Mon Sep 17 00:00:00 2001 From: Robert Grosse <999674+Storyyeller@users.noreply.github.com> Date: Tue, 16 Jan 2024 20:48:22 -0800 Subject: [PATCH 210/297] Fix typo in comments (in_place_collect) --- library/alloc/src/vec/in_place_collect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 0a2280545dac..ec5f32539f2c 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -9,7 +9,7 @@ //! or [`BinaryHeap`], the adapters guarantee to consume enough items per step to make room //! for the results (represented by [`InPlaceIterable`]), provide transitive access to `source` //! (via [`SourceIter`]) and thus the underlying allocation. -//! And finally there are alignment and size constriants to consider, this is currently ensured via +//! And finally there are alignment and size constraints to consider, this is currently ensured via //! const eval instead of trait bounds in the specialized [`SpecFromIter`] implementation. //! //! [`BinaryHeap`]: crate::collections::BinaryHeap From a87034c2977369c8e7670dbe477e3196c45e4615 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 7 Dec 2023 14:16:11 +0000 Subject: [PATCH 211/297] tests: add sanity-check assembly test for every target Adds a basic assembly test checking that each target can produce assembly and update the target tier policy to require this. Signed-off-by: David Wood --- .../spec/targets/asmjs_unknown_emscripten.rs | 7 - src/doc/rustc/src/target-tier-policy.md | 2 + src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 1 + src/tools/tidy/src/target_policy.rs | 52 ++ tests/assembly/targets/targets-elf.rs | 633 ++++++++++++++++++ tests/assembly/targets/targets-nvptx.rs | 21 + tests/assembly/targets/targets-pe.rs | 93 +++ 8 files changed, 803 insertions(+), 7 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs create mode 100644 src/tools/tidy/src/target_policy.rs create mode 100644 tests/assembly/targets/targets-elf.rs create mode 100644 tests/assembly/targets/targets-nvptx.rs create mode 100644 tests/assembly/targets/targets-pe.rs diff --git a/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs deleted file mode 100644 index e4768c67af55..000000000000 --- a/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::spec::{targets::wasm32_unknown_emscripten, LinkerFlavor, Target}; - -pub fn target() -> Target { - let mut target = wasm32_unknown_emscripten::target(); - target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]); - target -} diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 95932db14e1f..48b58f6f06ad 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -246,6 +246,8 @@ approved by the appropriate team for that shared code before acceptance. introducing unconditional uses of features that another variation of the target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target. +- Tier 3 targets must be able to produce assembly using at least one of + rustc's supported backends from any host target. If a tier 3 target stops meeting these requirements, or the target maintainers no longer have interest or time, or the target shows no signs of activity and diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index eb0a2fda290d..951499870334 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -70,6 +70,7 @@ pub mod pal; pub mod rustdoc_css_themes; pub mod rustdoc_gui_tests; pub mod style; +pub mod target_policy; pub mod target_specific_tests; pub mod tests_placement; pub mod ui_tests; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 9f92b8995b79..a9340c40f443 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -109,6 +109,7 @@ fn main() { // Checks that only make sense for the compiler. check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose); check!(fluent_alphabetical, &compiler_path, bless); + check!(target_policy, &root_path); // Checks that only make sense for the std libs. check!(pal, &library_path); diff --git a/src/tools/tidy/src/target_policy.rs b/src/tools/tidy/src/target_policy.rs new file mode 100644 index 000000000000..ca6590d1502a --- /dev/null +++ b/src/tools/tidy/src/target_policy.rs @@ -0,0 +1,52 @@ +//! Tests for target tier policy compliance. +//! +//! As of writing, only checks that sanity-check assembly test for targets doesn't miss any targets. + +use crate::walk::{filter_not_rust, walk}; +use std::{collections::HashSet, path::Path}; + +const TARGET_DEFINITIONS_PATH: &str = "compiler/rustc_target/src/spec/targets/"; +const ASSEMBLY_TEST_PATH: &str = "tests/assembly/targets/"; +const REVISION_LINE_START: &str = "// revisions: "; +const EXCEPTIONS: &[&str] = &[ + // FIXME: disabled since it fails on CI saying the csky component is missing + "csky_unknown_linux_gnuabiv2", + "csky_unknown_linux_gnuabiv2hf", +]; + +pub fn check(root_path: &Path, bad: &mut bool) { + let mut targets_to_find = HashSet::new(); + + let definitions_path = root_path.join(TARGET_DEFINITIONS_PATH); + for defn in ignore::WalkBuilder::new(&definitions_path) + .max_depth(Some(1)) + .filter_entry(|e| !filter_not_rust(e.path())) + .build() + { + let defn = defn.unwrap(); + // Skip directory itself. + if defn.path() == definitions_path { + continue; + } + + let path = defn.path(); + let target_name = path.file_stem().unwrap().to_string_lossy().into_owned(); + let _ = targets_to_find.insert(target_name); + } + + walk(&root_path.join(ASSEMBLY_TEST_PATH), |_, _| false, &mut |_, contents| { + for line in contents.lines() { + let Some(_) = line.find(REVISION_LINE_START) else { + continue; + }; + let (_, target_name) = line.split_at(REVISION_LINE_START.len()); + targets_to_find.remove(target_name); + } + }); + + for target in targets_to_find { + if !EXCEPTIONS.contains(&target.as_str()) { + tidy_error!(bad, "{ASSEMBLY_TEST_PATH}: missing assembly test for {target}") + } + } +} diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs new file mode 100644 index 000000000000..72a35f38ecad --- /dev/null +++ b/tests/assembly/targets/targets-elf.rs @@ -0,0 +1,633 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: aarch64_apple_darwin +// [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin +// [aarch64_apple_darwin] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios +// [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios +// [aarch64_apple_ios] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios_macabi +// [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi +// [aarch64_apple_ios_macabi] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios_sim +// [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim +// [aarch64_apple_ios_sim] needs-llvm-components: aarch64 +// revisions: aarch64_apple_tvos +// [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos +// [aarch64_apple_tvos] needs-llvm-components: aarch64 +// revisions: aarch64_apple_tvos_sim +// [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim +// [aarch64_apple_tvos_sim] needs-llvm-components: aarch64 +// revisions: aarch64_apple_watchos +// [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos +// [aarch64_apple_watchos] needs-llvm-components: aarch64 +// revisions: aarch64_apple_watchos_sim +// [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim +// [aarch64_apple_watchos_sim] needs-llvm-components: aarch64 +// revisions: aarch64_be_unknown_linux_gnu +// [aarch64_be_unknown_linux_gnu] compile-flags: --target aarch64_be-unknown-linux-gnu +// [aarch64_be_unknown_linux_gnu] needs-llvm-components: aarch64 +// revisions: aarch64_be_unknown_linux_gnu_ilp32 +// [aarch64_be_unknown_linux_gnu_ilp32] compile-flags: --target aarch64_be-unknown-linux-gnu_ilp32 +// [aarch64_be_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64 +// revisions: aarch64_be_unknown_netbsd +// [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd +// [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64 +// revisions: aarch64_fuchsia +// [aarch64_fuchsia] compile-flags: --target aarch64-fuchsia +// [aarch64_fuchsia] needs-llvm-components: aarch64 +// revisions: aarch64_kmc_solid_asp3 +// [aarch64_kmc_solid_asp3] compile-flags: --target aarch64-kmc-solid_asp3 +// [aarch64_kmc_solid_asp3] needs-llvm-components: aarch64 +// revisions: aarch64_linux_android +// [aarch64_linux_android] compile-flags: --target aarch64-linux-android +// [aarch64_linux_android] needs-llvm-components: aarch64 +// revisions: aarch64_nintendo_switch_freestanding +// [aarch64_nintendo_switch_freestanding] compile-flags: --target aarch64-nintendo-switch-freestanding +// [aarch64_nintendo_switch_freestanding] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_freebsd +// [aarch64_unknown_freebsd] compile-flags: --target aarch64-unknown-freebsd +// [aarch64_unknown_freebsd] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_fuchsia +// [aarch64_unknown_fuchsia] compile-flags: --target aarch64-unknown-fuchsia +// [aarch64_unknown_fuchsia] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_hermit +// [aarch64_unknown_hermit] compile-flags: --target aarch64-unknown-hermit +// [aarch64_unknown_hermit] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_illumos +// [aarch64_unknown_illumos] compile-flags: --target aarch64-unknown-illumos +// [aarch64_unknown_illumos] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_gnu +// [aarch64_unknown_linux_gnu] compile-flags: --target aarch64-unknown-linux-gnu +// [aarch64_unknown_linux_gnu] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_gnu_ilp32 +// [aarch64_unknown_linux_gnu_ilp32] compile-flags: --target aarch64-unknown-linux-gnu_ilp32 +// [aarch64_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_musl +// [aarch64_unknown_linux_musl] compile-flags: --target aarch64-unknown-linux-musl +// [aarch64_unknown_linux_musl] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_ohos +// [aarch64_unknown_linux_ohos] compile-flags: --target aarch64-unknown-linux-ohos +// [aarch64_unknown_linux_ohos] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_netbsd +// [aarch64_unknown_netbsd] compile-flags: --target aarch64-unknown-netbsd +// [aarch64_unknown_netbsd] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_none +// [aarch64_unknown_none] compile-flags: --target aarch64-unknown-none +// [aarch64_unknown_none] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_none_softfloat +// [aarch64_unknown_none_softfloat] compile-flags: --target aarch64-unknown-none-softfloat +// [aarch64_unknown_none_softfloat] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_nto_qnx_710 +// [aarch64_unknown_nto_qnx_710] compile-flags: --target aarch64-unknown-nto-qnx710 +// [aarch64_unknown_nto_qnx_710] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_openbsd +// [aarch64_unknown_openbsd] compile-flags: --target aarch64-unknown-openbsd +// [aarch64_unknown_openbsd] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_redox +// [aarch64_unknown_redox] compile-flags: --target aarch64-unknown-redox +// [aarch64_unknown_redox] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_teeos +// [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos +// [aarch64_unknown_teeos] needs-llvm-components: aarch64 +// revisions: aarch64_wrs_vxworks +// [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks +// [aarch64_wrs_vxworks] needs-llvm-components: aarch64 +// revisions: arm64_32_apple_watchos +// [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos +// [arm64_32_apple_watchos] needs-llvm-components: aarch64 +// revisions: arm64e_apple_darwin +// [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin +// [arm64e_apple_darwin] needs-llvm-components: aarch64 +// revisions: arm64e_apple_ios +// [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios +// [arm64e_apple_ios] needs-llvm-components: aarch64 +// revisions: arm_linux_androideabi +// [arm_linux_androideabi] compile-flags: --target arm-linux-androideabi +// [arm_linux_androideabi] needs-llvm-components: arm +// revisions: arm_unknown_linux_gnueabi +// [arm_unknown_linux_gnueabi] compile-flags: --target arm-unknown-linux-gnueabi +// [arm_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: arm_unknown_linux_gnueabihf +// [arm_unknown_linux_gnueabihf] compile-flags: --target arm-unknown-linux-gnueabihf +// [arm_unknown_linux_gnueabihf] needs-llvm-components: arm +// revisions: arm_unknown_linux_musleabi +// [arm_unknown_linux_musleabi] compile-flags: --target arm-unknown-linux-musleabi +// [arm_unknown_linux_musleabi] needs-llvm-components: arm +// revisions: arm_unknown_linux_musleabihf +// [arm_unknown_linux_musleabihf] compile-flags: --target arm-unknown-linux-musleabihf +// [arm_unknown_linux_musleabihf] needs-llvm-components: arm +// revisions: armeb_unknown_linux_gnueabi +// [armeb_unknown_linux_gnueabi] compile-flags: --target armeb-unknown-linux-gnueabi +// [armeb_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armebv7r_none_eabi +// [armebv7r_none_eabi] compile-flags: --target armebv7r-none-eabi +// [armebv7r_none_eabi] needs-llvm-components: arm +// revisions: armebv7r_none_eabihf +// [armebv7r_none_eabihf] compile-flags: --target armebv7r-none-eabihf +// [armebv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv4t_none_eabi +// [armv4t_none_eabi] compile-flags: --target armv4t-none-eabi +// [armv4t_none_eabi] needs-llvm-components: arm +// revisions: armv4t_unknown_linux_gnueabi +// [armv4t_unknown_linux_gnueabi] compile-flags: --target armv4t-unknown-linux-gnueabi +// [armv4t_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armv5te_none_eabi +// [armv5te_none_eabi] compile-flags: --target armv5te-none-eabi +// [armv5te_none_eabi] needs-llvm-components: arm +// revisions: armv5te_unknown_linux_gnueabi +// [armv5te_unknown_linux_gnueabi] compile-flags: --target armv5te-unknown-linux-gnueabi +// [armv5te_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armv5te_unknown_linux_musleabi +// [armv5te_unknown_linux_musleabi] compile-flags: --target armv5te-unknown-linux-musleabi +// [armv5te_unknown_linux_musleabi] needs-llvm-components: arm +// revisions: armv5te_unknown_linux_uclibceabi +// [armv5te_unknown_linux_uclibceabi] compile-flags: --target armv5te-unknown-linux-uclibceabi +// [armv5te_unknown_linux_uclibceabi] needs-llvm-components: arm +// revisions: armv6_unknown_freebsd +// [armv6_unknown_freebsd] compile-flags: --target armv6-unknown-freebsd +// [armv6_unknown_freebsd] needs-llvm-components: arm +// revisions: armv6_unknown_netbsd_eabihf +// [armv6_unknown_netbsd_eabihf] compile-flags: --target armv6-unknown-netbsd-eabihf +// [armv6_unknown_netbsd_eabihf] needs-llvm-components: arm +// revisions: armv6k_nintendo_3ds +// [armv6k_nintendo_3ds] compile-flags: --target armv6k-nintendo-3ds +// [armv6k_nintendo_3ds] needs-llvm-components: arm +// revisions: armv7_linux_androideabi +// [armv7_linux_androideabi] compile-flags: --target armv7-linux-androideabi +// [armv7_linux_androideabi] needs-llvm-components: arm +// revisions: armv7_sony_vita_newlibeabihf +// [armv7_sony_vita_newlibeabihf] compile-flags: --target armv7-sony-vita-newlibeabihf +// [armv7_sony_vita_newlibeabihf] needs-llvm-components: arm +// revisions: armv7_unknown_freebsd +// [armv7_unknown_freebsd] compile-flags: --target armv7-unknown-freebsd +// [armv7_unknown_freebsd] needs-llvm-components: arm +// revisions: armv7_unknown_linux_gnueabi +// [armv7_unknown_linux_gnueabi] compile-flags: --target armv7-unknown-linux-gnueabi +// [armv7_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armv7_unknown_linux_gnueabihf +// [armv7_unknown_linux_gnueabihf] compile-flags: --target armv7-unknown-linux-gnueabihf +// [armv7_unknown_linux_gnueabihf] needs-llvm-components: arm +// revisions: armv7_unknown_linux_musleabi +// [armv7_unknown_linux_musleabi] compile-flags: --target armv7-unknown-linux-musleabi +// [armv7_unknown_linux_musleabi] needs-llvm-components: arm +// revisions: armv7_unknown_linux_musleabihf +// [armv7_unknown_linux_musleabihf] compile-flags: --target armv7-unknown-linux-musleabihf +// [armv7_unknown_linux_musleabihf] needs-llvm-components: arm +// revisions: armv7_unknown_linux_ohos +// [armv7_unknown_linux_ohos] compile-flags: --target armv7-unknown-linux-ohos +// [armv7_unknown_linux_ohos] needs-llvm-components: arm +// revisions: armv7_unknown_linux_uclibceabi +// [armv7_unknown_linux_uclibceabi] compile-flags: --target armv7-unknown-linux-uclibceabi +// [armv7_unknown_linux_uclibceabi] needs-llvm-components: arm +// revisions: armv7_unknown_linux_uclibceabihf +// [armv7_unknown_linux_uclibceabihf] compile-flags: --target armv7-unknown-linux-uclibceabihf +// [armv7_unknown_linux_uclibceabihf] needs-llvm-components: arm +// revisions: armv7_unknown_netbsd_eabihf +// [armv7_unknown_netbsd_eabihf] compile-flags: --target armv7-unknown-netbsd-eabihf +// [armv7_unknown_netbsd_eabihf] needs-llvm-components: arm +// revisions: armv7_wrs_vxworks_eabihf +// [armv7_wrs_vxworks_eabihf] compile-flags: --target armv7-wrs-vxworks-eabihf +// [armv7_wrs_vxworks_eabihf] needs-llvm-components: arm +// revisions: armv7a_kmc_solid_asp3_eabi +// [armv7a_kmc_solid_asp3_eabi] compile-flags: --target armv7a-kmc-solid_asp3-eabi +// [armv7a_kmc_solid_asp3_eabi] needs-llvm-components: arm +// revisions: armv7a_kmc_solid_asp3_eabihf +// [armv7a_kmc_solid_asp3_eabihf] compile-flags: --target armv7a-kmc-solid_asp3-eabihf +// [armv7a_kmc_solid_asp3_eabihf] needs-llvm-components: arm +// revisions: armv7a_none_eabi +// [armv7a_none_eabi] compile-flags: --target armv7a-none-eabi +// [armv7a_none_eabi] needs-llvm-components: arm +// revisions: armv7a_none_eabihf +// [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf +// [armv7a_none_eabihf] needs-llvm-components: arm +// revisions: armv7k_apple_watchos +// [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos +// [armv7k_apple_watchos] needs-llvm-components: arm +// revisions: armv7r_none_eabi +// [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi +// [armv7r_none_eabi] needs-llvm-components: arm +// revisions: armv7r_none_eabihf +// [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf +// [armv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv7s_apple_ios +// [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios +// [armv7s_apple_ios] needs-llvm-components: arm +// FIXME: disabled since it fails on CI saying the csky component is missing +/* + revisions: csky_unknown_linux_gnuabiv2 + [csky_unknown_linux_gnuabiv2] compile-flags: --target csky-unknown-linux-gnuabiv2 + [csky_unknown_linux_gnuabiv2] needs-llvm-components: csky + revisions: csky_unknown_linux_gnuabiv2hf + [csky_unknown_linux_gnuabiv2hf] compile-flags: --target csky-unknown-linux-gnuabiv2hf + [csky_unknown_linux_gnuabiv2hf] needs-llvm-components: csky +*/ +// revisions: hexagon_unknown_linux_musl +// [hexagon_unknown_linux_musl] compile-flags: --target hexagon-unknown-linux-musl +// [hexagon_unknown_linux_musl] needs-llvm-components: hexagon +// revisions: hexagon_unknown_none_elf +// [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf +// [hexagon_unknown_none_elf] needs-llvm-components: hexagon +// revisions: i386_apple_ios +// [i386_apple_ios] compile-flags: --target i386-apple-ios +// [i386_apple_ios] needs-llvm-components: x86 +// revisions: i586_pc_nto_qnx700 +// [i586_pc_nto_qnx700] compile-flags: --target i586-pc-nto-qnx700 +// [i586_pc_nto_qnx700] needs-llvm-components: x86 +// revisions: i586_unknown_linux_gnu +// [i586_unknown_linux_gnu] compile-flags: --target i586-unknown-linux-gnu +// [i586_unknown_linux_gnu] needs-llvm-components: x86 +// revisions: i586_unknown_linux_musl +// [i586_unknown_linux_musl] compile-flags: --target i586-unknown-linux-musl +// [i586_unknown_linux_musl] needs-llvm-components: x86 +// revisions: i586_unknown_netbsd +// [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd +// [i586_unknown_netbsd] needs-llvm-components: x86 +// revisions: i686_apple_darwin +// [i686_apple_darwin] compile-flags: --target i686-apple-darwin +// [i686_apple_darwin] needs-llvm-components: x86 +// revisions: i686_linux_android +// [i686_linux_android] compile-flags: --target i686-linux-android +// [i686_linux_android] needs-llvm-components: x86 +// revisions: i686_unknown_freebsd +// [i686_unknown_freebsd] compile-flags: --target i686-unknown-freebsd +// [i686_unknown_freebsd] needs-llvm-components: x86 +// revisions: i686_unknown_haiku +// [i686_unknown_haiku] compile-flags: --target i686-unknown-haiku +// [i686_unknown_haiku] needs-llvm-components: x86 +// revisions: i686_unknown_hurd_gnu +// [i686_unknown_hurd_gnu] compile-flags: --target i686-unknown-hurd-gnu +// [i686_unknown_hurd_gnu] needs-llvm-components: x86 +// revisions: i686_unknown_linux_gnu +// [i686_unknown_linux_gnu] compile-flags: --target i686-unknown-linux-gnu +// [i686_unknown_linux_gnu] needs-llvm-components: x86 +// revisions: i686_unknown_linux_musl +// [i686_unknown_linux_musl] compile-flags: --target i686-unknown-linux-musl +// [i686_unknown_linux_musl] needs-llvm-components: x86 +// revisions: i686_unknown_netbsd +// [i686_unknown_netbsd] compile-flags: --target i686-unknown-netbsd +// [i686_unknown_netbsd] needs-llvm-components: x86 +// revisions: i686_unknown_openbsd +// [i686_unknown_openbsd] compile-flags: --target i686-unknown-openbsd +// [i686_unknown_openbsd] needs-llvm-components: x86 +// revisions: i686_wrs_vxworks +// [i686_wrs_vxworks] compile-flags: --target i686-wrs-vxworks +// [i686_wrs_vxworks] needs-llvm-components: x86 +// revisions: loongarch64_unknown_linux_gnu +// [loongarch64_unknown_linux_gnu] compile-flags: --target loongarch64-unknown-linux-gnu +// [loongarch64_unknown_linux_gnu] needs-llvm-components: loongarch +// revisions: loongarch64_unknown_none +// [loongarch64_unknown_none] compile-flags: --target loongarch64-unknown-none +// [loongarch64_unknown_none] needs-llvm-components: loongarch +// revisions: loongarch64_unknown_none_softfloat +// [loongarch64_unknown_none_softfloat] compile-flags: --target loongarch64-unknown-none-softfloat +// [loongarch64_unknown_none_softfloat] needs-llvm-components: loongarch +// revisions: m68k_unknown_linux_gnu +// [m68k_unknown_linux_gnu] compile-flags: --target m68k-unknown-linux-gnu +// [m68k_unknown_linux_gnu] needs-llvm-components: m68k +// revisions: mips64_openwrt_linux_musl +// [mips64_openwrt_linux_musl] compile-flags: --target mips64-openwrt-linux-musl +// [mips64_openwrt_linux_musl] needs-llvm-components: mips +// revisions: mips64_unknown_linux_gnuabi64 +// [mips64_unknown_linux_gnuabi64] compile-flags: --target mips64-unknown-linux-gnuabi64 +// [mips64_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: mips64_unknown_linux_muslabi64 +// [mips64_unknown_linux_muslabi64] compile-flags: --target mips64-unknown-linux-muslabi64 +// [mips64_unknown_linux_muslabi64] needs-llvm-components: mips +// revisions: mips64el_unknown_linux_gnuabi64 +// [mips64el_unknown_linux_gnuabi64] compile-flags: --target mips64el-unknown-linux-gnuabi64 +// [mips64el_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: mips64el_unknown_linux_muslabi64 +// [mips64el_unknown_linux_muslabi64] compile-flags: --target mips64el-unknown-linux-muslabi64 +// [mips64el_unknown_linux_muslabi64] needs-llvm-components: mips +// revisions: mips_unknown_linux_gnu +// [mips_unknown_linux_gnu] compile-flags: --target mips-unknown-linux-gnu +// [mips_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mips_unknown_linux_musl +// [mips_unknown_linux_musl] compile-flags: --target mips-unknown-linux-musl +// [mips_unknown_linux_musl] needs-llvm-components: mips +// revisions: mips_unknown_linux_uclibc +// [mips_unknown_linux_uclibc] compile-flags: --target mips-unknown-linux-uclibc +// [mips_unknown_linux_uclibc] needs-llvm-components: mips +// revisions: mipsel_sony_psp +// [mipsel_sony_psp] compile-flags: --target mipsel-sony-psp +// [mipsel_sony_psp] needs-llvm-components: mips +// revisions: mipsel_sony_psx +// [mipsel_sony_psx] compile-flags: --target mipsel-sony-psx +// [mipsel_sony_psx] needs-llvm-components: mips +// revisions: mipsel_unknown_linux_gnu +// [mipsel_unknown_linux_gnu] compile-flags: --target mipsel-unknown-linux-gnu +// [mipsel_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mipsel_unknown_linux_musl +// [mipsel_unknown_linux_musl] compile-flags: --target mipsel-unknown-linux-musl +// [mipsel_unknown_linux_musl] needs-llvm-components: mips +// revisions: mipsel_unknown_linux_uclibc +// [mipsel_unknown_linux_uclibc] compile-flags: --target mipsel-unknown-linux-uclibc +// [mipsel_unknown_linux_uclibc] needs-llvm-components: mips +// revisions: mipsel_unknown_netbsd +// [mipsel_unknown_netbsd] compile-flags: --target mipsel-unknown-netbsd +// [mipsel_unknown_netbsd] needs-llvm-components: mips +// revisions: mipsel_unknown_none +// [mipsel_unknown_none] compile-flags: --target mipsel-unknown-none +// [mipsel_unknown_none] needs-llvm-components: mips +// revisions: mipsisa32r6_unknown_linux_gnu +// [mipsisa32r6_unknown_linux_gnu] compile-flags: --target mipsisa32r6-unknown-linux-gnu +// [mipsisa32r6_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mipsisa32r6el_unknown_linux_gnu +// [mipsisa32r6el_unknown_linux_gnu] compile-flags: --target mipsisa32r6el-unknown-linux-gnu +// [mipsisa32r6el_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mipsisa64r6_unknown_linux_gnuabi64 +// [mipsisa64r6_unknown_linux_gnuabi64] compile-flags: --target mipsisa64r6-unknown-linux-gnuabi64 +// [mipsisa64r6_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: mipsisa64r6el_unknown_linux_gnuabi64 +// [mipsisa64r6el_unknown_linux_gnuabi64] compile-flags: --target mipsisa64r6el-unknown-linux-gnuabi64 +// [mipsisa64r6el_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: msp430_none_elf +// [msp430_none_elf] compile-flags: --target msp430-none-elf +// [msp430_none_elf] needs-llvm-components: msp430 +// revisions: powerpc64_unknown_freebsd +// [powerpc64_unknown_freebsd] compile-flags: --target powerpc64-unknown-freebsd +// [powerpc64_unknown_freebsd] needs-llvm-components: powerpc +// revisions: powerpc64_unknown_linux_gnu +// [powerpc64_unknown_linux_gnu] compile-flags: --target powerpc64-unknown-linux-gnu +// [powerpc64_unknown_linux_gnu] needs-llvm-components: powerpc +// revisions: powerpc64_unknown_linux_musl +// [powerpc64_unknown_linux_musl] compile-flags: --target powerpc64-unknown-linux-musl +// [powerpc64_unknown_linux_musl] needs-llvm-components: powerpc +// revisions: powerpc64_unknown_openbsd +// [powerpc64_unknown_openbsd] compile-flags: --target powerpc64-unknown-openbsd +// [powerpc64_unknown_openbsd] needs-llvm-components: powerpc +// revisions: powerpc64_wrs_vxworks +// [powerpc64_wrs_vxworks] compile-flags: --target powerpc64-wrs-vxworks +// [powerpc64_wrs_vxworks] needs-llvm-components: powerpc +// revisions: powerpc64le_unknown_freebsd +// [powerpc64le_unknown_freebsd] compile-flags: --target powerpc64le-unknown-freebsd +// [powerpc64le_unknown_freebsd] needs-llvm-components: powerpc +// revisions: powerpc64le_unknown_linux_gnu +// [powerpc64le_unknown_linux_gnu] compile-flags: --target powerpc64le-unknown-linux-gnu +// [powerpc64le_unknown_linux_gnu] needs-llvm-components: powerpc +// revisions: powerpc64le_unknown_linux_musl +// [powerpc64le_unknown_linux_musl] compile-flags: --target powerpc64le-unknown-linux-musl +// [powerpc64le_unknown_linux_musl] needs-llvm-components: powerpc +// revisions: powerpc_unknown_freebsd +// [powerpc_unknown_freebsd] compile-flags: --target powerpc-unknown-freebsd +// [powerpc_unknown_freebsd] needs-llvm-components: powerpc +// revisions: powerpc_unknown_linux_gnu +// [powerpc_unknown_linux_gnu] compile-flags: --target powerpc-unknown-linux-gnu +// [powerpc_unknown_linux_gnu] needs-llvm-components: powerpc +// revisions: powerpc_unknown_linux_gnuspe +// [powerpc_unknown_linux_gnuspe] compile-flags: --target powerpc-unknown-linux-gnuspe +// [powerpc_unknown_linux_gnuspe] needs-llvm-components: powerpc +// revisions: powerpc_unknown_linux_musl +// [powerpc_unknown_linux_musl] compile-flags: --target powerpc-unknown-linux-musl +// [powerpc_unknown_linux_musl] needs-llvm-components: powerpc +// revisions: powerpc_unknown_netbsd +// [powerpc_unknown_netbsd] compile-flags: --target powerpc-unknown-netbsd +// [powerpc_unknown_netbsd] needs-llvm-components: powerpc +// revisions: powerpc_unknown_openbsd +// [powerpc_unknown_openbsd] compile-flags: --target powerpc-unknown-openbsd +// [powerpc_unknown_openbsd] needs-llvm-components: powerpc +// revisions: powerpc_wrs_vxworks +// [powerpc_wrs_vxworks] compile-flags: --target powerpc-wrs-vxworks +// [powerpc_wrs_vxworks] needs-llvm-components: powerpc +// revisions: powerpc_wrs_vxworks_spe +// [powerpc_wrs_vxworks_spe] compile-flags: --target powerpc-wrs-vxworks-spe +// [powerpc_wrs_vxworks_spe] needs-llvm-components: powerpc +// revisions: riscv32gc_unknown_linux_gnu +// [riscv32gc_unknown_linux_gnu] compile-flags: --target riscv32gc-unknown-linux-gnu +// [riscv32gc_unknown_linux_gnu] needs-llvm-components: riscv +// revisions: riscv32gc_unknown_linux_musl +// [riscv32gc_unknown_linux_musl] compile-flags: --target riscv32gc-unknown-linux-musl +// [riscv32gc_unknown_linux_musl] needs-llvm-components: riscv +// revisions: riscv32i_unknown_none_elf +// [riscv32i_unknown_none_elf] compile-flags: --target riscv32i-unknown-none-elf +// [riscv32i_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32im_unknown_none_elf +// [riscv32im_unknown_none_elf] compile-flags: --target riscv32im-unknown-none-elf +// [riscv32im_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32imac_esp_espidf +// [riscv32imac_esp_espidf] compile-flags: --target riscv32imac-esp-espidf +// [riscv32imac_esp_espidf] needs-llvm-components: riscv +// revisions: riscv32imac_unknown_none_elf +// [riscv32imac_unknown_none_elf] compile-flags: --target riscv32imac-unknown-none-elf +// [riscv32imac_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32imac_unknown_xous_elf +// [riscv32imac_unknown_xous_elf] compile-flags: --target riscv32imac-unknown-xous-elf +// [riscv32imac_unknown_xous_elf] needs-llvm-components: riscv +// revisions: riscv32imafc_unknown_none_elf +// [riscv32imafc_unknown_none_elf] compile-flags: --target riscv32imafc-unknown-none-elf +// [riscv32imafc_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32imafc_esp_espidf +// [riscv32imafc_esp_espidf] compile-flags: --target riscv32imafc-esp-espidf +// [riscv32imafc_esp_espidf] needs-llvm-components: riscv +// revisions: riscv32imc_esp_espidf +// [riscv32imc_esp_espidf] compile-flags: --target riscv32imc-esp-espidf +// [riscv32imc_esp_espidf] needs-llvm-components: riscv +// revisions: riscv32imc_unknown_none_elf +// [riscv32imc_unknown_none_elf] compile-flags: --target riscv32imc-unknown-none-elf +// [riscv32imc_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv64_linux_android +// [riscv64_linux_android] compile-flags: --target riscv64-linux-android +// [riscv64_linux_android] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_freebsd +// [riscv64gc_unknown_freebsd] compile-flags: --target riscv64gc-unknown-freebsd +// [riscv64gc_unknown_freebsd] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_fuchsia +// [riscv64gc_unknown_fuchsia] compile-flags: --target riscv64gc-unknown-fuchsia +// [riscv64gc_unknown_fuchsia] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_hermit +// [riscv64gc_unknown_hermit] compile-flags: --target riscv64gc-unknown-hermit +// [riscv64gc_unknown_hermit] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_linux_gnu +// [riscv64gc_unknown_linux_gnu] compile-flags: --target riscv64gc-unknown-linux-gnu +// [riscv64gc_unknown_linux_gnu] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_linux_musl +// [riscv64gc_unknown_linux_musl] compile-flags: --target riscv64gc-unknown-linux-musl +// [riscv64gc_unknown_linux_musl] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_netbsd +// [riscv64gc_unknown_netbsd] compile-flags: --target riscv64gc-unknown-netbsd +// [riscv64gc_unknown_netbsd] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_none_elf +// [riscv64gc_unknown_none_elf] compile-flags: --target riscv64gc-unknown-none-elf +// [riscv64gc_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_openbsd +// [riscv64gc_unknown_openbsd] compile-flags: --target riscv64gc-unknown-openbsd +// [riscv64gc_unknown_openbsd] needs-llvm-components: riscv +// revisions: riscv64imac_unknown_none_elf +// [riscv64imac_unknown_none_elf] compile-flags: --target riscv64imac-unknown-none-elf +// [riscv64imac_unknown_none_elf] needs-llvm-components: riscv +// revisions: s390x_unknown_linux_gnu +// [s390x_unknown_linux_gnu] compile-flags: --target s390x-unknown-linux-gnu +// [s390x_unknown_linux_gnu] needs-llvm-components: systemz +// revisions: s390x_unknown_linux_musl +// [s390x_unknown_linux_musl] compile-flags: --target s390x-unknown-linux-musl +// [s390x_unknown_linux_musl] needs-llvm-components: systemz +// revisions: sparc64_unknown_linux_gnu +// [sparc64_unknown_linux_gnu] compile-flags: --target sparc64-unknown-linux-gnu +// [sparc64_unknown_linux_gnu] needs-llvm-components: sparc +// revisions: sparc64_unknown_netbsd +// [sparc64_unknown_netbsd] compile-flags: --target sparc64-unknown-netbsd +// [sparc64_unknown_netbsd] needs-llvm-components: sparc +// revisions: sparc64_unknown_openbsd +// [sparc64_unknown_openbsd] compile-flags: --target sparc64-unknown-openbsd +// [sparc64_unknown_openbsd] needs-llvm-components: sparc +// revisions: sparc_unknown_linux_gnu +// [sparc_unknown_linux_gnu] compile-flags: --target sparc-unknown-linux-gnu +// [sparc_unknown_linux_gnu] needs-llvm-components: sparc +// revisions: sparc_unknown_none_elf +// [sparc_unknown_none_elf] compile-flags: --target sparc-unknown-none-elf +// [sparc_unknown_none_elf] needs-llvm-components: sparc +// revisions: sparcv9_sun_solaris +// [sparcv9_sun_solaris] compile-flags: --target sparcv9-sun-solaris +// [sparcv9_sun_solaris] needs-llvm-components: sparc +// revisions: thumbv4t_none_eabi +// [thumbv4t_none_eabi] compile-flags: --target thumbv4t-none-eabi +// [thumbv4t_none_eabi] needs-llvm-components: arm +// revisions: thumbv5te_none_eabi +// [thumbv5te_none_eabi] compile-flags: --target thumbv5te-none-eabi +// [thumbv5te_none_eabi] needs-llvm-components: arm +// revisions: thumbv6m_none_eabi +// [thumbv6m_none_eabi] compile-flags: --target thumbv6m-none-eabi +// [thumbv6m_none_eabi] needs-llvm-components: arm +// revisions: thumbv7em_none_eabi +// [thumbv7em_none_eabi] compile-flags: --target thumbv7em-none-eabi +// [thumbv7em_none_eabi] needs-llvm-components: arm +// revisions: thumbv7em_none_eabihf +// [thumbv7em_none_eabihf] compile-flags: --target thumbv7em-none-eabihf +// [thumbv7em_none_eabihf] needs-llvm-components: arm +// revisions: thumbv7m_none_eabi +// [thumbv7m_none_eabi] compile-flags: --target thumbv7m-none-eabi +// [thumbv7m_none_eabi] needs-llvm-components: arm +// revisions: thumbv7neon_linux_androideabi +// [thumbv7neon_linux_androideabi] compile-flags: --target thumbv7neon-linux-androideabi +// [thumbv7neon_linux_androideabi] needs-llvm-components: arm +// revisions: thumbv7neon_unknown_linux_gnueabihf +// [thumbv7neon_unknown_linux_gnueabihf] compile-flags: --target thumbv7neon-unknown-linux-gnueabihf +// [thumbv7neon_unknown_linux_gnueabihf] needs-llvm-components: arm +// revisions: thumbv7neon_unknown_linux_musleabihf +// [thumbv7neon_unknown_linux_musleabihf] compile-flags: --target thumbv7neon-unknown-linux-musleabihf +// [thumbv7neon_unknown_linux_musleabihf] needs-llvm-components: arm +// revisions: thumbv8m_base_none_eabi +// [thumbv8m_base_none_eabi] compile-flags: --target thumbv8m.base-none-eabi +// [thumbv8m_base_none_eabi] needs-llvm-components: arm +// revisions: thumbv8m_main_none_eabi +// [thumbv8m_main_none_eabi] compile-flags: --target thumbv8m.main-none-eabi +// [thumbv8m_main_none_eabi] needs-llvm-components: arm +// revisions: thumbv8m_main_none_eabihf +// [thumbv8m_main_none_eabihf] compile-flags: --target thumbv8m.main-none-eabihf +// [thumbv8m_main_none_eabihf] needs-llvm-components: arm +// revisions: wasm32_unknown_emscripten +// [wasm32_unknown_emscripten] compile-flags: --target wasm32-unknown-emscripten +// [wasm32_unknown_emscripten] needs-llvm-components: webassembly +// revisions: wasm32_unknown_unknown +// [wasm32_unknown_unknown] compile-flags: --target wasm32-unknown-unknown +// [wasm32_unknown_unknown] needs-llvm-components: webassembly +// revisions: wasm32_wasi +// [wasm32_wasi] compile-flags: --target wasm32-wasi +// [wasm32_wasi] needs-llvm-components: webassembly +// revisions: wasm32_wasi_preview1_threads +// [wasm32_wasi_preview1_threads] compile-flags: --target wasm32-wasi-preview1-threads +// [wasm32_wasi_preview1_threads] needs-llvm-components: webassembly +// revisions: wasm64_unknown_unknown +// [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown +// [wasm64_unknown_unknown] needs-llvm-components: webassembly +// revisions: x86_64_apple_darwin +// [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin +// [x86_64_apple_darwin] needs-llvm-components: x86 +// revisions: x86_64_apple_ios +// [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios +// [x86_64_apple_ios] needs-llvm-components: x86 +// revisions: x86_64_apple_ios_macabi +// [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi +// [x86_64_apple_ios_macabi] needs-llvm-components: x86 +// revisions: x86_64_apple_tvos +// [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos +// [x86_64_apple_tvos] needs-llvm-components: x86 +// revisions: x86_64_apple_watchos_sim +// [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim +// [x86_64_apple_watchos_sim] needs-llvm-components: x86 +// revisions: x86_64_fortanix_unknown_sgx +// [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx +// [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86 +// revisions: x86_64_fuchsia +// [x86_64_fuchsia] compile-flags: --target x86_64-fuchsia +// [x86_64_fuchsia] needs-llvm-components: x86 +// revisions: x86_64_linux_android +// [x86_64_linux_android] compile-flags: --target x86_64-linux-android +// [x86_64_linux_android] needs-llvm-components: x86 +// revisions: x86_64_pc_nto_qnx710 +// [x86_64_pc_nto_qnx710] compile-flags: --target x86_64-pc-nto-qnx710 +// [x86_64_pc_nto_qnx710] needs-llvm-components: x86 +// revisions: x86_64_pc_solaris +// [x86_64_pc_solaris] compile-flags: --target x86_64-pc-solaris +// [x86_64_pc_solaris] needs-llvm-components: x86 +// revisions: x86_64_unikraft_linux_musl +// [x86_64_unikraft_linux_musl] compile-flags: --target x86_64-unikraft-linux-musl +// [x86_64_unikraft_linux_musl] needs-llvm-components: x86 +// revisions: x86_64_unknown_dragonfly +// [x86_64_unknown_dragonfly] compile-flags: --target x86_64-unknown-dragonfly +// [x86_64_unknown_dragonfly] needs-llvm-components: x86 +// revisions: x86_64_unknown_freebsd +// [x86_64_unknown_freebsd] compile-flags: --target x86_64-unknown-freebsd +// [x86_64_unknown_freebsd] needs-llvm-components: x86 +// revisions: x86_64_unknown_fuchsia +// [x86_64_unknown_fuchsia] compile-flags: --target x86_64-unknown-fuchsia +// [x86_64_unknown_fuchsia] needs-llvm-components: x86 +// revisions: x86_64_unknown_haiku +// [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku +// [x86_64_unknown_haiku] needs-llvm-components: x86 +// revisions: x86_64_unknown_hermit +// [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit +// [x86_64_unknown_hermit] needs-llvm-components: x86 +// revisions: x86_64_unknown_illumos +// [x86_64_unknown_illumos] compile-flags: --target x86_64-unknown-illumos +// [x86_64_unknown_illumos] needs-llvm-components: x86 +// revisions: x86_64_unknown_l4re_uclibc +// [x86_64_unknown_l4re_uclibc] compile-flags: --target x86_64-unknown-l4re-uclibc +// [x86_64_unknown_l4re_uclibc] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_gnu +// [x86_64_unknown_linux_gnu] compile-flags: --target x86_64-unknown-linux-gnu +// [x86_64_unknown_linux_gnu] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_gnux32 +// [x86_64_unknown_linux_gnux32] compile-flags: --target x86_64-unknown-linux-gnux32 +// [x86_64_unknown_linux_gnux32] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_musl +// [x86_64_unknown_linux_musl] compile-flags: --target x86_64-unknown-linux-musl +// [x86_64_unknown_linux_musl] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_ohos +// [x86_64_unknown_linux_ohos] compile-flags: --target x86_64-unknown-linux-ohos +// [x86_64_unknown_linux_ohos] needs-llvm-components: x86 +// revisions: x86_64_unknown_netbsd +// [x86_64_unknown_netbsd] compile-flags: --target x86_64-unknown-netbsd +// [x86_64_unknown_netbsd] needs-llvm-components: x86 +// revisions: x86_64_unknown_none +// [x86_64_unknown_none] compile-flags: --target x86_64-unknown-none +// [x86_64_unknown_none] needs-llvm-components: x86 +// revisions: x86_64_unknown_openbsd +// [x86_64_unknown_openbsd] compile-flags: --target x86_64-unknown-openbsd +// [x86_64_unknown_openbsd] needs-llvm-components: x86 +// revisions: x86_64_unknown_redox +// [x86_64_unknown_redox] compile-flags: --target x86_64-unknown-redox +// [x86_64_unknown_redox] needs-llvm-components: x86 +// revisions: x86_64_wrs_vxworks +// [x86_64_wrs_vxworks] compile-flags: --target x86_64-wrs-vxworks +// [x86_64_wrs_vxworks] needs-llvm-components: x86 +// revisions: x86_64h_apple_darwin +// [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin +// [x86_64h_apple_darwin] needs-llvm-components: x86 + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .section diff --git a/tests/assembly/targets/targets-nvptx.rs b/tests/assembly/targets/targets-nvptx.rs new file mode 100644 index 000000000000..063342304000 --- /dev/null +++ b/tests/assembly/targets/targets-nvptx.rs @@ -0,0 +1,21 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: nvptx64_nvidia_cuda +// [nvptx64_nvidia_cuda] compile-flags: --target nvptx64-nvidia-cuda +// [nvptx64_nvidia_cuda] needs-llvm-components: nvptx + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .version diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs new file mode 100644 index 000000000000..7398d7ef7900 --- /dev/null +++ b/tests/assembly/targets/targets-pe.rs @@ -0,0 +1,93 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: aarch64_pc_windows_msvc +// [aarch64_pc_windows_msvc] compile-flags: --target aarch64-pc-windows-msvc +// [aarch64_pc_windows_msvc] needs-llvm-components: aarch64 +// revisions: aarch64_pc_windows_gnullvm +// [aarch64_pc_windows_gnullvm] compile-flags: --target aarch64-pc-windows-gnullvm +// [aarch64_pc_windows_gnullvm] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_uefi +// [aarch64_unknown_uefi] compile-flags: --target aarch64-unknown-uefi +// [aarch64_unknown_uefi] needs-llvm-components: aarch64 +// revisions: aarch64_uwp_windows_msvc +// [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc +// [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64 +// revisions: avr_unknown_gnu_atmega328 +// [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328 +// [avr_unknown_gnu_atmega328] needs-llvm-components: avr +// revisions: bpfeb_unknown_none +// [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none +// [bpfeb_unknown_none] needs-llvm-components: bpf +// revisions: bpfel_unknown_none +// [bpfel_unknown_none] compile-flags: --target bpfel-unknown-none +// [bpfel_unknown_none] needs-llvm-components: bpf +// revisions: i586_pc_windows_msvc +// [i586_pc_windows_msvc] compile-flags: --target i586-pc-windows-msvc +// [i586_pc_windows_msvc] needs-llvm-components: x86 +// revisions: i686_pc_windows_gnu +// [i686_pc_windows_gnu] compile-flags: --target i686-pc-windows-gnu +// [i686_pc_windows_gnu] needs-llvm-components: x86 +// revisions: i686_pc_windows_msvc +// [i686_pc_windows_msvc] compile-flags: --target i686-pc-windows-msvc +// [i686_pc_windows_msvc] needs-llvm-components: x86 +// revisions: i686_pc_windows_gnullvm +// [i686_pc_windows_gnullvm] compile-flags: --target i686-pc-windows-gnullvm +// [i686_pc_windows_gnullvm] needs-llvm-components: x86 +// revisions: i686_uwp_windows_gnu +// [i686_uwp_windows_gnu] compile-flags: --target i686-uwp-windows-gnu +// [i686_uwp_windows_gnu] needs-llvm-components: x86 +// revisions: i686_unknown_uefi +// [i686_unknown_uefi] compile-flags: --target i686-unknown-uefi +// [i686_unknown_uefi] needs-llvm-components: x86 +// revisions: i686_uwp_windows_msvc +// [i686_uwp_windows_msvc] compile-flags: --target i686-uwp-windows-msvc +// [i686_uwp_windows_msvc] needs-llvm-components: x86 +// revisions: i686_win7_windows_msvc +// [i686_win7_windows_msvc] compile-flags: --target i686-win7-windows-msvc +// [i686_win7_windows_msvc] needs-llvm-components: x86 +// revisions: powerpc64_ibm_aix +// [powerpc64_ibm_aix] compile-flags: --target powerpc64-ibm-aix +// [powerpc64_ibm_aix] needs-llvm-components: powerpc +// revisions: thumbv7a_uwp_windows_msvc +// [thumbv7a_uwp_windows_msvc] compile-flags: --target thumbv7a-uwp-windows-msvc +// [thumbv7a_uwp_windows_msvc] needs-llvm-components: arm +// revisions: thumbv7a_pc_windows_msvc +// [thumbv7a_pc_windows_msvc] compile-flags: --target thumbv7a-pc-windows-msvc +// [thumbv7a_pc_windows_msvc] needs-llvm-components: arm +// revisions: x86_64_pc_windows_gnu +// [x86_64_pc_windows_gnu] compile-flags: --target x86_64-pc-windows-gnu +// [x86_64_pc_windows_gnu] needs-llvm-components: x86 +// revisions: x86_64_pc_windows_gnullvm +// [x86_64_pc_windows_gnullvm] compile-flags: --target x86_64-pc-windows-gnullvm +// [x86_64_pc_windows_gnullvm] needs-llvm-components: x86 +// revisions: x86_64_pc_windows_msvc +// [x86_64_pc_windows_msvc] compile-flags: --target x86_64-pc-windows-msvc +// [x86_64_pc_windows_msvc] needs-llvm-components: x86 +// revisions: x86_64_unknown_uefi +// [x86_64_unknown_uefi] compile-flags: --target x86_64-unknown-uefi +// [x86_64_unknown_uefi] needs-llvm-components: x86 +// revisions: x86_64_uwp_windows_gnu +// [x86_64_uwp_windows_gnu] compile-flags: --target x86_64-uwp-windows-gnu +// [x86_64_uwp_windows_gnu] needs-llvm-components: x86 +// revisions: x86_64_uwp_windows_msvc +// [x86_64_uwp_windows_msvc] compile-flags: --target x86_64-uwp-windows-msvc +// [x86_64_uwp_windows_msvc] needs-llvm-components: x86 +// revisions: x86_64_win7_windows_msvc +// [x86_64_win7_windows_msvc] compile-flags: --target x86_64-win7-windows-msvc +// [x86_64_win7_windows_msvc] needs-llvm-components: x86 + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .file From 4db93c57507dd7c2c3a5cfe9509b67494824a829 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Jan 2024 21:30:45 +0000 Subject: [PATCH 212/297] Stop using track_errors for some forever unstable rustc_attr analyses --- .../src/collect/type_of/opaque.rs | 8 +++++--- compiler/rustc_hir_analysis/src/lib.rs | 10 +++------- compiler/rustc_hir_analysis/src/outlives/test.rs | 8 +++++--- compiler/rustc_hir_analysis/src/variance/test.rs | 13 ++++++++----- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 1f7ca48234a2..4f4453867957 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -5,20 +5,22 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType}; -pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { +pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let type_of = tcx.type_of(id.owner_id).instantiate_identity(); - tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }); + res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of })); } } } + res } /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f5abb7261c00..16e530ca946c 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -169,9 +169,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function // or the compiler in general. if tcx.features().rustc_attrs { - tcx.sess.track_errors(|| { - tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); - })?; + tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?; } tcx.sess.track_errors(|| { @@ -190,9 +188,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { })?; if tcx.features().rustc_attrs { - tcx.sess.track_errors(|| { - tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); - })?; + tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?; } tcx.sess.time("wf_checking", || { @@ -200,7 +196,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { })?; if tcx.features().rustc_attrs { - tcx.sess.track_errors(|| collect::test_opaque_hidden_types(tcx))?; + collect::test_opaque_hidden_types(tcx)?; } // Freeze definitions as we don't add new ones at this point. This improves performance by diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index dea3f1a99308..60cd8c39fa02 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -1,7 +1,8 @@ use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::sym; +use rustc_span::{symbol::sym, ErrorGuaranteed}; -pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { +pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. @@ -22,7 +23,8 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for p in pred { err.note(p); } - err.emit(); + res = Err(err.emit()); } } + res } diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 5264d5aa26f2..c211e1af046a 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -2,19 +2,21 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; -pub fn test_variance(tcx: TyCtxt<'_>) { +pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } } @@ -25,10 +27,11 @@ pub fn test_variance(tcx: TyCtxt<'_>) { if tcx.has_attr(id.owner_id, sym::rustc_variance) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } + res } From b1ce8a4ecdcdb179d023d9fd1061575ba651aeeb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Jan 2024 22:13:39 +0000 Subject: [PATCH 213/297] Move `check_mod_impl_wf` query call out of track_errors and bubble errors up instead. --- .../rustc_hir_analysis/src/impl_wf_check.rs | 46 +++++-- .../src/impl_wf_check/min_specialization.rs | 126 +++++++++++------- compiler/rustc_hir_analysis/src/lib.rs | 15 ++- compiler/rustc_middle/src/query/mod.rs | 3 +- .../in-trait/return-dont-satisfy-bounds.rs | 2 + .../return-dont-satisfy-bounds.stderr | 26 +++- .../specializing-constness-2.stderr | 14 +- 7 files changed, 160 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 3f9b1f384d79..2fe08ead72b2 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -17,7 +17,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::{Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; mod min_specialization; @@ -51,24 +51,29 @@ mod min_specialization; /// impl<'a> Trait for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { +fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; let module = tcx.hir_module_items(module_def_id); + let mut res = Ok(()); for id in module.items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) { - enforce_impl_params_are_constrained(tcx, id.owner_id.def_id); + res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id)); if min_specialization { - check_min_specialization(tcx, id.owner_id.def_id); + res = res.and(check_min_specialization(tcx, id.owner_id.def_id)); } } } + res } pub fn provide(providers: &mut Providers) { *providers = Providers { check_mod_impl_wf, ..*providers }; } -fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { +fn enforce_impl_params_are_constrained( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); if impl_self_ty.references_error() { @@ -80,7 +85,10 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}", ), ); - return; + // This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on + // `type_of` having been called much earlier, and thus this value being read from cache. + // Compilation must continue in order for other important diagnostics to keep showing up. + return Ok(()); } let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); @@ -113,13 +121,19 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) }) .collect(); + let mut res = Ok(()); for param in &impl_generics.params { match param.kind { // Disallow ANY unconstrained type parameters. ty::GenericParamDefKind::Type { .. } => { let param_ty = ty::ParamTy::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ty)) { - report_unused_parameter(tcx, tcx.def_span(param.def_id), "type", param_ty.name); + res = Err(report_unused_parameter( + tcx, + tcx.def_span(param.def_id), + "type", + param_ty.name, + )); } } ty::GenericParamDefKind::Lifetime => { @@ -127,27 +141,28 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) if lifetimes_in_associated_types.contains(¶m_lt) && // (*) !input_parameters.contains(¶m_lt) { - report_unused_parameter( + res = Err(report_unused_parameter( tcx, tcx.def_span(param.def_id), "lifetime", param.name, - ); + )); } } ty::GenericParamDefKind::Const { .. } => { let param_ct = ty::ParamConst::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ct)) { - report_unused_parameter( + res = Err(report_unused_parameter( tcx, tcx.def_span(param.def_id), "const", param_ct.name, - ); + )); } } } } + res // (*) This is a horrible concession to reality. I think it'd be // better to just ban unconstrained lifetimes outright, but in @@ -169,7 +184,12 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) // used elsewhere are not projected back out. } -fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol) { +fn report_unused_parameter( + tcx: TyCtxt<'_>, + span: Span, + kind: &str, + name: Symbol, +) -> ErrorGuaranteed { let mut err = struct_span_code_err!( tcx.dcx(), span, @@ -188,5 +208,5 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol "proving the result of expressions other than the parameter are unique is not supported", ); } - err.emit(); + err.emit() } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 93dd2342a4d1..6d685aec663b 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -82,10 +82,14 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt}; -pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { +pub(super) fn check_min_specialization( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { if let Some(node) = parent_specialization_node(tcx, impl_def_id) { - check_always_applicable(tcx, impl_def_id, node); + check_always_applicable(tcx, impl_def_id, node)?; } + Ok(()) } fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option { @@ -109,42 +113,58 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti /// Check that `impl1` is a sound specialization #[instrument(level = "debug", skip(tcx))] -fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) { +fn check_always_applicable( + tcx: TyCtxt<'_>, + impl1_def_id: LocalDefId, + impl2_node: Node, +) -> Result<(), ErrorGuaranteed> { let span = tcx.def_span(impl1_def_id); - check_has_items(tcx, impl1_def_id, impl2_node, span); + let mut res = check_has_items(tcx, impl1_def_id, impl2_node, span); - if let Ok((impl1_args, impl2_args)) = get_impl_args(tcx, impl1_def_id, impl2_node) { - let impl2_def_id = impl2_node.def_id(); - debug!(?impl2_def_id, ?impl2_args); + let (impl1_args, impl2_args) = get_impl_args(tcx, impl1_def_id, impl2_node)?; + let impl2_def_id = impl2_node.def_id(); + debug!(?impl2_def_id, ?impl2_args); - let parent_args = if impl2_node.is_from_trait() { - impl2_args.to_vec() - } else { - unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args) - }; + let parent_args = if impl2_node.is_from_trait() { + impl2_args.to_vec() + } else { + unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args) + }; - check_constness(tcx, impl1_def_id, impl2_node, span); - check_static_lifetimes(tcx, &parent_args, span); - check_duplicate_params(tcx, impl1_args, &parent_args, span); - check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span); - } + res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span)); + res = res.and(check_static_lifetimes(tcx, &parent_args, span)); + res = res.and(check_duplicate_params(tcx, impl1_args, &parent_args, span)); + res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span)); + + res } -fn check_has_items(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) { +fn check_has_items( + tcx: TyCtxt<'_>, + impl1_def_id: LocalDefId, + impl2_node: Node, + span: Span, +) -> Result<(), ErrorGuaranteed> { if let Node::Impl(impl2_id) = impl2_node && tcx.associated_item_def_ids(impl1_def_id).is_empty() { let base_impl_span = tcx.def_span(impl2_id); - tcx.dcx().emit_err(errors::EmptySpecialization { span, base_impl_span }); + return Err(tcx.dcx().emit_err(errors::EmptySpecialization { span, base_impl_span })); } + Ok(()) } /// Check that the specializing impl `impl1` is at least as const as the base /// impl `impl2` -fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) { +fn check_constness( + tcx: TyCtxt<'_>, + impl1_def_id: LocalDefId, + impl2_node: Node, + span: Span, +) -> Result<(), ErrorGuaranteed> { if impl2_node.is_from_trait() { // This isn't a specialization - return; + return Ok(()); } let impl1_constness = tcx.constness(impl1_def_id.to_def_id()); @@ -152,9 +172,10 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, if let hir::Constness::Const = impl2_constness { if let hir::Constness::NotConst = impl1_constness { - tcx.dcx().emit_err(errors::ConstSpecialize { span }); + return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span })); } } + Ok(()) } /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two @@ -290,15 +311,17 @@ fn check_duplicate_params<'tcx>( impl1_args: GenericArgsRef<'tcx>, parent_args: &Vec>, span: Span, -) { +) -> Result<(), ErrorGuaranteed> { let mut base_params = cgp::parameters_for(parent_args, true); base_params.sort_by_key(|param| param.0); if let (_, [duplicate, ..]) = base_params.partition_dedup() { let param = impl1_args[duplicate.0 as usize]; - tcx.dcx() + return Err(tcx + .dcx() .struct_span_err(span, format!("specializing impl repeats parameter `{param}`")) - .emit(); + .emit()); } + Ok(()) } /// Check that `'static` lifetimes are not introduced by the specializing impl. @@ -313,10 +336,11 @@ fn check_static_lifetimes<'tcx>( tcx: TyCtxt<'tcx>, parent_args: &Vec>, span: Span, -) { +) -> Result<(), ErrorGuaranteed> { if tcx.any_free_region_meets(parent_args, |r| r.is_static()) { - tcx.dcx().emit_err(errors::StaticSpecialize { span }); + return Err(tcx.dcx().emit_err(errors::StaticSpecialize { span })); } + Ok(()) } /// Check whether predicates on the specializing impl (`impl1`) are allowed. @@ -337,7 +361,7 @@ fn check_predicates<'tcx>( impl2_node: Node, impl2_args: GenericArgsRef<'tcx>, span: Span, -) { +) -> Result<(), ErrorGuaranteed> { let impl1_predicates: Vec<_> = traits::elaborate( tcx, tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_args).into_iter(), @@ -399,14 +423,16 @@ fn check_predicates<'tcx>( } impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits)); + let mut res = Ok(()); for (clause, span) in impl1_predicates { if !impl2_predicates .iter() .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) { - check_specialization_on(tcx, clause, span) + res = res.and(check_specialization_on(tcx, clause, span)) } } + res } /// Checks if some predicate on the specializing impl (`predicate1`) is the same @@ -443,19 +469,26 @@ fn trait_predicates_eq<'tcx>( } #[instrument(level = "debug", skip(tcx))] -fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) { +fn check_specialization_on<'tcx>( + tcx: TyCtxt<'tcx>, + clause: ty::Clause<'tcx>, + span: Span, +) -> Result<(), ErrorGuaranteed> { match clause.kind().skip_binder() { // Global predicates are either always true or always false, so we // are fine to specialize on. - _ if clause.is_global() => (), + _ if clause.is_global() => Ok(()), // We allow specializing on explicitly marked traits with no associated // items. ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { - if !matches!( + if matches!( trait_specialization_kind(tcx, clause), Some(TraitSpecializationKind::Marker) ) { - tcx.dcx() + Ok(()) + } else { + Err(tcx + .dcx() .struct_span_err( span, format!( @@ -463,17 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, sp tcx.def_path_str(trait_ref.def_id), ), ) - .emit(); + .emit()) } } - ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - tcx.dcx() - .struct_span_err( - span, - format!("cannot specialize on associated type `{projection_ty} == {term}`",), - ) - .emit(); - } + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => Err(tcx + .dcx() + .struct_span_err( + span, + format!("cannot specialize on associated type `{projection_ty} == {term}`",), + ) + .emit()), ty::ClauseKind::ConstArgHasType(..) => { // FIXME(min_specialization), FIXME(const_generics): // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure @@ -483,12 +515,12 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, sp // While we do not support constructs like `` there is probably no risk of // soundness bugs, but when we support generic const parameter types this will need to be // revisited. + Ok(()) } - _ => { - tcx.dcx() - .struct_span_err(span, format!("cannot specialize on predicate `{clause}`")) - .emit(); - } + _ => Err(tcx + .dcx() + .struct_span_err(span, format!("cannot specialize on predicate `{clause}`")) + .emit()), } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 16e530ca946c..1a370ad10cf7 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -166,17 +166,18 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) }); - // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function - // or the compiler in general. if tcx.features().rustc_attrs { tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?; } - tcx.sess.track_errors(|| { - tcx.sess.time("coherence_checking", || { - // Check impls constrain their parameters - tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); + tcx.sess.time("coherence_checking", || { + // Check impls constrain their parameters + let res = + tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); + // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function + // or the compiler in general. + res.and(tcx.sess.track_errors(|| { for &trait_def_id in tcx.all_local_trait_impls(()).keys() { tcx.ensure().coherent_trait(trait_def_id); } @@ -184,7 +185,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // these queries are executed for side-effects (error reporting): tcx.ensure().crate_inherent_impls(()); tcx.ensure().crate_inherent_impls_overlap_check(()); - }); + })) })?; if tcx.features().rustc_attrs { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1dc772208810..6e5870df7c14 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -961,8 +961,9 @@ rustc_queries! { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } - query check_mod_impl_wf(key: LocalModDefId) -> () { + query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } + ensure_forwards_result_if_red } query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index ad73b12feb53..ff265e576b90 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -7,6 +7,8 @@ struct Bar; impl Foo for Bar { fn foo>(self) -> impl Foo { //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] + //~| ERROR: the trait bound `Bar: Foo` is not satisfied [E0277] + //~| ERROR: impl has stricter requirements than trait self } } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index db587d069f8b..638de01f9139 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -11,6 +11,28 @@ note: required by a bound in `Foo::{opaque#0}` LL | fn foo(self) -> impl Foo; | ^^^^^^ required by this bound in `Foo::{opaque#0}` -error: aborting due to 1 previous error +error[E0276]: impl has stricter requirements than trait + --> $DIR/return-dont-satisfy-bounds.rs:8:16 + | +LL | fn foo(self) -> impl Foo; + | -------------------------------- definition of `foo` from trait +... +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^ impl has extra requirement `F2: Foo` -For more information about this error, try `rustc --explain E0277`. +error[E0277]: the trait bound `Bar: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:8:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar` +... +LL | self + | ---- return type was inferred to be `Bar` here + | + = help: the trait `Foo` is implemented for `Bar` + = help: for that trait implementation, expected `char`, found `u8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index 5210a6942010..e5b9493b3ce1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -7,6 +7,16 @@ LL | impl A for T { LL | impl const A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/specializing-constness-2.rs:27:5 + | +LL | ::a(); + | ^^^^^^^^^^^^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` -For more information about this error, try `rustc --explain E0119`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. From 49347ee12dd23c357d45374a6e442e2c32fa4202 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 08:57:07 +0000 Subject: [PATCH 214/297] Make crate_inherent_impls_overlap_check bubble up its errors --- .../src/coherence/inherent_impls_overlap.rs | 46 +++++++++++-------- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 3 +- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 4c3455c7240f..d66f073b1b4c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -6,16 +6,18 @@ use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; use rustc_trait_selection::traits::{self, SkipLeakCheck}; use smallvec::SmallVec; use std::collections::hash_map::Entry; -pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) { +pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> { let mut inherent_overlap_checker = InherentOverlapChecker { tcx }; + let mut res = Ok(()); for id in tcx.hir().items() { - inherent_overlap_checker.check_item(id); + res = res.and(inherent_overlap_checker.check_item(id)); } + res } struct InherentOverlapChecker<'tcx> { @@ -58,10 +60,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { == item2.ident(self.tcx).normalize_to_macros_2_0() } - fn check_for_duplicate_items_in_impl(&self, impl_: DefId) { + fn check_for_duplicate_items_in_impl(&self, impl_: DefId) -> Result<(), ErrorGuaranteed> { let impl_items = self.tcx.associated_items(impl_); let mut seen_items = FxHashMap::default(); + let mut res = Ok(()); for impl_item in impl_items.in_definition_order() { let span = self.tcx.def_span(impl_item.def_id); let ident = impl_item.ident(self.tcx); @@ -70,7 +73,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { match seen_items.entry(norm_ident) { Entry::Occupied(entry) => { let former = entry.get(); - struct_span_code_err!( + res = Err(struct_span_code_err!( self.tcx.dcx(), span, E0592, @@ -79,13 +82,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ) .with_span_label(span, format!("duplicate definitions for `{ident}`")) .with_span_label(*former, format!("other definition for `{ident}`")) - .emit(); + .emit()); } Entry::Vacant(entry) => { entry.insert(span); } } } + res } fn check_for_common_items_in_impls( @@ -93,10 +97,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl1: DefId, impl2: DefId, overlap: traits::OverlapResult<'_>, - ) { + ) -> Result<(), ErrorGuaranteed> { let impl_items1 = self.tcx.associated_items(impl1); let impl_items2 = self.tcx.associated_items(impl2); + let mut res = Ok(()); for &item1 in impl_items1.in_definition_order() { let collision = impl_items2 .filter_by_name_unhygienic(item1.name) @@ -128,9 +133,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> { traits::add_placeholder_note(&mut err); } - err.emit(); + res = Err(err.emit()); } } + res } fn check_for_overlapping_inherent_impls( @@ -138,7 +144,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { overlap_mode: OverlapMode, impl1_def_id: DefId, impl2_def_id: DefId, - ) { + ) -> Result<(), ErrorGuaranteed> { let maybe_overlap = traits::overlapping_impls( self.tcx, impl1_def_id, @@ -150,14 +156,16 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ); if let Some(overlap) = maybe_overlap { - self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap); + self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap) + } else { + Ok(()) } } - fn check_item(&mut self, id: hir::ItemId) { + fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> { let def_kind = self.tcx.def_kind(id.owner_id); if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) { - return; + return Ok(()); } let impls = self.tcx.inherent_impls(id.owner_id); @@ -173,17 +181,18 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // otherwise switch to an allocating algorithm with // faster asymptotic runtime. const ALLOCATING_ALGO_THRESHOLD: usize = 500; + let mut res = Ok(()); if impls.len() < ALLOCATING_ALGO_THRESHOLD { for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { - self.check_for_duplicate_items_in_impl(impl1_def_id); + res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( + res = res.and(self.check_for_overlapping_inherent_impls( overlap_mode, impl1_def_id, impl2_def_id, - ); + )); } } } @@ -315,20 +324,21 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl_blocks.sort_unstable(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; - self.check_for_duplicate_items_in_impl(impl1_def_id); + res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( + res = res.and(self.check_for_overlapping_inherent_impls( overlap_mode, impl1_def_id, impl2_def_id, - ); + )); } } } } } + res } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1a370ad10cf7..da9a97db9a4b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -184,8 +184,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // these queries are executed for side-effects (error reporting): tcx.ensure().crate_inherent_impls(()); - tcx.ensure().crate_inherent_impls_overlap_check(()); })) + .and(tcx.ensure().crate_inherent_impls_overlap_check(())) })?; if tcx.features().rustc_attrs { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6e5870df7c14..15f0dc0208d5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1019,8 +1019,9 @@ rustc_queries! { /// Checks all types in the crate for overlap in their inherent impls. Reports errors. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls_overlap_check(_: ()) -> () { + query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for overlap between inherent impls defined in this crate" } + ensure_forwards_result_if_red } /// Checks whether all impls in the crate pass the overlap check, returning From 557b11187090b0ec749b07858c6ac18f95b7490e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 14:29:54 +0000 Subject: [PATCH 215/297] Make crate_inherent_impls fallible and stop using `track_errors` for it --- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../src/coherence/inherent_impls.rs | 79 +++++++++++-------- .../src/coherence/inherent_impls_overlap.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 5 +- compiler/rustc_hir_typeck/src/expr.rs | 3 +- compiler/rustc_hir_typeck/src/method/probe.rs | 6 +- .../rustc_hir_typeck/src/method/suggest.rs | 19 +++-- .../src/rmeta/decoder/cstore_impl.rs | 4 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/query/erase.rs | 4 + compiler/rustc_middle/src/query/mod.rs | 10 +-- compiler/rustc_middle/src/query/plumbing.rs | 12 ++- compiler/rustc_middle/src/ty/trait_def.rs | 18 ++++- compiler/rustc_monomorphize/src/collector.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 6 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/types.rs | 4 +- .../passes/collect_intra_doc_links.rs | 3 +- 19 files changed, 115 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9f4f1413650f..b9e72a3b1ea9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1446,7 +1446,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let candidates: Vec<_> = tcx - .inherent_impls(adt_did) + .inherent_impls(adt_did)? .iter() .filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?))) .collect(); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 3162004a6348..abef365c3ca3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -13,32 +13,41 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; /// On-demand query: yields a map containing all types mapped to their inherent impls. -pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { +pub fn crate_inherent_impls( + tcx: TyCtxt<'_>, + (): (), +) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> { let mut collect = InherentCollect { tcx, impls_map: Default::default() }; + let mut res = Ok(()); for id in tcx.hir().items() { - collect.check_item(id); + res = res.and(collect.check_item(id)); } - collect.impls_map + res?; + Ok(tcx.arena.alloc(collect.impls_map)) } -pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { - let crate_map = tcx.crate_inherent_impls(()); - tcx.arena.alloc_from_iter( +pub fn crate_incoherent_impls( + tcx: TyCtxt<'_>, + simp: SimplifiedType, +) -> Result<&[DefId], ErrorGuaranteed> { + let crate_map = tcx.crate_inherent_impls(())?; + Ok(tcx.arena.alloc_from_iter( crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()), - ) + )) } /// On-demand query: yields a vector of the inherent impls for a specific type. -pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] { - let crate_map = tcx.crate_inherent_impls(()); - match crate_map.inherent_impls.get(&ty_def_id) { +pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> { + let crate_map = tcx.crate_inherent_impls(())?; + Ok(match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], None => &[], - } + }) } struct InherentCollect<'tcx> { @@ -47,14 +56,19 @@ struct InherentCollect<'tcx> { } impl<'tcx> InherentCollect<'tcx> { - fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) { + fn check_def_id( + &mut self, + impl_def_id: LocalDefId, + self_ty: Ty<'tcx>, + ty_def_id: DefId, + ) -> Result<(), ErrorGuaranteed> { if let Some(ty_def_id) = ty_def_id.as_local() { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default(); vec.push(impl_def_id.to_def_id()); - return; + return Ok(()); } if self.tcx.features().rustc_attrs { @@ -62,18 +76,16 @@ impl<'tcx> InherentCollect<'tcx> { if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span }); - return; + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span })); } for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { span: impl_span, help_span: self.tcx.def_span(impl_item), - }); - return; + })); } } @@ -82,24 +94,28 @@ impl<'tcx> InherentCollect<'tcx> { } else { bug!("unexpected self type: {:?}", self_ty); } + Ok(()) } else { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }); + Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span })) } } - fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) { + fn check_primitive_impl( + &mut self, + impl_def_id: LocalDefId, + ty: Ty<'tcx>, + ) -> Result<(), ErrorGuaranteed> { let items = self.tcx.associated_item_def_ids(impl_def_id); if !self.tcx.hir().rustc_coherence_is_core() { if self.tcx.features().rustc_attrs { for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { span, help_span: self.tcx.def_span(impl_item), - }); - return; + })); } } } else { @@ -108,8 +124,7 @@ impl<'tcx> InherentCollect<'tcx> { if let ty::Ref(_, subty, _) = ty.kind() { note = Some(errors::InherentPrimitiveTyNote { subty: *subty }); } - self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note }); - return; + return Err(self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note })); } } @@ -118,11 +133,12 @@ impl<'tcx> InherentCollect<'tcx> { } else { bug!("unexpected primitive type: {:?}", ty); } + Ok(()) } - fn check_item(&mut self, id: hir::ItemId) { + fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> { if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) { - return; + return Ok(()); } let id = id.owner_id.def_id; @@ -132,10 +148,10 @@ impl<'tcx> InherentCollect<'tcx> { ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()), ty::Foreign(did) => self.check_def_id(id, self_ty, did), ty::Dynamic(data, ..) if data.principal_def_id().is_some() => { - self.check_def_id(id, self_ty, data.principal_def_id().unwrap()); + self.check_def_id(id, self_ty, data.principal_def_id().unwrap()) } ty::Dynamic(..) => { - self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }); + Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span })) } ty::Bool | ty::Char @@ -151,7 +167,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::FnPtr(_) | ty::Tuple(..) => self.check_primitive_impl(id, self_ty), ty::Alias(..) | ty::Param(_) => { - self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }); + Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span })) } ty::FnDef(..) | ty::Closure(..) @@ -162,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Infer(_) => { bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty); } - ty::Error(_) => {} + // We could bail out here, but that will silence other useful errors. + ty::Error(_) => Ok(()), } } } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index d66f073b1b4c..63ea02720145 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -168,7 +168,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { return Ok(()); } - let impls = self.tcx.inherent_impls(id.owner_id); + let impls = self.tcx.inherent_impls(id.owner_id)?; let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id()); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index da9a97db9a4b..08956d222d2a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -181,10 +181,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { for &trait_def_id in tcx.all_local_trait_impls(()).keys() { tcx.ensure().coherent_trait(trait_def_id); } - - // these queries are executed for side-effects (error reporting): - tcx.ensure().crate_inherent_impls(()); })) + // these queries are executed for side-effects (error reporting): + .and(tcx.ensure().crate_inherent_impls(())) .and(tcx.ensure().crate_inherent_impls_overlap_check(())) })?; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ac8701a33d44..065052d9a5d2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2104,7 +2104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut items = self .tcx .inherent_impls(def_id) - .iter() + .into_iter() + .flatten() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. .filter(|item| { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 10c31d8c641c..4dc802008d03 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -711,14 +711,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else { bug!("unexpected incoherent type: {:?}", self_ty) }; - for &impl_def_id in self.tcx.incoherent_impls(simp) { + for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() { self.assemble_inherent_impl_probe(impl_def_id); } } fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) { - let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id); - for &impl_def_id in impl_def_ids.iter() { + let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten(); + for &impl_def_id in impl_def_ids { self.assemble_inherent_impl_probe(impl_def_id); } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3bf1e1312b31..0b8a25eedafa 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -359,7 +359,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(adt_def, _) = ty.kind() { self.tcx .inherent_impls(adt_def.did()) - .iter() + .into_iter() + .flatten() .any(|def_id| self.associated_value(*def_id, item_name).is_some()) } else { false @@ -1048,7 +1049,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut inherent_impls_candidate = self .tcx .inherent_impls(adt.did()) - .iter() + .into_iter() + .flatten() .copied() .filter(|def_id| { if let Some(assoc) = self.associated_value(*def_id, item_name) { @@ -1103,7 +1105,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the {item_kind} was found for\n{type_candidates}{additional_types}" )); } else { - 'outer: for inherent_impl_did in self.tcx.inherent_impls(adt.did()) { + 'outer: for inherent_impl_did in + self.tcx.inherent_impls(adt.did()).into_iter().flatten() + { for inherent_method in self.tcx.associated_items(inherent_impl_did).in_definition_order() { @@ -1457,9 +1461,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Adt(adt_def, _) = rcvr_ty.kind() else { return; }; - let mut items = self - .tcx - .inherent_impls(adt_def.did()) + // FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case. + let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return }; + let mut items = impls .iter() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. @@ -1823,7 +1827,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { simplify_type(tcx, ty, TreatParams::AsCandidateKey) .and_then(|simp| { tcx.incoherent_impls(simp) - .iter() + .into_iter() + .flatten() .find_map(|&id| self.associated_value(id, item_name)) }) .is_some() diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 912c2f36eb3c..c3d6c21c4027 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -283,7 +283,7 @@ provide! { tcx, def_id, other, cdata, tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index)) } associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) } - inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } + inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) } item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } @@ -328,7 +328,7 @@ provide! { tcx, def_id, other, cdata, traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) } trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) } implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } - crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) } + crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) } dep_kind => { cdata.dep_kind } module_children => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a458b528a97c..2d4e49e27d9b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1485,7 +1485,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } let inherent_impls = tcx.with_stable_hashing_context(|hcx| { - tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true) + tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true) }); for (def_id, impls) in inherent_impls { record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| { @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { empty_proc_macro!(self); let tcx = self.tcx; let all_impls = tcx.with_stable_hashing_context(|hcx| { - tcx.crate_inherent_impls(()).incoherent_impls.to_sorted(&hcx, true) + tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true) }); let all_impls: Vec<_> = all_impls diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 8a4fd01437f9..e745913fabc3 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -114,6 +114,7 @@ macro_rules! arena_types { [] mod_child: rustc_middle::metadata::ModChild, [] features: rustc_feature::Features, [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph, + [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, ]); ) } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b9200f1abf16..a49825bdd708 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -78,6 +78,10 @@ impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::>()]; } +impl EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Result<&'_ T, traits::CodegenObligationError> { type Result = [u8; size_of::>()]; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 15f0dc0208d5..b3aa02e1aa38 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -859,13 +859,13 @@ rustc_queries! { /// Maps a `DefId` of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. - query inherent_impls(key: DefId) -> &'tcx [DefId] { + query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } - query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { + query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting all inherent impls for `{:?}`", key } } @@ -1012,9 +1012,9 @@ rustc_queries! { /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls { - arena_cache + query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> { desc { "finding all inherent impls defined in crate" } + ensure_forwards_result_if_red } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. @@ -1647,7 +1647,7 @@ rustc_queries! { /// /// Do not call this directly, but instead use the `incoherent_impls` query. /// This query is only used to get the data necessary for that query. - query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { + query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting all impls for a type in a crate" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index a41d4f1ad589..8d88488e1675 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -174,7 +174,7 @@ pub fn query_ensure<'tcx, Cache>( } #[inline] -pub fn query_ensure_error_guaranteed<'tcx, Cache>( +pub fn query_ensure_error_guaranteed<'tcx, Cache, T>( tcx: TyCtxt<'tcx>, execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option, query_cache: &Cache, @@ -182,14 +182,16 @@ pub fn query_ensure_error_guaranteed<'tcx, Cache>( check_cache: bool, ) -> Result<(), ErrorGuaranteed> where - Cache: QueryCache>>, + Cache: QueryCache>>, + Result: EraseType, { let key = key.into_query_param(); if let Some(res) = try_get_cached(tcx, query_cache, &key) { - super::erase::restore(res) + super::erase::restore(res).map(drop) } else { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }) .map(super::erase::restore) + .map(|res| res.map(drop)) // Either we actually executed the query, which means we got a full `Result`, // or we can just assume the query succeeded, because it was green in the // incremental cache. If it is green, that means that the previous compilation @@ -205,7 +207,7 @@ macro_rules! query_ensure { query_ensure($($args)*) }; ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => { - query_ensure_error_guaranteed($($args)*) + query_ensure_error_guaranteed($($args)*).map(|_| ()) }; ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { query_ensure!([$($modifiers)*]$($args)*) @@ -667,5 +669,7 @@ mod sealed { pub use sealed::IntoQueryParam; +use super::erase::EraseType; + #[derive(Copy, Clone, Debug, HashStable)] pub struct CyclePlaceholder(pub ErrorGuaranteed); diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 227a0753d042..d85b541d3638 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -254,16 +254,28 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait } /// Query provider for `incoherent_impls`. -pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { +pub(super) fn incoherent_impls_provider( + tcx: TyCtxt<'_>, + simp: SimplifiedType, +) -> Result<&[DefId], ErrorGuaranteed> { let mut impls = Vec::new(); + let mut res = Ok(()); for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { - for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) { + let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) { + Ok(impls) => impls, + Err(e) => { + res = Err(e); + continue; + } + }; + for &impl_def_id in incoherent_impls { impls.push(impl_def_id) } } debug!(?impls); + res?; - tcx.arena.alloc_slice(&impls) + Ok(tcx.arena.alloc_slice(&impls)) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 070580860c16..20e70f87b75e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1433,7 +1433,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt } fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option { - for impl_def_id in tcx.inherent_impls(def_id) { + for impl_def_id in tcx.inherent_impls(def_id).ok()? { if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind( tcx, fn_ident, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 58ff4d8c7934..5a95f2083f66 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1745,12 +1745,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // Doing analysis on local `DefId`s would cause infinite recursion. return; } + let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return }; // Look at all the associated functions without receivers in the type's // inherent impls to look for builders that return `Self` - let mut items = self - .r - .tcx - .inherent_impls(def_id) + let mut items = impls .iter() .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 014bcb1a8817..aab974ad79ed 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -312,7 +312,7 @@ pub(crate) fn build_impls( let tcx = cx.tcx; // for each implementation of an item represented by `did`, build the clean::Item for that impl - for &did in tcx.inherent_impls(did).iter() { + for &did in tcx.inherent_impls(did).into_iter().flatten() { build_impl(cx, did, attrs, ret); } @@ -325,7 +325,7 @@ pub(crate) fn build_impls( if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; - for &did in tcx.incoherent_impls(type_) { + for &did in tcx.incoherent_impls(type_).into_iter().flatten() { build_impl(cx, did, attrs, ret); } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 90eb783c7cae..6710193f9611 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1862,7 +1862,7 @@ impl PrimitiveType { .get(self) .into_iter() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten()) .copied() } @@ -1870,7 +1870,7 @@ impl PrimitiveType { Self::simplified_types() .values() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten()) .copied() } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index dbff33dc1ecf..30b3e5c784dc 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -624,7 +624,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Checks if item_name belongs to `impl SomeItem` let mut assoc_items: Vec<_> = tcx .inherent_impls(did) - .iter() + .into_iter() + .flatten() .flat_map(|&imp| { filter_assoc_items_by_name_and_namespace( tcx, From 18e66432c40e8c136b5d0fab27137fdabd579ae0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 16:58:29 +0000 Subject: [PATCH 216/297] Fix clippy --- src/tools/clippy/clippy_lints/src/derive.rs | 3 ++- src/tools/clippy/clippy_lints/src/inherent_impl.rs | 3 ++- .../clippy/clippy_lints/src/iter_without_into_iter.rs | 2 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 5 +++-- src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs | 3 ++- src/tools/clippy/clippy_utils/src/lib.rs | 8 +++++--- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index d8abe411030b..d1fe9f5cbece 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -386,7 +386,8 @@ fn check_unsafe_derive_deserialize<'tcx>( && cx .tcx .inherent_impls(def.did()) - .iter() + .into_iter() + .flatten() .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) .any(|imp| has_unsafe(cx, imp)) { diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index e4781752e757..fb7b82ec304e 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -53,9 +53,10 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { // List of spans to lint. (lint_span, first_span) let mut lint_spans = Vec::new(); + let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { return }; let inherent_impls = cx .tcx - .with_stable_hashing_context(|hcx| cx.tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)); + .with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true)); for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| { impls.len() > 1 diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 903d3a2ab896..82a37bb4f278 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -139,7 +139,7 @@ fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iter fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool { if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) { - cx.tcx.inherent_impls(ty_did).iter().any(|&did| { + cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| { cx.tcx .associated_items(did) .filter_by_name_unhygienic(method_name) diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index c09d3d1862b0..c1ab020117ca 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -441,7 +441,8 @@ fn check_for_is_empty( let is_empty = cx .tcx .inherent_impls(impl_ty) - .iter() + .into_iter() + .flatten() .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty)) .find(|item| item.kind == AssocKind::Fn); @@ -605,7 +606,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Checks the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool { let is_empty = sym!(is_empty); - cx.tcx.inherent_impls(id).iter().any(|imp| { + cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| { cx.tcx .associated_items(*imp) .filter_by_name_unhygienic(is_empty) diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index e38c66f6741d..0602eeaa7041 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -73,7 +73,8 @@ pub(super) fn check<'tcx>( let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| { cx.tcx .inherent_impls(adt_def.did()) - .iter() + .into_iter() + .flatten() .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) .any(|assoc| { assoc.fn_has_self_parameter diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index cdf8528f48a2..1a4b22799f2a 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -534,10 +534,11 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator SimplifiedType::Uint(UintTy::U128), "f32" => SimplifiedType::Float(FloatTy::F32), "f64" => SimplifiedType::Float(FloatTy::F64), - _ => return [].iter().copied(), + #[allow(trivial_casts)] + _ => return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_]).into_iter().flatten().copied(), }; - tcx.incoherent_impls(ty).iter().copied() + tcx.incoherent_impls(ty).into_iter().flatten().copied() } fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec { @@ -663,7 +664,8 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec { // `impl S { ... }` let inherent_impl_children = tcx .inherent_impls(def_id) - .iter() + .into_iter() + .flatten() .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment)); let direct_children = item_children_by_name(tcx, def_id, segment); From 12c19a2bb777a87c10afe1a7ea7fbee00def730d Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 17 Jan 2024 10:38:50 +0000 Subject: [PATCH 217/297] target: fix powerpc64-unknown-linux-musl datalayout In LLVM 17, PowerPC targets started including function pointer alignments in data layouts, and in Rust's update to that version (#114048), we added the function pointer alignments. `powerpc64-unknown-linux-musl` had `Fi64` set but this seems incorrect, and the code in LLVM would always have computed `Fn32` because it is a MUSL target. Signed-off-by: David Wood --- .../src/spec/targets/powerpc64_unknown_linux_musl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index e2e707f4a1ac..90df3c696846 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(), + data_layout: "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(), arch: "powerpc64".into(), options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base }, } From d6b99b9c920f3c12326b0e7110236e9fe7c7ba52 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jan 2024 14:23:41 +0000 Subject: [PATCH 218/297] Use FnOnceOutput instead of FnOnce where expected --- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../opaque-used-in-extraneous-argument.rs | 21 +++++ .../opaque-used-in-extraneous-argument.stderr | 78 +++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs create mode 100644 tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6c9000c45f61..4028de27cae1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1013,7 +1013,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { .extend( // Group the return ty with its def id, if we had one. entry.return_ty.map(|ty| { - (tcx.require_lang_item(LangItem::FnOnce, None), ty) + (tcx.require_lang_item(LangItem::FnOnceOutput, None), ty) }), ); } diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs new file mode 100644 index 000000000000..529913479ef4 --- /dev/null +++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs @@ -0,0 +1,21 @@ +//! This is a regression test to avoid an ICE in diagnostics code. +//! A typo in the compiler used to get the DefId of FnOnce, and +//! use it where an associated item was expected. + +fn frob() -> impl Fn + '_ {} +//~^ ERROR missing lifetime specifier +//~| ERROR cannot find type `P` +//~| ERROR cannot find type `T` +//~| ERROR `Fn`-family traits' type parameters is subject to change + +fn open_parent<'path>() { + todo!() +} + +fn main() { + let old_path = frob("hello"); + //~^ ERROR function takes 0 arguments + + open_parent(&old_path) + //~^ ERROR function takes 0 arguments +} diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr new file mode 100644 index 000000000000..b54b9f908b2a --- /dev/null +++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr @@ -0,0 +1,78 @@ +error[E0106]: missing lifetime specifier + --> $DIR/opaque-used-in-extraneous-argument.rs:5:39 + | +LL | fn frob() -> impl Fn + '_ {} + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values + | +LL | fn frob() -> impl Fn + 'static {} + | ~~~~~~~ + +error[E0412]: cannot find type `P` in this scope + --> $DIR/opaque-used-in-extraneous-argument.rs:5:22 + | +LL | fn frob() -> impl Fn + '_ {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn frob

() -> impl Fn + '_ {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/opaque-used-in-extraneous-argument.rs:5:34 + | +LL | fn frob() -> impl Fn + '_ {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn frob() -> impl Fn + '_ {} + | +++ + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/opaque-used-in-extraneous-argument.rs:5:19 + | +LL | fn frob() -> impl Fn + '_ {} + | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(P) -> T` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/opaque-used-in-extraneous-argument.rs:16:20 + | +LL | let old_path = frob("hello"); + | ^^^^ ------- + | | + | unexpected argument of type `&'static str` + | help: remove the extra argument + | +note: function defined here + --> $DIR/opaque-used-in-extraneous-argument.rs:5:4 + | +LL | fn frob() -> impl Fn + '_ {} + | ^^^^ + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/opaque-used-in-extraneous-argument.rs:19:5 + | +LL | open_parent(&old_path) + | ^^^^^^^^^^^ --------- + | | + | unexpected argument of type `&impl FnOnce<{type error}, Output = {type error}> + Fn<{type error}> + 'static` + | help: remove the extra argument + | +note: function defined here + --> $DIR/opaque-used-in-extraneous-argument.rs:11:4 + | +LL | fn open_parent<'path>() { + | ^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0106, E0412, E0658. +For more information about an error, try `rustc --explain E0061`. From 8507f5105bb5294d802c38918b0b21916b376c16 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Thu, 11 Jan 2024 01:36:05 +0700 Subject: [PATCH 219/297] Improved collapse_debuginfo attribute, added command-line flag (no|external|yes) --- compiler/rustc_expand/messages.ftl | 3 + compiler/rustc_expand/src/base.rs | 56 +++++++++++++++++- compiler/rustc_expand/src/errors.rs | 7 +++ compiler/rustc_expand/src/mbe/macro_rules.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_interface/src/tests.rs | 9 +-- compiler/rustc_metadata/src/rmeta/decoder.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_session/src/config.rs | 32 +++++++++-- compiler/rustc_session/src/options.rs | 17 ++++++ compiler/rustc_span/src/hygiene.rs | 19 +++++-- compiler/rustc_span/src/symbol.rs | 2 + .../collapse-debuginfo-external-attr.rs | 31 ++++++++++ ...buginfo-external-flag-overriden-by-attr.rs | 34 +++++++++++ .../collapse-debuginfo-external-flag.rs | 26 +++++++++ tests/debuginfo/collapse-debuginfo-no-attr.rs | 2 +- .../collapse-debuginfo-with-yes-flag.rs | 57 +++++++++++++++++++ 17 files changed, 281 insertions(+), 21 deletions(-) create mode 100644 tests/debuginfo/collapse-debuginfo-external-attr.rs create mode 100644 tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs create mode 100644 tests/debuginfo/collapse-debuginfo-external-flag.rs create mode 100644 tests/debuginfo/collapse-debuginfo-with-yes-flag.rs diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 475dd348e7b6..3e3b48143004 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -16,6 +16,9 @@ expand_attributes_wrong_form = expand_cannot_be_name_of_macro = `{$trait_ident}` cannot be a name of {$macro_type} macro +expand_collapse_debuginfo_illegal = + illegal value for attribute #[collapse_debuginfo(no|external|yes)] + expand_count_repetition_misplaced = `count` can not be placed inside the inner-most repetition diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0a1c44303970..edc9c5a9130a 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] +use crate::base::ast::NestedMetaItem; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; @@ -19,6 +20,7 @@ use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools}; use rustc_parse::{parser, MACRO_ARGUMENTS}; +use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; @@ -761,6 +763,55 @@ impl SyntaxExtension { } } + fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo { + use crate::errors::CollapseMacroDebuginfoIllegal; + // #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)]) + // considered as `yes` + attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| { + let [NestedMetaItem::MetaItem(item)] = &l[..] else { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span }); + return CollapseMacroDebuginfo::Unspecified; + }; + if !item.is_word() { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span }); + CollapseMacroDebuginfo::Unspecified + } else { + match item.name_or_empty() { + sym::no => CollapseMacroDebuginfo::No, + sym::external => CollapseMacroDebuginfo::External, + sym::yes => CollapseMacroDebuginfo::Yes, + _ => { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span }); + CollapseMacroDebuginfo::Unspecified + } + } + } + }) + } + + /// if-ext - if macro from different crate (related to callsite code) + /// | cmd \ attr | no | (unspecified) | external | yes | + /// | no | no | no | no | no | + /// | (unspecified) | no | no | if-ext | yes | + /// | external | no | if-ext | if-ext | yes | + /// | yes | yes | yes | yes | yes | + fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool { + let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo) + .map(|v| Self::collapse_debuginfo_by_name(sess, v)) + .unwrap_or(CollapseMacroDebuginfo::Unspecified); + let flag = sess.opts.unstable_opts.collapse_macro_debuginfo; + let attr = collapse_debuginfo_attr; + let ext = !is_local; + #[rustfmt::skip] + let collapse_table = [ + [false, false, false, false], + [false, false, ext, true], + [false, ext, ext, true], + [true, true, true, true], + ]; + collapse_table[flag as usize][attr as usize] + } + /// Constructs a syntax extension with the given properties /// and other properties converted from attributes. pub fn new( @@ -772,6 +823,7 @@ impl SyntaxExtension { edition: Edition, name: Symbol, attrs: &[ast::Attribute], + is_local: bool, ) -> SyntaxExtension { let allow_internal_unstable = attr::allow_internal_unstable(sess, attrs).collect::>(); @@ -780,8 +832,8 @@ impl SyntaxExtension { let local_inner_macros = attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros)); - let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo); - tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); + let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local); + tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro) .map(|attr| { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 2b43fae6852a..4a1c00f0104f 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -58,6 +58,13 @@ pub(crate) struct ResolveRelativePath { pub path: String, } +#[derive(Diagnostic)] +#[diag(expand_collapse_debuginfo_illegal)] +pub(crate) struct CollapseMacroDebuginfoIllegal { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(expand_macro_const_stability)] pub(crate) struct MacroConstStability { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 363b52aef8a7..1a39708ed8ed 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -367,6 +367,7 @@ pub fn compile_declarative_macro( edition, def.ident.name, &def.attrs, + def.id != DUMMY_NODE_ID, ) }; let dummy_syn_ext = || (mk_syn_ext(Box::new(macro_rules_dummy_expander)), Vec::new()); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4442b67df6e2..68b6f69854dd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -469,7 +469,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // `#[collapse_debuginfo]` gated!( - collapse_debuginfo, Normal, template!(Word), WarnFollowing, + collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing, experimental!(collapse_debuginfo) ), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 588139a303c5..555c822ad6d6 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,10 +4,10 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, - FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, - LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, - Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + CollapseMacroDebuginfo, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, + ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, + InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, + OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; @@ -742,6 +742,7 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); + tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 49e849964be4..20e3ae3ba949 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1027,6 +1027,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.edition, Symbol::intern(name), &attrs, + false, ) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ad9296a4cc88..a5d9e0fcf44c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2535,8 +2535,7 @@ impl<'tcx> TyCtxt<'tcx> { if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() { return span; } - let collapse_debuginfo_enabled = self.features().collapse_debuginfo; - hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled) + hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo) } #[inline] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ac15c3b407b2..e751ff13a34c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3190,12 +3190,12 @@ pub enum WasiExecModel { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, - LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, - OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, - SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - WasiExecModel, + BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo, + DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold, + InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, + NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, + RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3274,6 +3274,7 @@ pub(crate) mod dep_tracking { LtoCli, DebugInfo, DebugInfoCompression, + CollapseMacroDebuginfo, UnstableFeatures, NativeLib, SanitizerSet, @@ -3437,6 +3438,25 @@ pub enum ProcMacroExecutionStrategy { CrossThread, } +/// How to perform collapse macros debug info +/// if-ext - if macro from different crate (related to callsite code) +/// | cmd \ attr | no | (unspecified) | external | yes | +/// | no | no | no | no | no | +/// | (unspecified) | no | no | if-ext | yes | +/// | external | no | if-ext | if-ext | yes | +/// | yes | yes | yes | yes | yes | +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum CollapseMacroDebuginfo { + /// Don't collapse debuginfo for the macro + No = 0, + /// Unspecified value + Unspecified = 1, + /// Collapse debuginfo if the macro comes from a different crate + External = 2, + /// Collapse debuginfo for the macro + Yes = 3, +} + /// Which format to use for `-Z dump-mono-stats` #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum DumpMonoStatsFormat { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f4bf79f93f28..6c91929fcbe4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -388,6 +388,7 @@ mod desc { pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; + pub const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -1302,6 +1303,19 @@ mod parse { true } + pub(crate) fn parse_collapse_macro_debuginfo( + slot: &mut CollapseMacroDebuginfo, + v: Option<&str>, + ) -> bool { + *slot = match v { + Some("no") => CollapseMacroDebuginfo::No, + Some("external") => CollapseMacroDebuginfo::External, + Some("yes") => CollapseMacroDebuginfo::Yes, + _ => return false, + }; + true + } + pub(crate) fn parse_proc_macro_execution_strategy( slot: &mut ProcMacroExecutionStrategy, v: Option<&str>, @@ -1534,6 +1548,9 @@ options! { "instrument control-flow architecture protection"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), + collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified, + parse_collapse_macro_debuginfo, [TRACKED], + "set option to collapse debuginfo for macros"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index d03965b539c8..21623fdc1d23 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -464,12 +464,15 @@ impl HygieneData { &self, mut span: Span, to: Span, - collapse_debuginfo_enabled: bool, + collapse_debuginfo_feature_enabled: bool, ) -> Span { let orig_span = span; let mut ret_span = span; - debug!("walk_chain_collapsed({:?}, {:?})", span, to); + debug!( + "walk_chain_collapsed({:?}, {:?}), feature_enable={}", + span, to, collapse_debuginfo_feature_enabled, + ); debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt()); while !span.eq_ctxt(to) && span.from_expansion() { let outer_expn = self.outer_expn(span.ctxt()); @@ -477,7 +480,7 @@ impl HygieneData { let expn_data = self.expn_data(outer_expn); debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data); span = expn_data.call_site; - if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo { + if !collapse_debuginfo_feature_enabled || expn_data.collapse_debuginfo { ret_span = span; } } @@ -601,8 +604,14 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { HygieneData::with(|data| data.walk_chain(span, to)) } -pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span { - HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled)) +pub fn walk_chain_collapsed( + span: Span, + to: Span, + collapse_debuginfo_feature_enabled: bool, +) -> Span { + HygieneData::with(|hdata| { + hdata.walk_chain_collapsed(span, to, collapse_debuginfo_feature_enabled) + }) } pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 72b62a795fc5..44795022cbab 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -749,6 +749,7 @@ symbols! { extern_in_paths, extern_prelude, extern_types, + external, external_doc, f, f16c_target_feature, @@ -1811,6 +1812,7 @@ symbols! { xmm_reg, yeet_desugar_details, yeet_expr, + yes, yield_expr, ymm_reg, zmm_reg, diff --git a/tests/debuginfo/collapse-debuginfo-external-attr.rs b/tests/debuginfo/collapse-debuginfo-external-attr.rs new file mode 100644 index 000000000000..f36b0833ad51 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-attr.rs @@ -0,0 +1,31 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that local macro debug info is not collapsed with #[collapse_debuginfo(external)] + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#one_callsite[...] +// gdb-command:continue + +fn one() { + println!("one"); +} + +#[collapse_debuginfo(external)] +macro_rules! outer { + () => { + one(); // #one_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs b/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs new file mode 100644 index 000000000000..e5cbc1a685d0 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs @@ -0,0 +1,34 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that macro attribute #[collapse_debuginfo(no)] +// overrides "collapse_macro_debuginfo=external" flag + +// compile-flags:-g -Z collapse_macro_debuginfo=external + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#one_callsite[...] +// gdb-command:next +// gdb-command:frame +// gdb-command:continue + +fn one() { + println!("one"); +} + +#[collapse_debuginfo(no)] +macro_rules! outer { + () => { + one(); // #one_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-external-flag.rs b/tests/debuginfo/collapse-debuginfo-external-flag.rs new file mode 100644 index 000000000000..9a0aef38ea6c --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-flag.rs @@ -0,0 +1,26 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that println macro debug info is collapsed with "collapse_macro_debuginfo=external" flag + +// compile-flags:-g -Z collapse_macro_debuginfo=external + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#println_callsite[...] +// gdb-command:continue + +macro_rules! outer { + () => { + println!("one"); // #println_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-no-attr.rs b/tests/debuginfo/collapse-debuginfo-no-attr.rs index 230c8795be36..d156c381a150 100644 --- a/tests/debuginfo/collapse-debuginfo-no-attr.rs +++ b/tests/debuginfo/collapse-debuginfo-no-attr.rs @@ -4,7 +4,7 @@ // Test that line numbers are not replaced with those of the outermost expansion site when the // `collapse_debuginfo` feature is active and the attribute is not provided. -// compile-flags:-g +// compile-flags:-g -Z collapse_macro_debuginfo=no // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs b/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs new file mode 100644 index 000000000000..76a97a325d7e --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs @@ -0,0 +1,57 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that line numbers are replaced with those of the outermost expansion site when the +// `collapse_debuginfo` feature is active and the command line flag is provided. + +// compile-flags:-g -Z collapse_macro_debuginfo=yes + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc1[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc2[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc3[...] +// gdb-command:continue + +fn one() { + println!("one"); +} +fn two() { + println!("two"); +} +fn three() { + println!("three"); +} +fn four() { + println!("four"); +} + +macro_rules! outer { + ($b:block) => { + one(); + inner!(); + $b + }; +} + +macro_rules! inner { + () => { + two(); + }; +} + +fn main() { + let ret = 0; // #break + outer!({ // #loc1 + three(); // #loc2 + four(); // #loc3 + }); + std::process::exit(ret); +} From f1ef930c9d06ebd8a3839346b493f49d40fa69e5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jan 2024 14:52:38 +0000 Subject: [PATCH 220/297] Don't ICE when deducing future output if other errors already occurred --- compiler/rustc_hir_typeck/src/closure.rs | 14 +++++++--- .../inference_var_self_argument.rs | 12 ++++++++ .../inference_var_self_argument.stderr | 28 +++++++++++++++++++ tests/ui/object-safety/erroneous_signature.rs | 17 +++++++++++ .../object-safety/erroneous_signature.stderr | 15 ++++++++++ 5 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 tests/ui/async-await/inference_var_self_argument.rs create mode 100644 tests/ui/async-await/inference_var_self_argument.stderr create mode 100644 tests/ui/object-safety/erroneous_signature.rs create mode 100644 tests/ui/object-safety/erroneous_signature.stderr diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 57fdfa4ecb6e..8a08ee21fbeb 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -760,16 +760,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { get_future_output(obligation.predicate, obligation.cause.span) })? } + ty::Alias(ty::Projection, _) => { + return Some(Ty::new_error_with_message( + self.tcx, + closure_span, + "this projection should have been projected to an opaque type", + )); + } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self .tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, ty::Error(_) => return Some(ret_ty), - _ => span_bug!( - closure_span, - "async fn coroutine return type not an inference variable: {ret_ty}" - ), + _ => { + span_bug!(closure_span, "invalid async fn coroutine return type: {ret_ty:?}") + } }; let output_ty = self.normalize(closure_span, output_ty); diff --git a/tests/ui/async-await/inference_var_self_argument.rs b/tests/ui/async-await/inference_var_self_argument.rs new file mode 100644 index 000000000000..fd8482f86b4f --- /dev/null +++ b/tests/ui/async-await/inference_var_self_argument.rs @@ -0,0 +1,12 @@ +//! This is a regression test for an ICE. +// edition: 2021 + +trait Foo { + async fn foo(self: &dyn Foo) { + //~^ ERROR: `Foo` cannot be made into an object + //~| ERROR invalid `self` parameter type: &dyn Foo + todo!() + } +} + +fn main() {} diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr new file mode 100644 index 000000000000..8a8c1ea03f14 --- /dev/null +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -0,0 +1,28 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/inference_var_self_argument.rs:5:5 + | +LL | async fn foo(self: &dyn Foo) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/inference_var_self_argument.rs:5:14 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | async fn foo(self: &dyn Foo) { + | ^^^ ...because method `foo` is `async` + = help: consider moving `foo` to another trait + +error[E0307]: invalid `self` parameter type: &dyn Foo + --> $DIR/inference_var_self_argument.rs:5:24 + | +LL | async fn foo(self: &dyn Foo) { + | ^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0307. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/erroneous_signature.rs b/tests/ui/object-safety/erroneous_signature.rs new file mode 100644 index 000000000000..cc1841cc4b2a --- /dev/null +++ b/tests/ui/object-safety/erroneous_signature.rs @@ -0,0 +1,17 @@ +trait Foo { + fn err(&self) -> MissingType; + //~^ ERROR cannot find type `MissingType` in this scope +} + +impl Foo for i32 { + fn err(&self) -> MissingType { + //~^ ERROR cannot find type `MissingType` in this scope + 0 + } +} + +fn coerce(x: &i32) -> &dyn Foo { + x +} + +fn main() {} diff --git a/tests/ui/object-safety/erroneous_signature.stderr b/tests/ui/object-safety/erroneous_signature.stderr new file mode 100644 index 000000000000..f3b14ffe34c3 --- /dev/null +++ b/tests/ui/object-safety/erroneous_signature.stderr @@ -0,0 +1,15 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/erroneous_signature.rs:2:22 + | +LL | fn err(&self) -> MissingType; + | ^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/erroneous_signature.rs:7:22 + | +LL | fn err(&self) -> MissingType { + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. From c70773d8a17438194c2415b91d81206ed10480a2 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 17 Jan 2024 14:47:59 -0500 Subject: [PATCH 221/297] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 1cff2ee6b92e..1ae631085f01 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 1cff2ee6b92e0ad3f87c44b70b28f788b2528b3c +Subproject commit 1ae631085f01c1a72d05df1ec81f3759a8360042 From c48cdfe8ee582e3e67c9ffc036d8046add812565 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 14 Jan 2024 16:25:43 -0800 Subject: [PATCH 222/297] Remove unnecessary `let`s and borrowing from `Waker::noop()` usage. `Waker::noop()` now returns a `&'static Waker` reference, so it can be passed directly to `Context` creation with no temporary lifetime issue. --- library/core/tests/async_iter/mod.rs | 3 +-- src/tools/miri/tests/pass/async-fn.rs | 3 +-- src/tools/miri/tests/pass/dyn-star.rs | 3 +-- src/tools/miri/tests/pass/future-self-referential.rs | 6 ++---- src/tools/miri/tests/pass/issues/issue-miri-2068.rs | 3 +-- src/tools/miri/tests/pass/move-data-across-await-point.rs | 3 +-- tests/coverage/async.coverage | 3 +-- tests/coverage/async.rs | 3 +-- tests/coverage/async2.coverage | 3 +-- tests/coverage/async2.rs | 3 +-- tests/coverage/async_block.coverage | 3 +-- tests/coverage/async_block.rs | 3 +-- tests/coverage/closure_macro_async.coverage | 3 +-- tests/coverage/closure_macro_async.rs | 3 +-- tests/ui/async-await/for-await-passthrough.rs | 3 +-- tests/ui/async-await/for-await.rs | 3 +-- .../ui/async-await/in-trait/async-default-fn-overridden.rs | 3 +-- .../in-trait/dont-project-to-specializable-projection.rs | 3 +-- .../dont-project-to-specializable-projection.stderr | 2 +- tests/ui/coroutine/async-gen-yield-ty-is-unit.rs | 3 +-- tests/ui/coroutine/async_gen_fn_iter.rs | 3 +-- tests/ui/dyn-star/dispatch-on-pin-mut.rs | 5 ++--- 22 files changed, 24 insertions(+), 46 deletions(-) diff --git a/library/core/tests/async_iter/mod.rs b/library/core/tests/async_iter/mod.rs index 0c30bd1dfeac..4f425d7286d0 100644 --- a/library/core/tests/async_iter/mod.rs +++ b/library/core/tests/async_iter/mod.rs @@ -7,8 +7,7 @@ fn into_async_iter() { let async_iter = async_iter::from_iter(0..3); let mut async_iter = pin!(async_iter.into_async_iter()); - let waker = core::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(core::task::Waker::noop()); assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(0))); assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(1))); diff --git a/src/tools/miri/tests/pass/async-fn.rs b/src/tools/miri/tests/pass/async-fn.rs index 6c92735df0af..13400c88c711 100644 --- a/src/tools/miri/tests/pass/async-fn.rs +++ b/src/tools/miri/tests/pass/async-fn.rs @@ -76,8 +76,7 @@ async fn uninhabited_variant() { fn run_fut(fut: impl Future) -> T { use std::task::{Context, Poll, Waker}; - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); let mut pinned = Box::pin(fut); loop { diff --git a/src/tools/miri/tests/pass/dyn-star.rs b/src/tools/miri/tests/pass/dyn-star.rs index 8e26c4850fa8..dab589b46518 100644 --- a/src/tools/miri/tests/pass/dyn-star.rs +++ b/src/tools/miri/tests/pass/dyn-star.rs @@ -93,8 +93,7 @@ fn dispatch_on_pin_mut() { let mut fut = async_main(); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { diff --git a/src/tools/miri/tests/pass/future-self-referential.rs b/src/tools/miri/tests/pass/future-self-referential.rs index 38cb700fd584..8aeb26a7a957 100644 --- a/src/tools/miri/tests/pass/future-self-referential.rs +++ b/src/tools/miri/tests/pass/future-self-referential.rs @@ -77,8 +77,7 @@ impl Future for DoStuff { } fn run_fut(fut: impl Future) -> T { - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); let mut pinned = pin!(fut); loop { @@ -90,8 +89,7 @@ fn run_fut(fut: impl Future) -> T { } fn self_referential_box() { - let waker = Waker::noop(); - let cx = &mut Context::from_waker(&waker); + let cx = &mut Context::from_waker(Waker::noop()); async fn my_fut() -> i32 { let val = 10; diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs index f18c4a3a0655..ccee2221e295 100644 --- a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs +++ b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs @@ -6,8 +6,7 @@ use std::task::{Context, Poll, Waker}; pub fn fuzzing_block_on>(fut: F) -> O { let mut fut = std::pin::pin!(fut); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(&mut context) { Poll::Ready(v) => return v, diff --git a/src/tools/miri/tests/pass/move-data-across-await-point.rs b/src/tools/miri/tests/pass/move-data-across-await-point.rs index 9bea6ea57420..1a93a6bf6649 100644 --- a/src/tools/miri/tests/pass/move-data-across-await-point.rs +++ b/src/tools/miri/tests/pass/move-data-across-await-point.rs @@ -56,8 +56,7 @@ fn data_moved() { fn run_fut(fut: impl Future) -> T { use std::task::{Context, Poll, Waker}; - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); let mut pinned = Box::pin(fut); loop { diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 015e03d5165f..231614588500 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -117,8 +117,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index abc9e5f7f646..df29682968d3 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -110,8 +110,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index acd83de94934..a69eefe72cbc 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -41,8 +41,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs index 393573f7dc95..ae83f0103e64 100644 --- a/tests/coverage/async2.rs +++ b/tests/coverage/async2.rs @@ -39,8 +39,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index 297397ca26c8..0e24b80124f4 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -24,8 +24,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs index 9d8647bf1f20..f94bcfe31937 100644 --- a/tests/coverage/async_block.rs +++ b/tests/coverage/async_block.rs @@ -23,8 +23,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 2c9bd4ac97a1..2336d4d0528c 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -54,8 +54,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index a7f0cabb4c23..9f5721b5e266 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -53,8 +53,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs index 7fa133aaedcd..b1a382958a15 100644 --- a/tests/ui/async-await/for-await-passthrough.rs +++ b/tests/ui/async-await/for-await-passthrough.rs @@ -25,8 +25,7 @@ async fn real_main() { fn main() { let future = real_main(); - let waker = std::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop()); let mut future = core::pin::pin!(future); while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} } diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs index 6345ceb0c279..00dbdfb2389d 100644 --- a/tests/ui/async-await/for-await.rs +++ b/tests/ui/async-await/for-await.rs @@ -17,8 +17,7 @@ async fn real_main() { fn main() { let future = real_main(); - let waker = std::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop()); let mut future = core::pin::pin!(future); while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} } diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 491dfcc6ae0f..8c01f1bddefd 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -40,8 +40,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs index f21abf012ba9..e2fd9f9dfea4 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs @@ -43,8 +43,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr index 0560cd9c5fe1..b7336485eb84 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -21,7 +21,7 @@ LL | default async fn foo(_: T) -> &'static str { = note: specialization behaves in inconsistent and surprising ways with async functions in traits, and for now is disallowed error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future>` in the current scope - --> $DIR/dont-project-to-specializable-projection.rs:50:28 + --> $DIR/dont-project-to-specializable-projection.rs:49:28 | LL | match fut.as_mut().poll(ctx) { | ^^^^ method not found in `Pin<&mut impl Future>` diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index aac74d3eacba..80c0b69a6f7e 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -11,7 +11,6 @@ async gen fn gen_fn() -> &'static str { pub fn main() { let async_iterator = pin!(gen_fn()); - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); async_iterator.poll_next(ctx); } diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs index ec6464d00487..604156b4d373 100644 --- a/tests/ui/coroutine/async_gen_fn_iter.rs +++ b/tests/ui/coroutine/async_gen_fn_iter.rs @@ -74,8 +74,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.rs b/tests/ui/dyn-star/dispatch-on-pin-mut.rs index c4ae279e6c11..151aa9092fbe 100644 --- a/tests/ui/dyn-star/dispatch-on-pin-mut.rs +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.rs @@ -19,15 +19,14 @@ async fn async_main() { // ------------------------------------------------------------------------- // // Implementation Details Below... -use std::task::*; use std::pin::pin; +use std::task::*; fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { From eb8c1f899818273490d32585d03c1bb74263472d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 17 Jan 2024 18:02:14 -0300 Subject: [PATCH 223/297] Remove spastorino from users_on_vacation --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 2b818c0a990d..bd14640e280e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -631,7 +631,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "spastorino"] +users_on_vacation = ["jyn514"] [assign.adhoc_groups] compiler-team = [ From b9ebeee4da258f1ed8bb93f0273180572a839058 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 17 Jan 2024 21:16:22 +0000 Subject: [PATCH 224/297] Remove `box ` recovery --- compiler/rustc_parse/src/parser/expr.rs | 28 +++++++------------------ 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8ca02452342b..a1e4fc7876dc 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -33,7 +33,6 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::source_map::{self, Spanned}; -use rustc_span::symbol::kw::PathRoot; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; @@ -642,26 +641,13 @@ impl<'a> Parser<'a> { } /// Parse `box expr` - this syntax has been removed, but we still parse this - /// for now to provide an automated way to fix usages of it - fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - let (span, expr) = self.parse_expr_prefix_common(lo)?; - let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap(); - self.dcx().emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() }); - // So typechecking works, parse `box ` as `::std::boxed::Box::new(expr)` - let path = Path { - span, - segments: [ - PathSegment::from_ident(Ident::with_dummy_span(PathRoot)), - PathSegment::from_ident(Ident::with_dummy_span(sym::std)), - PathSegment::from_ident(Ident::from_str("boxed")), - PathSegment::from_ident(Ident::from_str("Box")), - PathSegment::from_ident(Ident::with_dummy_span(sym::new)), - ] - .into(), - tokens: None, - }; - let path = self.mk_expr(span, ExprKind::Path(None, path)); - Ok((span, self.mk_call(path, ThinVec::from([expr])))) + /// for now to provide a more useful error + fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> { + let (span, _) = self.parse_expr_prefix_common(box_kw)?; + let inner_span = span.with_lo(box_kw.hi()); + let code = self.sess.source_map().span_to_snippet(inner_span).unwrap(); + self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() }); + Ok((span, ExprKind::Err)) } fn is_mistaken_not_ident_negation(&self) -> bool { From 510fcd318b61d0e45165cdb0de880ee2f4f9cde2 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 17 Jan 2024 17:09:04 -0500 Subject: [PATCH 225/297] Use UnhashMap for a few more maps This avoids hashing data that's already hashed. --- compiler/rustc_data_structures/src/hashes.rs | 12 +++++++++++- .../rustc_data_structures/src/stable_hasher.rs | 14 +++++++++++++- compiler/rustc_span/src/hygiene.rs | 4 ++-- compiler/rustc_span/src/source_map.rs | 4 ++-- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs index 291ee5bbe26e..1564eeb4baee 100644 --- a/compiler/rustc_data_structures/src/hashes.rs +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -75,11 +75,21 @@ impl fmt::LowerHex for Hash64 { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub struct Hash128 { inner: u128, } +// We expect Hash128 to be well mixed. So there's no point in hashing both parts. +// +// This also allows using Hash128-containing types in UnHash-based hashmaps, which would otherwise +// debug_assert! that we're hashing more than a single u64. +impl std::hash::Hash for Hash128 { + fn hash(&self, h: &mut H) { + h.write_u64(self.truncate().as_u64()); + } +} + impl Hash128 { #[inline] pub fn truncate(self) -> Hash64 { diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index afe26f80de8c..52304c72a2f8 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -314,7 +314,19 @@ impl_stable_traits_for_trivial_type!(char); impl_stable_traits_for_trivial_type!(()); impl_stable_traits_for_trivial_type!(Hash64); -impl_stable_traits_for_trivial_type!(Hash128); + +// We need a custom impl as the default hash function will only hash half the bits. For stable +// hashing we want to hash the full 128-bit hash. +impl HashStable for Hash128 { + #[inline] + fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { + self.as_u128().hash(hasher); + } +} + +unsafe impl StableOrd for Hash128 { + const CAN_USE_UNSTABLE_SORT: bool = true; +} impl HashStable for ! { fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index d03965b539c8..5be794f3e17b 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -330,7 +330,7 @@ pub(crate) struct HygieneData { /// would have collisions without a disambiguator. /// The keys of this map are always computed with `ExpnData.disambiguator` /// set to 0. - expn_data_disambiguators: FxHashMap, + expn_data_disambiguators: UnhashMap, } impl HygieneData { @@ -359,7 +359,7 @@ impl HygieneData { dollar_crate_name: kw::DollarCrate, }], syntax_context_map: FxHashMap::default(), - expn_data_disambiguators: FxHashMap::default(), + expn_data_disambiguators: UnhashMap::default(), } } diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 72a8b23721d7..df7635e447da 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -10,8 +10,8 @@ //! information, source code snippets, etc. use crate::*; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock}; +use rustc_data_structures::unhash::UnhashMap; use std::fs; use std::io::{self, BorrowedBuf, Read}; use std::path::{self}; @@ -164,7 +164,7 @@ impl FileLoader for RealFileLoader { #[derive(Default)] struct SourceMapFiles { source_files: monotonic::MonotonicVec>, - stable_id_to_source_file: FxHashMap>, + stable_id_to_source_file: UnhashMap>, } pub struct SourceMap { From 3f7c7842e6dd0dfc713c52fe7ffd24cd6a54fa87 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 17 Jan 2024 15:59:04 +0000 Subject: [PATCH 226/297] Move `removed-syntax` tests to their own directory --- tests/ui/parser/{ => removed-syntax}/removed-syntax-box.fixed | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-box.rs | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-box.stderr | 0 .../{ => removed-syntax}/removed-syntax-closure-lifetime.rs | 0 .../{ => removed-syntax}/removed-syntax-closure-lifetime.stderr | 0 .../ui/parser/{ => removed-syntax}/removed-syntax-enum-newtype.rs | 0 .../{ => removed-syntax}/removed-syntax-enum-newtype.stderr | 0 .../ui/parser/{ => removed-syntax}/removed-syntax-field-let-2.rs | 0 .../parser/{ => removed-syntax}/removed-syntax-field-let-2.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-field-let.rs | 0 .../parser/{ => removed-syntax}/removed-syntax-field-let.stderr | 0 .../parser/{ => removed-syntax}/removed-syntax-field-semicolon.rs | 0 .../{ => removed-syntax}/removed-syntax-field-semicolon.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-fixed-vec.rs | 0 .../parser/{ => removed-syntax}/removed-syntax-fixed-vec.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-fn-sigil.rs | 0 .../ui/parser/{ => removed-syntax}/removed-syntax-fn-sigil.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-mode.rs | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-mode.stderr | 0 .../ui/parser/{ => removed-syntax}/removed-syntax-mut-vec-expr.rs | 0 .../{ => removed-syntax}/removed-syntax-mut-vec-expr.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-mut-vec-ty.rs | 0 .../parser/{ => removed-syntax}/removed-syntax-mut-vec-ty.stderr | 0 .../ui/parser/{ => removed-syntax}/removed-syntax-ptr-lifetime.rs | 0 .../{ => removed-syntax}/removed-syntax-ptr-lifetime.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-record.rs | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-record.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-static-fn.rs | 0 .../parser/{ => removed-syntax}/removed-syntax-static-fn.stderr | 0 .../parser/{ => removed-syntax}/removed-syntax-uniq-mut-expr.rs | 0 .../{ => removed-syntax}/removed-syntax-uniq-mut-expr.stderr | 0 .../ui/parser/{ => removed-syntax}/removed-syntax-uniq-mut-ty.rs | 0 .../parser/{ => removed-syntax}/removed-syntax-uniq-mut-ty.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-with-1.rs | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-with-1.stderr | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-with-2.rs | 0 tests/ui/parser/{ => removed-syntax}/removed-syntax-with-2.stderr | 0 37 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-box.fixed (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-box.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-box.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-closure-lifetime.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-closure-lifetime.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-enum-newtype.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-enum-newtype.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-field-let-2.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-field-let-2.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-field-let.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-field-let.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-field-semicolon.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-field-semicolon.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-fixed-vec.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-fixed-vec.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-fn-sigil.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-fn-sigil.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-mode.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-mode.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-mut-vec-expr.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-mut-vec-expr.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-mut-vec-ty.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-mut-vec-ty.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-ptr-lifetime.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-ptr-lifetime.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-record.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-record.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-static-fn.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-static-fn.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-uniq-mut-expr.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-uniq-mut-expr.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-uniq-mut-ty.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-uniq-mut-ty.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-with-1.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-with-1.stderr (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-with-2.rs (100%) rename tests/ui/parser/{ => removed-syntax}/removed-syntax-with-2.stderr (100%) diff --git a/tests/ui/parser/removed-syntax-box.fixed b/tests/ui/parser/removed-syntax/removed-syntax-box.fixed similarity index 100% rename from tests/ui/parser/removed-syntax-box.fixed rename to tests/ui/parser/removed-syntax/removed-syntax-box.fixed diff --git a/tests/ui/parser/removed-syntax-box.rs b/tests/ui/parser/removed-syntax/removed-syntax-box.rs similarity index 100% rename from tests/ui/parser/removed-syntax-box.rs rename to tests/ui/parser/removed-syntax/removed-syntax-box.rs diff --git a/tests/ui/parser/removed-syntax-box.stderr b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-box.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-box.stderr diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.rs b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs similarity index 100% rename from tests/ui/parser/removed-syntax-closure-lifetime.rs rename to tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-closure-lifetime.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr diff --git a/tests/ui/parser/removed-syntax-enum-newtype.rs b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs similarity index 100% rename from tests/ui/parser/removed-syntax-enum-newtype.rs rename to tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs diff --git a/tests/ui/parser/removed-syntax-enum-newtype.stderr b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-enum-newtype.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr diff --git a/tests/ui/parser/removed-syntax-field-let-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs similarity index 100% rename from tests/ui/parser/removed-syntax-field-let-2.rs rename to tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs diff --git a/tests/ui/parser/removed-syntax-field-let-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-field-let-2.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr diff --git a/tests/ui/parser/removed-syntax-field-let.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-let.rs similarity index 100% rename from tests/ui/parser/removed-syntax-field-let.rs rename to tests/ui/parser/removed-syntax/removed-syntax-field-let.rs diff --git a/tests/ui/parser/removed-syntax-field-let.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-field-let.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr diff --git a/tests/ui/parser/removed-syntax-field-semicolon.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs similarity index 100% rename from tests/ui/parser/removed-syntax-field-semicolon.rs rename to tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs diff --git a/tests/ui/parser/removed-syntax-field-semicolon.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-field-semicolon.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr diff --git a/tests/ui/parser/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs similarity index 100% rename from tests/ui/parser/removed-syntax-fixed-vec.rs rename to tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs diff --git a/tests/ui/parser/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-fixed-vec.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr diff --git a/tests/ui/parser/removed-syntax-fn-sigil.rs b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs similarity index 100% rename from tests/ui/parser/removed-syntax-fn-sigil.rs rename to tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs diff --git a/tests/ui/parser/removed-syntax-fn-sigil.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-fn-sigil.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr diff --git a/tests/ui/parser/removed-syntax-mode.rs b/tests/ui/parser/removed-syntax/removed-syntax-mode.rs similarity index 100% rename from tests/ui/parser/removed-syntax-mode.rs rename to tests/ui/parser/removed-syntax/removed-syntax-mode.rs diff --git a/tests/ui/parser/removed-syntax-mode.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mode.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-mode.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-mode.stderr diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.rs b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-expr.rs rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-expr.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.rs b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-ty.rs rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-ty.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.rs b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs similarity index 100% rename from tests/ui/parser/removed-syntax-ptr-lifetime.rs rename to tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-ptr-lifetime.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr diff --git a/tests/ui/parser/removed-syntax-record.rs b/tests/ui/parser/removed-syntax/removed-syntax-record.rs similarity index 100% rename from tests/ui/parser/removed-syntax-record.rs rename to tests/ui/parser/removed-syntax/removed-syntax-record.rs diff --git a/tests/ui/parser/removed-syntax-record.stderr b/tests/ui/parser/removed-syntax/removed-syntax-record.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-record.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-record.stderr diff --git a/tests/ui/parser/removed-syntax-static-fn.rs b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs similarity index 100% rename from tests/ui/parser/removed-syntax-static-fn.rs rename to tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs diff --git a/tests/ui/parser/removed-syntax-static-fn.stderr b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-static-fn.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.rs b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-expr.rs rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-expr.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.rs b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-ty.rs rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-ty.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr diff --git a/tests/ui/parser/removed-syntax-with-1.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-1.rs similarity index 100% rename from tests/ui/parser/removed-syntax-with-1.rs rename to tests/ui/parser/removed-syntax/removed-syntax-with-1.rs diff --git a/tests/ui/parser/removed-syntax-with-1.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-with-1.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr diff --git a/tests/ui/parser/removed-syntax-with-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs similarity index 100% rename from tests/ui/parser/removed-syntax-with-2.rs rename to tests/ui/parser/removed-syntax/removed-syntax-with-2.rs diff --git a/tests/ui/parser/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-with-2.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr From 99797bbd9fdb138dd59a782f156db8397d07943c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 13:52:08 +1100 Subject: [PATCH 227/297] coverage: Format all remaining tests These tests can simply be reformatted as normal, because the resulting changes are unimportant. --- tests/coverage/closure_macro.cov-map | 12 ++++++------ tests/coverage/closure_macro.coverage | 3 ++- tests/coverage/closure_macro.rs | 3 ++- tests/coverage/closure_macro_async.cov-map | 16 ++++++++-------- tests/coverage/closure_macro_async.coverage | 3 ++- tests/coverage/closure_macro_async.rs | 3 ++- tests/coverage/coroutine.cov-map | 16 ++++++++-------- tests/coverage/coroutine.coverage | 7 +++++-- tests/coverage/coroutine.rs | 6 +++++- tests/coverage/inline-dead.cov-map | 18 +++++++++--------- tests/coverage/inline-dead.coverage | 5 ++--- tests/coverage/inline-dead.rs | 4 +--- tests/coverage/partial_eq.cov-map | 4 ++-- tests/coverage/partial_eq.coverage | 7 ++++++- tests/coverage/partial_eq.rs | 7 ++++++- tests/coverage/thin-lto.cov-map | 4 ++-- tests/coverage/thin-lto.coverage | 3 +-- tests/coverage/thin-lto.rs | 3 +-- 18 files changed, 70 insertions(+), 54 deletions(-) diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index b02c7e2e4c66..323d6e3c8aa5 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -1,20 +1,20 @@ Function name: closure_macro::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) Function name: closure_macro::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) +- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) @@ -27,10 +27,10 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 12, 00, 54] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 35, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84) diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index 0f2c917e0900..a6eeb79a71c8 100644 --- a/tests/coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage @@ -14,7 +14,8 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + LL| | $value.or_else(|e| { + LL| | // FIXME(85000): no coverage in closure macros LL| | let message = format!($error_message, e); LL| | if message.len() > 0 { LL| | println!("{}", message); diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/closure_macro.rs index 9b289141c2e5..c3ef91678809 100644 --- a/tests/coverage/closure_macro.rs +++ b/tests/coverage/closure_macro.rs @@ -14,7 +14,8 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + $value.or_else(|e| { + // FIXME(85000): no coverage in closure macros let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 14b1525ca0e6..5f5e06442789 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -1,28 +1,28 @@ Function name: closure_macro_async::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) Function name: closure_macro_async::test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 34, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43) Function name: closure_macro_async::test::{closure#0} -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 34, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) @@ -35,10 +35,10 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 12, 00, 54] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 37, 18) to (start + 0, 84) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 2c9bd4ac97a1..da6afa5800fb 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -15,7 +15,8 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + LL| | $value.or_else(|e| { + LL| | // FIXME(85000): no coverage in closure macros LL| | let message = format!($error_message, e); LL| | if message.len() > 0 { LL| | println!("{}", message); diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index a7f0cabb4c23..00169b18045e 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -15,7 +15,8 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + $value.or_else(|e| { + // FIXME(85000): no coverage in closure macros let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 8dd03acc2f4d..ef9faab590b3 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -1,5 +1,5 @@ Function name: coroutine::get_u32 -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 01, 01, 0b, 05, 01, 0e, 00, 13, 02, 00, 1d, 00, 3c, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 01, 01, 0b, 05, 02, 09, 00, 0e, 02, 02, 09, 00, 28, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -7,14 +7,14 @@ Number of expressions: 2 - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 11, 1) to (start + 1, 11) -- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 19) -- Code(Expression(0, Sub)) at (prev + 0, 29) to (start + 0, 60) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 14) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 40) = (c0 - c1) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: coroutine::main -Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -27,7 +27,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(6) - expression 7 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 22) +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) - Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53) @@ -43,11 +43,11 @@ Number of file 0 mappings: 9 = ((c4 - c5) - c6) Function name: coroutine::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 1c, 01, 1f, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 1c, 01, 1f, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 17, 28) to (start + 1, 31) +- Code(Counter(0)) at (prev + 21, 28) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index 3a9791a0dbd8..bd3d4e468801 100644 --- a/tests/coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage @@ -9,8 +9,11 @@ LL| |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic LL| |// to handle this condition, and still report dead block coverage. LL| 1|fn get_u32(val: bool) -> Result { - LL| 1| if val { Ok(1) } else { Err(String::from("some error")) } - ^0 + LL| 1| if val { + LL| 1| Ok(1) + LL| | } else { + LL| 0| Err(String::from("some error")) + LL| | } LL| 1|} LL| | LL| 1|fn main() { diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs index 86d19af6f4f0..2aa689466fc3 100644 --- a/tests/coverage/coroutine.rs +++ b/tests/coverage/coroutine.rs @@ -9,7 +9,11 @@ use std::pin::Pin; // drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic // to handle this condition, and still report dead block coverage. fn get_u32(val: bool) -> Result { - if val { Ok(1) } else { Err(String::from("some error")) } + if val { + Ok(1) + } else { + Err(String::from("some error")) + } } fn main() { diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index ab04e746b916..c669b7245ead 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -1,20 +1,20 @@ Function name: inline_dead::dead (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 25, 1) to (start + 2, 2) +- Code(Zero) at (prev + 23, 1) to (start + 2, 2) Function name: inline_dead::live:: -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 10, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 0e, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Zero - expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) - Code(Zero) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - Zero) @@ -22,16 +22,16 @@ Number of file 0 mappings: 4 = (Zero + (c0 - Zero)) Function name: inline_dead::main -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 07, 06, 02, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 05, 06, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) -- Code(Counter(0)) at (prev + 7, 6) to (start + 2, 2) +- Code(Counter(0)) at (prev + 5, 6) to (start + 2, 2) Function name: inline_dead::main::{closure#0} -Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 02, 0d, 00, 0e, 03, 02, 05, 00, 06] +Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -39,7 +39,7 @@ Number of expressions: 2 - expression 1 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 7, 23) to (start + 1, 22) -- Code(Zero) at (prev + 2, 13) to (start + 0, 14) -- Code(Expression(0, Add)) at (prev + 2, 5) to (start + 0, 6) +- Code(Zero) at (prev + 1, 23) to (start + 0, 24) +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 6) = (Zero + (c0 - Zero)) diff --git a/tests/coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage index 7c201f482db3..a643332bce1f 100644 --- a/tests/coverage/inline-dead.coverage +++ b/tests/coverage/inline-dead.coverage @@ -5,9 +5,8 @@ LL| 1| println!("{}", live::()); LL| 1| LL| 1| let f = |x: bool| { - LL| 1| debug_assert!( - LL| 0| x - LL| | ); + LL| 1| debug_assert!(x); + ^0 LL| 1| }; LL| 1| f(false); LL| 1|} diff --git a/tests/coverage/inline-dead.rs b/tests/coverage/inline-dead.rs index 854fa0629675..a854c17f6d59 100644 --- a/tests/coverage/inline-dead.rs +++ b/tests/coverage/inline-dead.rs @@ -5,9 +5,7 @@ fn main() { println!("{}", live::()); let f = |x: bool| { - debug_assert!( - x - ); + debug_assert!(x); }; f(false); } diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 3a803e3c18fb..5e4aae0260b5 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -55,10 +55,10 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 5) to (start + 6, 6) Function name: partial_eq::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 05, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 0a, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 5, 2) +- Code(Counter(0)) at (prev + 21, 1) to (start + 10, 2) diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index c6d9ad6cf27e..6e3696386a77 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -23,7 +23,12 @@ LL| 1| let version_3_2_1 = Version::new(3, 2, 1); LL| 1| let version_3_3_0 = Version::new(3, 3, 0); LL| 1| - LL| 1| println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); + LL| 1| println!( + LL| 1| "{:?} < {:?} = {}", + LL| 1| version_3_2_1, + LL| 1| version_3_3_0, + LL| 1| version_3_2_1 < version_3_3_0 + LL| 1| ); LL| 1|} LL| | LL| |/* diff --git a/tests/coverage/partial_eq.rs b/tests/coverage/partial_eq.rs index dd8b42c18cea..825e266f111f 100644 --- a/tests/coverage/partial_eq.rs +++ b/tests/coverage/partial_eq.rs @@ -22,7 +22,12 @@ fn main() { let version_3_2_1 = Version::new(3, 2, 1); let version_3_3_0 = Version::new(3, 3, 0); - println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); + println!( + "{:?} < {:?} = {}", + version_3_2_1, + version_3_3_0, + version_3_2_1 < version_3_3_0 + ); } /* diff --git a/tests/coverage/thin-lto.cov-map b/tests/coverage/thin-lto.cov-map index 7e84e398f845..1f61b805f622 100644 --- a/tests/coverage/thin-lto.cov-map +++ b/tests/coverage/thin-lto.cov-map @@ -1,8 +1,8 @@ Function name: thin_lto::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 01, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 11] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 2) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 17) diff --git a/tests/coverage/thin-lto.coverage b/tests/coverage/thin-lto.coverage index 21abb5dce04e..7ece467217ac 100644 --- a/tests/coverage/thin-lto.coverage +++ b/tests/coverage/thin-lto.coverage @@ -1,5 +1,4 @@ LL| |// compile-flags: -O -C lto=thin -C prefer-dynamic=no LL| | - LL| 1|pub fn main() { - LL| 1|} + LL| 1|pub fn main() {} diff --git a/tests/coverage/thin-lto.rs b/tests/coverage/thin-lto.rs index 050aac263197..04e9cd0e8088 100644 --- a/tests/coverage/thin-lto.rs +++ b/tests/coverage/thin-lto.rs @@ -1,4 +1,3 @@ // compile-flags: -O -C lto=thin -C prefer-dynamic=no -pub fn main() { -} +pub fn main() {} From c1c7707238bd58242588d75a350def4ceb59c581 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 02:11:55 +0000 Subject: [PATCH 228/297] Deny braced macro invocations in let-else --- compiler/rustc_ast/src/util/classify.rs | 10 +++++-- tests/ui/parser/bad-let-else-statement.rs | 25 +++++++++++++++++ tests/ui/parser/bad-let-else-statement.stderr | 28 ++++++++++++++++++- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 65036bcdc36f..098b8f2d6d03 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -2,7 +2,7 @@ // Predicates on exprs and stmts that the pretty-printer and parser use -use crate::ast; +use crate::{ast, token::Delimiter}; /// Does this expression require a semicolon to be treated /// as a statement? The negation of this: 'can this expression @@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { | While(..) | ConstBlock(_) => break Some(expr), - // FIXME: These can end in `}`, but changing these would break stable code. - InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => { + MacCall(mac) => { + break (mac.args.delim == Delimiter::Brace).then_some(expr); + } + + InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => { + // These should have been denied pre-expansion. break None; } diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index 7b927c89ba07..a42e8c41c2ef 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -161,4 +161,29 @@ fn q() { }; } +fn r() { + let ok = format_args!("") else { return; }; + + let bad = format_args! {""} else { return; }; + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed +} + +fn s() { + macro_rules! a { + () => { {} } + } + + macro_rules! b { + (1) => { + let x = a!() else { return; }; + }; + (2) => { + let x = a! {} else { return; }; + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + }; + } + + b!(1); b!(2); +} + fn main() {} diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 7cbda25e417f..4ea924ddcb80 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -228,5 +228,31 @@ LL | x LL ~ }) else { | -error: aborting due to 17 previous errors +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:167:31 + | +LL | let bad = format_args! {""} else { return; }; + | ^ + | +help: wrap the expression in parentheses + | +LL | let bad = (format_args! {""}) else { return; }; + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:181:25 + | +LL | let x = a! {} else { return; }; + | ^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) +help: wrap the expression in parentheses + | +LL | let x = (a! {}) else { return; }; + | + + + +error: aborting due to 19 previous errors From ec263df5e440598159f19a42c104c3b5f13888a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 03:01:05 +0000 Subject: [PATCH 229/297] Suggest wrapping mac args in parens rather than the whole expression --- compiler/rustc_parse/messages.ftl | 2 + compiler/rustc_parse/src/errors.rs | 37 +++++++++++++------ compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 15 ++++++-- tests/ui/parser/bad-let-else-statement.stderr | 12 +++--- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index d515e86a1829..e3ecd24b6a5f 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -722,6 +722,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses +parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro + parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses parse_switch_mut_let_order = diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 34b34a1bad6c..8f57b2eb5aa9 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: WrapExpressionInParentheses, + pub sub: WrapInParentheses, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_sugg_wrap_expression_in_parentheses, - applicability = "machine-applicable" -)] -pub(crate) struct WrapExpressionInParentheses { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, + +pub(crate) enum WrapInParentheses { + #[multipart_suggestion( + parse_sugg_wrap_expression_in_parentheses, + applicability = "machine-applicable" + )] + Expression { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, + #[multipart_suggestion( + parse_sugg_wrap_macro_in_parentheses, + applicability = "machine-applicable" + )] + MacroArgs { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, } #[derive(Diagnostic)] @@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse { pub span: Span, pub operator: &'static str, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] @@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse { #[primary_span] pub span: Span, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8ca02452342b..f858706805db 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1844,7 +1844,7 @@ impl<'a> Parser<'a> { let lexpr = self.parse_expr_labeled(label, true)?; self.dcx().emit_err(errors::LabeledLoopInBreak { span: lexpr.span, - sub: errors::WrapExpressionInParentheses { + sub: errors::WrapInParentheses::Expression { left: lexpr.span.shrink_to_lo(), right: lexpr.span.shrink_to_hi(), }, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1a8bbf0a1572..1bae5b322403 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -389,7 +389,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::InvalidExpressionInLetElse { span: init.span, operator: op.node.as_str(), - sugg: errors::WrapExpressionInParentheses { + sugg: errors::WrapInParentheses::Expression { left: init.span.shrink_to_lo(), right: init.span.shrink_to_hi(), }, @@ -400,12 +400,19 @@ impl<'a> Parser<'a> { fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { if let Some(trailing) = classify::expr_trailing_brace(init) { - self.dcx().emit_err(errors::InvalidCurlyInLetElse { - span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), - sugg: errors::WrapExpressionInParentheses { + let sugg = match &trailing.kind { + ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs { + left: mac.args.dspan.open, + right: mac.args.dspan.close, + }, + _ => errors::WrapInParentheses::Expression { left: trailing.span.shrink_to_lo(), right: trailing.span.shrink_to_hi(), }, + }; + self.dcx().emit_err(errors::InvalidCurlyInLetElse { + span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), + sugg, }); } } diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 4ea924ddcb80..887455913d84 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -234,10 +234,10 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let bad = format_args! {""} else { return; }; | ^ | -help: wrap the expression in parentheses +help: use parentheses instead of braces for this macro | -LL | let bad = (format_args! {""}) else { return; }; - | + + +LL | let bad = format_args! ("") else { return; }; + | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:181:25 @@ -249,10 +249,10 @@ LL | b!(1); b!(2); | ----- in this macro invocation | = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) -help: wrap the expression in parentheses +help: use parentheses instead of braces for this macro | -LL | let x = (a! {}) else { return; }; - | + + +LL | let x = a! () else { return; }; + | ~~ error: aborting due to 19 previous errors From e68f3039d4f2b12dcfc348ebb50fd7855e6d7fd1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 17 Jan 2024 13:53:25 -0500 Subject: [PATCH 230/297] Optimize large array creation in const-eval This changes repeated memcpy's to a memset for the case that we're propagating a single byte into a region of memory. --- .../rustc_const_eval/src/interpret/memory.rs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 7ff970661d6f..3afd14eb5743 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1209,21 +1209,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping); } } + } - for i in 0..num_copies { - ptr::copy( - src_bytes, - dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication - size.bytes_usize(), - ); + let size_in_bytes = size.bytes_usize(); + // For particularly large arrays (where this is perf-sensitive) it's common that + // we're writing a single byte repeatedly. So, optimize that case to a memset. + if size_in_bytes == 1 && num_copies >= 1 { + // SAFETY: `src_bytes` would be read from anyway by copies below (num_copies >= 1). + // Since size_in_bytes = 1, then the `init.no_bytes_init()` check above guarantees + // that this read at type `u8` is OK -- it must be an initialized byte. + let value = *src_bytes; + dest_bytes.write_bytes(value, (size * num_copies).bytes_usize()); + } else if src_alloc_id == dest_alloc_id { + let mut dest_ptr = dest_bytes; + for _ in 0..num_copies { + ptr::copy(src_bytes, dest_ptr, size_in_bytes); + dest_ptr = dest_ptr.add(size_in_bytes); } } else { - for i in 0..num_copies { - ptr::copy_nonoverlapping( - src_bytes, - dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication - size.bytes_usize(), - ); + let mut dest_ptr = dest_bytes; + for _ in 0..num_copies { + ptr::copy_nonoverlapping(src_bytes, dest_ptr, size_in_bytes); + dest_ptr = dest_ptr.add(size_in_bytes); } } } From d96003dd2a780ecb19252229b1927b1dc09f699b Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 10 Dec 2023 20:13:21 -0500 Subject: [PATCH 231/297] Correctly handle normalization in implied bounds Special-case Bevy dependents to not error --- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 7 +- .../src/check/compare_impl_item/refine.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 57 ++++- .../src/impl_wf_check/min_specialization.rs | 3 +- compiler/rustc_middle/src/query/erase.rs | 4 + compiler/rustc_middle/src/query/mod.rs | 11 +- compiler/rustc_middle/src/traits/query.rs | 2 +- .../rustc_trait_selection/src/traits/misc.rs | 4 +- .../src/traits/outlives_bounds.rs | 200 ++++++++++-------- .../query/type_op/implied_outlives_bounds.rs | 86 +++++++- .../src/implied_outlives_bounds.rs | 18 +- tests/ui/implied-bounds/auxiliary/bevy_ecs.rs | 18 -- tests/ui/implied-bounds/bevy_world_query.rs | 23 +- tests/ui/implied-bounds/from-trait-impl.rs | 5 +- .../ui/implied-bounds/from-trait-impl.stderr | 26 +++ tests/ui/implied-bounds/gluon_salsa.rs | 5 +- .../normalization-nested.lifetime.stderr | 35 +-- tests/ui/implied-bounds/sod_service_chain.rs | 6 +- .../implied-bounds/sod_service_chain.stderr | 31 +++ 20 files changed, 375 insertions(+), 170 deletions(-) delete mode 100644 tests/ui/implied-bounds/auxiliary/bevy_ecs.rs create mode 100644 tests/ui/implied-bounds/from-trait-impl.stderr create mode 100644 tests/ui/implied-bounds/sod_service_chain.stderr diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 77914802bf77..d7b1447d9800 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -368,7 +368,7 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias { .. } => { let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?; - let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys); + let implied_bounds = infcx.implied_bounds_tys_compat(param_env, def_id, &wf_tys); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 774feb94f7dc..e2cdeb5b204e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -378,7 +378,7 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), + infcx.implied_bounds_tys_compat(param_env, impl_m_def_id, &wf_tys), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { @@ -702,7 +702,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), + infcx.implied_bounds_tys_compat(param_env, impl_m_def_id, &wf_tys), ); ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; @@ -2070,7 +2070,8 @@ pub(super) fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types); + let implied_bounds = + infcx.implied_bounds_tys_compat(param_env, impl_ty_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index f7fc0c81b953..3509a39fec90 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -158,7 +158,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), implied_wf_types), + infcx.implied_bounds_tys_compat(param_env, impl_m.def_id.expect_local(), &implied_wf_types), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4772bae58c47..1af6282070ed 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -15,6 +15,7 @@ use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::query::Providers; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, @@ -112,8 +113,6 @@ where let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; - let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types); - let errors = wfcx.select_all_or_error(); if !errors.is_empty() { let err = infcx.err_ctxt().report_fulfillment_errors(errors); @@ -128,10 +127,58 @@ where } } + let infcx_compat = infcx.fork(); + + debug!(?assumed_wf_types); + let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env)?; - infcx.tainted_by_errors().error_reported() + let errors = infcx.resolve_regions(&outlives_env); + if errors.is_empty() { + return Ok(()); + } + + let is_bevy = 'is_bevy: { + // We don't want to emit this for dependents of Bevy, for now. + // See #119956 + let is_bevy_paramset = |def: ty::AdtDef<'_>| { + let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did)); + adt_did.contains("ParamSet") + }; + for ty in assumed_wf_types.iter() { + match ty.kind() { + ty::Adt(def, _) => { + if is_bevy_paramset(*def) { + break 'is_bevy true; + } + } + ty::Ref(_, ty, _) => match ty.kind() { + ty::Adt(def, _) => { + if is_bevy_paramset(*def) { + break 'is_bevy true; + } + } + _ => {} + }, + _ => {} + } + } + false + }; + + if is_bevy { + let implied_bounds = + infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let errors_compat = infcx_compat.resolve_regions(&outlives_env); + if errors_compat.is_empty() { + Ok(()) + } else { + Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat)) + } + } else { + Err(infcx.err_ctxt().report_region_errors(body_def_id, &errors)) + } } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> { @@ -723,7 +770,7 @@ fn resolve_regions_with_wf_tys<'tcx>( let infcx = tcx.infer_ctxt().build(); let outlives_environment = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, id, wf_tys.clone()), + infcx.implied_bounds_tys_compat(param_env, id, wf_tys), ); let region_bound_pairs = outlives_environment.region_bound_pairs(); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 93dd2342a4d1..a922209deb80 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -202,7 +202,8 @@ fn get_impl_args( return Err(guar); } - let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); + let implied_bounds = + infcx.implied_bounds_tys_compat(param_env, impl1_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b9200f1abf16..7122f1317315 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -74,6 +74,10 @@ impl EraseType for Result<&'_ T, traits::query::NoSolution> { type Result = [u8; size_of::>()]; } +impl EraseType for Result<&'_ [T], traits::query::NoSolution> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::>()]; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1dc772208810..f5b76f08f0ba 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1949,7 +1949,7 @@ rustc_queries! { desc { "normalizing `{}`", goal.value } } - query implied_outlives_bounds( + query implied_outlives_bounds_compat( goal: CanonicalTyGoal<'tcx> ) -> Result< &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, @@ -1958,6 +1958,15 @@ rustc_queries! { desc { "computing implied outlives bounds for `{}`", goal.value.value } } + query implied_outlives_bounds( + goal: CanonicalTyGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, + NoSolution, + > { + desc { "computing implied outlives bounds v2 for `{}`", goal.value.value } + } + /// Do not call this query directly: /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. query dropck_outlives( diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 5f02dd22961c..61d96cad57d7 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -191,7 +191,7 @@ pub struct NormalizationResult<'tcx> { /// case they are called implied bounds). They are fed to the /// `OutlivesEnv` which in turn is supplied to the region checker and /// other parts of the inference system. -#[derive(Clone, Debug, TypeFoldable, TypeVisitable, HashStable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable)] pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 073174127d6a..52de8c4ceae6 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -191,10 +191,10 @@ pub fn all_fields_implement_trait<'tcx>( // Check regions assuming the self type of the impl is WF let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys( + infcx.implied_bounds_tys_compat( param_env, parent_cause.body_id, - FxIndexSet::from_iter([self_type]), + &FxIndexSet::from_iter([self_type]), ), ); let errors = infcx.resolve_regions(&outlives_env); diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 5b349d576b6a..ec17024345a5 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -9,123 +9,139 @@ use rustc_span::def_id::LocalDefId; pub use rustc_middle::traits::query::OutlivesBound; +pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator> + 'a; pub type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { - fn implied_outlives_bounds( - &self, + fn implied_bounds_tys_compat( + &'a self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, - ty: Ty<'tcx>, - ) -> Vec>; + tys: &'a FxIndexSet>, + ) -> BoundsCompat<'a, 'tcx>; fn implied_bounds_tys( &'a self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, - tys: FxIndexSet>, + tys: &'a FxIndexSet>, ) -> Bounds<'a, 'tcx>; } -impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { - /// Implied bounds are region relationships that we deduce - /// automatically. The idea is that (e.g.) a caller must check that a - /// function's argument types are well-formed immediately before - /// calling that fn, and hence the *callee* can assume that its - /// argument types are well-formed. This may imply certain relationships - /// between generic parameters. For example: - /// ``` - /// fn foo(x: &T) {} - /// ``` - /// can only be called with a `'a` and `T` such that `&'a T` is WF. - /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. - /// - /// # Parameters - /// - /// - `param_env`, the where-clauses in scope - /// - `body_id`, the body-id to use when normalizing assoc types. - /// Note that this may cause outlives obligations to be injected - /// into the inference context with this body-id. - /// - `ty`, the type that we are supposed to assume is WF. - #[instrument(level = "debug", skip(self, param_env, body_id), ret)] - fn implied_outlives_bounds( - &self, - param_env: ty::ParamEnv<'tcx>, - body_id: LocalDefId, - ty: Ty<'tcx>, - ) -> Vec> { - let ty = self.resolve_vars_if_possible(ty); - let ty = OpportunisticRegionResolver::new(self).fold_ty(ty); +/// Implied bounds are region relationships that we deduce +/// automatically. The idea is that (e.g.) a caller must check that a +/// function's argument types are well-formed immediately before +/// calling that fn, and hence the *callee* can assume that its +/// argument types are well-formed. This may imply certain relationships +/// between generic parameters. For example: +/// ``` +/// fn foo(x: &T) {} +/// ``` +/// can only be called with a `'a` and `T` such that `&'a T` is WF. +/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. +/// +/// # Parameters +/// +/// - `param_env`, the where-clauses in scope +/// - `body_id`, the body-id to use when normalizing assoc types. +/// Note that this may cause outlives obligations to be injected +/// into the inference context with this body-id. +/// - `ty`, the type that we are supposed to assume is WF. +#[instrument(level = "debug", skip(infcx, param_env, body_id), ret)] +fn implied_outlives_bounds<'a, 'tcx>( + infcx: &'a InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + body_id: LocalDefId, + ty: Ty<'tcx>, + compat: bool, +) -> Vec> { + let ty = infcx.resolve_vars_if_possible(ty); + let ty = OpportunisticRegionResolver::new(infcx).fold_ty(ty); - // We do not expect existential variables in implied bounds. - // We may however encounter unconstrained lifetime variables - // in very rare cases. - // - // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for - // an example. - assert!(!ty.has_non_region_infer()); + // We do not expect existential variables in implied bounds. + // We may however encounter unconstrained lifetime variables + // in very rare cases. + // + // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for + // an example. + assert!(!ty.has_non_region_infer()); - let mut canonical_var_values = OriginalQueryValues::default(); - let canonical_ty = self.canonicalize_query(param_env.and(ty), &mut canonical_var_values); - let Ok(canonical_result) = self.tcx.implied_outlives_bounds(canonical_ty) else { - return vec![]; - }; + let mut canonical_var_values = OriginalQueryValues::default(); + let canonical_ty = infcx.canonicalize_query(param_env.and(ty), &mut canonical_var_values); + let implied_bounds_result = if compat { + infcx.tcx.implied_outlives_bounds_compat(canonical_ty) + } else { + infcx.tcx.implied_outlives_bounds(canonical_ty) + }; + let Ok(canonical_result) = implied_bounds_result else { + return vec![]; + }; - let mut constraints = QueryRegionConstraints::default(); - let Ok(InferOk { value: mut bounds, obligations }) = self - .instantiate_nll_query_response_and_region_obligations( - &ObligationCause::dummy(), + let mut constraints = QueryRegionConstraints::default(); + let Ok(InferOk { value: mut bounds, obligations }) = infcx + .instantiate_nll_query_response_and_region_obligations( + &ObligationCause::dummy(), + param_env, + &canonical_var_values, + canonical_result, + &mut constraints, + ) + else { + return vec![]; + }; + assert_eq!(&obligations, &[]); + + // Because of #109628, we may have unexpected placeholders. Ignore them! + // FIXME(#109628): panic in this case once the issue is fixed. + bounds.retain(|bound| !bound.has_placeholders()); + + if !constraints.is_empty() { + let span = infcx.tcx.def_span(body_id); + + debug!(?constraints); + if !constraints.member_constraints.is_empty() { + span_bug!(span, "{:#?}", constraints.member_constraints); + } + + // Instantiation may have produced new inference variables and constraints on those + // variables. Process these constraints. + let ocx = ObligationCtxt::new(infcx); + let cause = ObligationCause::misc(span, body_id); + for &constraint in &constraints.outlives { + ocx.register_obligation(infcx.query_outlives_constraint_to_obligation( + constraint, + cause.clone(), param_env, - &canonical_var_values, - canonical_result, - &mut constraints, - ) - else { - return vec![]; - }; - assert_eq!(&obligations, &[]); + )); + } - // Because of #109628, we may have unexpected placeholders. Ignore them! - // FIXME(#109628): panic in this case once the issue is fixed. - bounds.retain(|bound| !bound.has_placeholders()); + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.dcx().span_delayed_bug( + span, + "implied_outlives_bounds failed to solve obligations from instantiation", + ); + } + }; - if !constraints.is_empty() { - let span = self.tcx.def_span(body_id); + bounds +} - debug!(?constraints); - if !constraints.member_constraints.is_empty() { - span_bug!(span, "{:#?}", constraints.member_constraints); - } - - // Instantiation may have produced new inference variables and constraints on those - // variables. Process these constraints. - let ocx = ObligationCtxt::new(self); - let cause = ObligationCause::misc(span, body_id); - for &constraint in &constraints.outlives { - ocx.register_obligation(self.query_outlives_constraint_to_obligation( - constraint, - cause.clone(), - param_env, - )); - } - - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - self.dcx().span_delayed_bug( - span, - "implied_outlives_bounds failed to solve obligations from instantiation", - ); - } - }; - - bounds +impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { + fn implied_bounds_tys_compat( + &'a self, + param_env: ParamEnv<'tcx>, + body_id: LocalDefId, + tys: &'a FxIndexSet>, + ) -> BoundsCompat<'a, 'tcx> { + tys.iter().flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, true)) } fn implied_bounds_tys( &'a self, param_env: ParamEnv<'tcx>, body_id: LocalDefId, - tys: FxIndexSet>, + tys: &'a FxIndexSet>, ) -> Bounds<'a, 'tcx> { - tys.into_iter().flat_map(move |ty| self.implied_outlives_bounds(param_env, body_id, ty)) + tys.iter().flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, false)) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index ba6ed2987740..bdc53f895fec 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -5,10 +5,11 @@ use crate::traits::ObligationCtxt; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; +use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::traits::query::OutlivesBound; use rustc_middle::infer::canonical::CanonicalQueryResponse; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::DUMMY_SP; use smallvec::{smallvec, SmallVec}; @@ -47,14 +48,14 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { param_env.and(ty) }); - tcx.implied_outlives_bounds(canonicalized) + tcx.implied_outlives_bounds_compat(canonicalized) } fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, ) -> Result { - compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty) + compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty) } } @@ -62,6 +63,85 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( ocx: &ObligationCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, +) -> Result>, NoSolution> { + let normalize_op = |ty| { + let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty); + if !ocx.select_all_or_error().is_empty() { + return Err(NoSolution); + } + let ty = ocx.infcx.resolve_vars_if_possible(ty); + let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty); + Ok(ty) + }; + + // Sometimes when we ask what it takes for T: WF, we get back that + // U: WF is required; in that case, we push U onto this stack and + // process it next. Because the resulting predicates aren't always + // guaranteed to be a subset of the original type, so we need to store the + // WF args we've computed in a set. + let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default(); + let mut wf_args = vec![ty.into(), normalize_op(ty)?.into()]; + + let mut outlives_bounds: Vec> = vec![]; + + while let Some(arg) = wf_args.pop() { + if !checked_wf_args.insert(arg) { + continue; + } + + // From the full set of obligations, just filter down to the region relationships. + for obligation in + wf::unnormalized_obligations(ocx.infcx, param_env, arg).into_iter().flatten() + { + assert!(!obligation.has_escaping_bound_vars()); + let Some(pred) = obligation.predicate.kind().no_bound_vars() else { + continue; + }; + match pred { + // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound + // if we ever support that + ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) + | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::NormalizesTo(..) + | ty::PredicateKind::AliasRelate(..) => {} + + // We need to search through *all* WellFormed predicates + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + wf_args.push(arg); + } + + // We need to register region relationships + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( + ty::OutlivesPredicate(r_a, r_b), + )) => outlives_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a)), + + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( + ty_a, + r_b, + ))) => { + let ty_a = normalize_op(ty_a)?; + let mut components = smallvec![]; + push_outlives_components(ocx.infcx.tcx, ty_a, &mut components); + outlives_bounds.extend(implied_bounds_from_components(r_b, components)) + } + } + } + } + + Ok(outlives_bounds) +} + +pub fn compute_implied_outlives_bounds_compat_inner<'tcx>( + ocx: &ObligationCtxt<'_, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, ) -> Result>, NoSolution> { let tcx = ocx.infcx.tcx; diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 959838ab348f..24e91c263e34 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -8,13 +8,29 @@ use rustc_infer::traits::query::OutlivesBound; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_trait_selection::infer::InferCtxtBuilderExt; -use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::compute_implied_outlives_bounds_inner; +use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::{ + compute_implied_outlives_bounds_compat_inner, compute_implied_outlives_bounds_inner, +}; use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; pub(crate) fn provide(p: &mut Providers) { + *p = Providers { implied_outlives_bounds_compat, ..*p }; *p = Providers { implied_outlives_bounds, ..*p }; } +fn implied_outlives_bounds_compat<'tcx>( + tcx: TyCtxt<'tcx>, + goal: CanonicalTyGoal<'tcx>, +) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, + NoSolution, +> { + tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| { + let (param_env, ty) = key.into_parts(); + compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty) + }) +} + fn implied_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalTyGoal<'tcx>, diff --git a/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs b/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs deleted file mode 100644 index b373d39f4d94..000000000000 --- a/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Related to Bevy regression #118553 - -pub trait WorldQuery {} -impl WorldQuery for &u8 {} - -pub struct Query(Q); - -pub trait SystemParam { - type State; -} -impl SystemParam for Query { - type State = (); - // `Q: 'static` is required because we need the TypeId of Q ... -} - -pub struct ParamSet(T) -where - T::State: Sized; diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs index f8e64632676d..d5de0e9ef217 100644 --- a/tests/ui/implied-bounds/bevy_world_query.rs +++ b/tests/ui/implied-bounds/bevy_world_query.rs @@ -1,11 +1,26 @@ -// aux-crate:bevy_ecs=bevy_ecs.rs // check-pass -// Related to Bevy regression #118553 -extern crate bevy_ecs; +// We currently special case bevy from erroring on incorrect implied bounds +// from normalization (issue #109628). +// Otherwise, we would expect this to hit that error. -use bevy_ecs::*; +pub trait WorldQuery {} +impl WorldQuery for &u8 {} + +pub struct Query(Q); + +pub trait SystemParam { + type State; +} +impl SystemParam for Query { + type State = (); + // `Q: 'static` is required because we need the TypeId of Q ... +} + +pub struct ParamSet(T) where T::State: Sized; fn handler<'a>(_: ParamSet>) {} +fn ref_handler<'a>(_: &ParamSet>) {} + fn main() {} diff --git a/tests/ui/implied-bounds/from-trait-impl.rs b/tests/ui/implied-bounds/from-trait-impl.rs index d13fddd9b8d4..6e126575aa9a 100644 --- a/tests/ui/implied-bounds/from-trait-impl.rs +++ b/tests/ui/implied-bounds/from-trait-impl.rs @@ -1,6 +1,3 @@ -// check-pass -// known-bug: #109628 - trait Trait { type Assoc; } @@ -14,11 +11,13 @@ where T::Assoc: Clone; // any predicate using `T::Assoc` works here fn func1(foo: Foo<(&str,)>) { + //~^ ERROR `&str` does not fulfill the required lifetime let _: &'static str = foo.0.0; } trait TestTrait {} impl TestTrait for [Foo<(X,)>; 1] {} +//~^ ERROR `X` may not live long enough fn main() {} diff --git a/tests/ui/implied-bounds/from-trait-impl.stderr b/tests/ui/implied-bounds/from-trait-impl.stderr new file mode 100644 index 000000000000..4151d206ae25 --- /dev/null +++ b/tests/ui/implied-bounds/from-trait-impl.stderr @@ -0,0 +1,26 @@ +error[E0477]: the type `&str` does not fulfill the required lifetime + --> $DIR/from-trait-impl.rs:13:15 + | +LL | fn func1(foo: Foo<(&str,)>) { + | ^^^^^^^^^^^^ + | + = note: type must satisfy the static lifetime + +error[E0310]: the parameter type `X` may not live long enough + --> $DIR/from-trait-impl.rs:20:23 + | +LL | impl TestTrait for [Foo<(X,)>; 1] {} + | ^^^^^^^^^^^^^^ + | | + | the parameter type `X` must be valid for the static lifetime... + | ...so that the type `X` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | impl TestTrait for [Foo<(X,)>; 1] {} + | +++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0310, E0477. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/implied-bounds/gluon_salsa.rs b/tests/ui/implied-bounds/gluon_salsa.rs index 98951af8ac2d..cd5500cb458f 100644 --- a/tests/ui/implied-bounds/gluon_salsa.rs +++ b/tests/ui/implied-bounds/gluon_salsa.rs @@ -1,5 +1,5 @@ // check-pass -// Related to Bevy regression #118553 +// Found in a crater run on #118553 pub trait QueryBase { type Db; @@ -17,8 +17,7 @@ pub struct QueryTable<'me, Q, DB> { _marker: Option<&'me ()>, } -impl<'me, Q> QueryTable<'me, Q, ::Db> -// projection is important +impl<'me, Q> QueryTable<'me, Q, ::Db> // projection is important // ^^^ removing 'me (and in QueryTable) gives a different error where Q: for<'f> AsyncQueryFunction<'f>, diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr index e020230d86a4..041892c7542a 100644 --- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr +++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr @@ -1,33 +1,10 @@ -error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/normalization-nested.rs:35:28 - | -LL | pub fn test_wfcheck<'x>(_: Map>) {} - | ^^^^^^^^^^^^^^^^ - | | - | this data with lifetime `'x`... - | ...is used and required to live as long as `'static` here - | -note: `'static` lifetime requirement introduced by this bound - --> $DIR/normalization-nested.rs:33:14 - | -LL | I::Item: 'static; - | ^^^^^^^ - -error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/normalization-nested.rs:37:29 +error: lifetime may not live long enough + --> $DIR/normalization-nested.rs:38:5 | LL | pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { - | ^^^^^^^^^^^^^^^^ - | | - | this data with lifetime `'x`... - | ...is used and required to live as long as `'static` here - | -note: `'static` lifetime requirement introduced by this bound - --> $DIR/normalization-nested.rs:33:14 - | -LL | I::Item: 'static; - | ^^^^^^^ + | -- lifetime `'x` defined here +LL | s + | ^ returning this value requires that `'x` must outlive `'static` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0759`. diff --git a/tests/ui/implied-bounds/sod_service_chain.rs b/tests/ui/implied-bounds/sod_service_chain.rs index f45ced71f757..7443a29f30cb 100644 --- a/tests/ui/implied-bounds/sod_service_chain.rs +++ b/tests/ui/implied-bounds/sod_service_chain.rs @@ -1,5 +1,4 @@ -// check-pass -// Related to crater regressions on #118553 +// Found in a crater run on #118553 pub trait Debug {} @@ -30,6 +29,9 @@ impl> ServiceChainBuilder { pub fn next>( self, ) -> ServiceChainBuilder, NS> { + //~^ the associated type + //~| the associated type + //~| the associated type panic!(); } } diff --git a/tests/ui/implied-bounds/sod_service_chain.stderr b/tests/ui/implied-bounds/sod_service_chain.stderr new file mode 100644 index 000000000000..1c0ef573e7d3 --- /dev/null +++ b/tests/ui/implied-bounds/sod_service_chain.stderr @@ -0,0 +1,31 @@ +error[E0310]: the associated type `

::Error` may not live long enough + --> $DIR/sod_service_chain.rs:31:10 + | +LL | ) -> ServiceChainBuilder, NS> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `

::Error` must be valid for the static lifetime... + | ...so that the type `

::Error` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | ) -> ServiceChainBuilder, NS> where

::Error: 'static { + | ++++++++++++++++++++++++++++++++++++ + +error[E0310]: the associated type `::Error` may not live long enough + --> $DIR/sod_service_chain.rs:31:10 + | +LL | ) -> ServiceChainBuilder, NS> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::Error` must be valid for the static lifetime... + | ...so that the type `::Error` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | ) -> ServiceChainBuilder, NS> where ::Error: 'static { + | ++++++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. From acab76573fffe8a3c2578506f277a89ef772a05d Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Tue, 16 Jan 2024 18:39:00 -0500 Subject: [PATCH 232/297] Add -Zno-implied-bounds-compat option and use it --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 7 +++---- .../src/check/compare_impl_item/refine.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 17 ++++++++++++----- .../src/impl_wf_check/min_specialization.rs | 3 +-- compiler/rustc_session/src/options.rs | 2 ++ .../rustc_trait_selection/src/traits/misc.rs | 2 +- .../src/traits/outlives_bounds.rs | 18 ++++++++++++++++-- 8 files changed, 37 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d7b1447d9800..03e2b0e00220 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -368,7 +368,7 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias { .. } => { let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?; - let implied_bounds = infcx.implied_bounds_tys_compat(param_env, def_id, &wf_tys); + let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e2cdeb5b204e..5b264f6f034c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -378,7 +378,7 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys_compat(param_env, impl_m_def_id, &wf_tys), + infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { @@ -702,7 +702,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys_compat(param_env, impl_m_def_id, &wf_tys), + infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys), ); ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; @@ -2070,8 +2070,7 @@ pub(super) fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let implied_bounds = - infcx.implied_bounds_tys_compat(param_env, impl_ty_def_id, &assumed_wf_types); + let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 3509a39fec90..0d8de0cabd1a 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -158,7 +158,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys_compat(param_env, impl_m.def_id.expect_local(), &implied_wf_types), + infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), &implied_wf_types), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 1af6282070ed..58046173fb1a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -127,10 +127,13 @@ where } } + debug!(?assumed_wf_types); + let infcx_compat = infcx.fork(); - debug!(?assumed_wf_types); - let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, &assumed_wf_types); + // We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always. + let implied_bounds = + infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let errors = infcx.resolve_regions(&outlives_env); @@ -166,9 +169,13 @@ where false }; - if is_bevy { + // If we have set `no_implied_bounds_compat`, then do not attempt compatibility. + // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`, + // but that does result in slightly more work when this option is set and + // just obscures what we mean here anyways. Let's just be explicit. + if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat { let implied_bounds = - infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types); + infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, true); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let errors_compat = infcx_compat.resolve_regions(&outlives_env); if errors_compat.is_empty() { @@ -770,7 +777,7 @@ fn resolve_regions_with_wf_tys<'tcx>( let infcx = tcx.infer_ctxt().build(); let outlives_environment = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys_compat(param_env, id, wf_tys), + infcx.implied_bounds_tys(param_env, id, wf_tys), ); let region_bound_pairs = outlives_environment.region_bound_pairs(); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index a922209deb80..6964446f9c77 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -202,8 +202,7 @@ fn get_impl_args( return Err(guar); } - let implied_bounds = - infcx.implied_bounds_tys_compat(param_env, impl1_def_id, &assumed_wf_types); + let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f4bf79f93f28..5bc88ae6ed17 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1724,6 +1724,8 @@ options! { "run all passes except codegen; no output"), no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], "omit DWARF address ranges that give faster lookups"), + no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED], + "disable the compatibility version of the `implied_bounds_ty` query"), no_jump_tables: bool = (false, parse_no_flag, [TRACKED], "disable the jump tables and lookup tables that can be generated from a switch case lowering"), no_leak_check: bool = (false, parse_no_flag, [UNTRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 52de8c4ceae6..0cd376fcbbdc 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -191,7 +191,7 @@ pub fn all_fields_implement_trait<'tcx>( // Check regions assuming the self type of the impl is WF let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys_compat( + infcx.implied_bounds_tys( param_env, parent_cause.body_id, &FxIndexSet::from_iter([self_type]), diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index ec17024345a5..52631d4353bf 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -12,13 +12,17 @@ pub use rustc_middle::traits::query::OutlivesBound; pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator> + 'a; pub type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { + /// Do *NOT* call this directly. fn implied_bounds_tys_compat( &'a self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, tys: &'a FxIndexSet>, + compat: bool, ) -> BoundsCompat<'a, 'tcx>; + /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` + /// with `compat` set to `true`, otherwise `false`. fn implied_bounds_tys( &'a self, param_env: ty::ParamEnv<'tcx>, @@ -132,8 +136,10 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { param_env: ParamEnv<'tcx>, body_id: LocalDefId, tys: &'a FxIndexSet>, + compat: bool, ) -> BoundsCompat<'a, 'tcx> { - tys.iter().flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, true)) + tys.iter() + .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat)) } fn implied_bounds_tys( @@ -142,6 +148,14 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { body_id: LocalDefId, tys: &'a FxIndexSet>, ) -> Bounds<'a, 'tcx> { - tys.iter().flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, false)) + tys.iter().flat_map(move |ty| { + implied_outlives_bounds( + self, + param_env, + body_id, + *ty, + !self.tcx.sess.opts.unstable_opts.no_implied_bounds_compat, + ) + }) } } From 63446d00ee2005125b1e4a7c3f00547101065709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 26 Sep 2023 22:34:09 +0200 Subject: [PATCH 233/297] Remove `OneThread` --- compiler/rustc_data_structures/src/marker.rs | 1 - compiler/rustc_data_structures/src/sync.rs | 56 -------------------- compiler/rustc_session/src/session.rs | 15 +++--- 3 files changed, 8 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 266e54604a6b..a9ccfbed4116 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -177,7 +177,6 @@ cfg_match! { [Vec where T: DynSync, A: std::alloc::Allocator + DynSync] [Box where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync] [crate::sync::RwLock where T: DynSend + DynSync] - [crate::sync::OneThread where T] [crate::sync::WorkerLocal where T: DynSend] [crate::intern::Interned<'a, T> where 'a, T: DynSync] [crate::tagged_ptr::CopyTaggedPtr where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool] diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 48edfba8da08..adcb6ceaebf8 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -43,7 +43,6 @@ pub use crate::marker::*; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; -use std::ops::{Deref, DerefMut}; mod lock; pub use lock::{Lock, LockGuard, Mode}; @@ -309,8 +308,6 @@ cfg_match! { use parking_lot::RwLock as InnerRwLock; - use std::thread; - /// This makes locks panic if they are already held. /// It is only useful when you are running in a single thread const ERROR_CHECKING: bool = false; @@ -445,56 +442,3 @@ impl Clone for RwLock { RwLock::new(self.borrow().clone()) } } - -/// A type which only allows its inner value to be used in one thread. -/// It will panic if it is used on multiple threads. -#[derive(Debug)] -pub struct OneThread { - #[cfg(parallel_compiler)] - thread: thread::ThreadId, - inner: T, -} - -#[cfg(parallel_compiler)] -unsafe impl std::marker::Sync for OneThread {} -#[cfg(parallel_compiler)] -unsafe impl std::marker::Send for OneThread {} - -impl OneThread { - #[inline(always)] - fn check(&self) { - #[cfg(parallel_compiler)] - assert_eq!(thread::current().id(), self.thread); - } - - #[inline(always)] - pub fn new(inner: T) -> Self { - OneThread { - #[cfg(parallel_compiler)] - thread: thread::current().id(), - inner, - } - } - - #[inline(always)] - pub fn into_inner(value: Self) -> T { - value.check(); - value.inner - } -} - -impl Deref for OneThread { - type Target = T; - - fn deref(&self) -> &T { - self.check(); - &self.inner - } -} - -impl DerefMut for OneThread { - fn deref_mut(&mut self) -> &mut T { - self.check(); - &mut self.inner - } -} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 3f6c70a18d39..cba6ce0d235e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -14,7 +14,9 @@ use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread}; +use rustc_data_structures::sync::{ + AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, +}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; @@ -35,7 +37,6 @@ use rustc_target::spec::{ }; use std::any::Any; -use std::cell::{self, RefCell}; use std::env; use std::fmt; use std::ops::{Div, Mul}; @@ -149,7 +150,7 @@ pub struct Session { /// Input, input file path and output file path to this compilation process. pub io: CompilerIO, - incr_comp_session: OneThread>, + incr_comp_session: RwLock, /// Used by `-Z self-profile`. pub prof: SelfProfilerRef, @@ -533,9 +534,9 @@ impl Session { *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory }; } - pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> { + pub fn incr_comp_session_dir(&self) -> MappedReadGuard<'_, PathBuf> { let incr_comp_session = self.incr_comp_session.borrow(); - cell::Ref::map(incr_comp_session, |incr_comp_session| match *incr_comp_session { + ReadGuard::map(incr_comp_session, |incr_comp_session| match *incr_comp_session { IncrCompSession::NotInitialized => panic!( "trying to get session directory from `IncrCompSession`: {:?}", *incr_comp_session, @@ -548,7 +549,7 @@ impl Session { }) } - pub fn incr_comp_session_dir_opt(&self) -> Option> { + pub fn incr_comp_session_dir_opt(&self) -> Option> { self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir()) } @@ -1176,7 +1177,7 @@ pub fn build_session( parse_sess, sysroot, io, - incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), + incr_comp_session: RwLock::new(IncrCompSession::NotInitialized), prof, code_stats: Default::default(), optimization_fuel, From a9e30e6cdf721df1d8085dcc3396cf14651ca69f Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Wed, 17 Jan 2024 01:10:19 -0500 Subject: [PATCH 234/297] Don't use compat versions of implied bounds in ImpliedOutlivesBounds query --- .../traits/query/type_op/implied_outlives_bounds.rs | 4 ++-- tests/ui/associated-inherent-types/issue-111404-1.rs | 1 + .../ui/associated-inherent-types/issue-111404-1.stderr | 10 +++++++++- .../normalization-nested.lifetime.stderr | 10 ---------- tests/ui/implied-bounds/normalization-nested.rs | 5 +---- tests/ui/inference/issue-80409.rs | 10 +++++++++- tests/ui/inference/issue-80409.stderr | 6 ++++++ 7 files changed, 28 insertions(+), 18 deletions(-) delete mode 100644 tests/ui/implied-bounds/normalization-nested.lifetime.stderr create mode 100644 tests/ui/inference/issue-80409.stderr diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index bdc53f895fec..2fdb63d7deeb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -48,14 +48,14 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { param_env.and(ty) }); - tcx.implied_outlives_bounds_compat(canonicalized) + tcx.implied_outlives_bounds(canonicalized) } fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, ) -> Result { - compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty) + compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty) } } diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index dd62e59f07d2..74f9434b8818 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -10,5 +10,6 @@ impl<'a> Foo { fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} //~^ ERROR higher-ranked subtype error //~| ERROR higher-ranked subtype error +//~| ERROR higher-ranked subtype error fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr index cf4d4a5f19b1..1613161a873f 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr @@ -12,5 +12,13 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error: higher-ranked subtype error + --> $DIR/issue-111404-1.rs:10:1 + | +LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr deleted file mode 100644 index 041892c7542a..000000000000 --- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/normalization-nested.rs:38:5 - | -LL | pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { - | -- lifetime `'x` defined here -LL | s - | ^ returning this value requires that `'x` must outlive `'static` - -error: aborting due to 1 previous error - diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs index 87903783a678..3f569aa1acea 100644 --- a/tests/ui/implied-bounds/normalization-nested.rs +++ b/tests/ui/implied-bounds/normalization-nested.rs @@ -1,11 +1,8 @@ // Test for normalization of projections that appear in the item bounds // (versus those that appear directly in the input types). -// Both revisions should pass. `lifetime` revision is a bug. // // revisions: param_ty lifetime -// [param_ty] check-pass -// [lifetime] check-fail -// [lifetime] known-bug: #109799 +// check-pass pub trait Iter { type Item; diff --git a/tests/ui/inference/issue-80409.rs b/tests/ui/inference/issue-80409.rs index 80cad6dfc46e..d36688978e9f 100644 --- a/tests/ui/inference/issue-80409.rs +++ b/tests/ui/inference/issue-80409.rs @@ -1,4 +1,12 @@ -// check-pass +// This should not pass, because `usize: Fsm` does not hold. However, it currently ICEs. + +// check-fail +// known-bug: #80409 +// failure-status: 101 +// normalize-stderr-test "note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +// rustc-env:RUST_BACKTRACE=0 #![allow(unreachable_code, unused)] diff --git a/tests/ui/inference/issue-80409.stderr b/tests/ui/inference/issue-80409.stderr new file mode 100644 index 000000000000..7bb4786db3a9 --- /dev/null +++ b/tests/ui/inference/issue-80409.stderr @@ -0,0 +1,6 @@ +error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } } + | + = query stack during panic: +end of query stack +error: aborting due to 1 previous error + From 0373ce6876864a2f31b0ab885c7ba80e1f69eb15 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 18 Jan 2024 14:36:17 +1100 Subject: [PATCH 235/297] Warn when no profiler runtime means coverage tests won't be run/blessed --- src/tools/compiletest/src/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 34d48559c378..42c751bb6bed 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -15,6 +15,15 @@ fn main() { eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } + if !config.profiler_support && config.mode == Mode::CoverageRun { + let actioned = if config.bless { "blessed" } else { "checked" }; + eprintln!( + r#" +WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned} +help: try setting `profiler = true` in the `[build]` section of `config.toml`"# + ); + } + log_config(&config); run_tests(config); } From 6a573cbc60af8319e11cf0f0a578f8a12caa932d Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 17 Jan 2024 19:35:19 -0800 Subject: [PATCH 236/297] Revert changes to internal method for now - Move fix to a separate PR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 28 ++----------------- compiler/rustc_smir/src/rustc_smir/context.rs | 5 ++-- tests/ui-fulldeps/stable-mir/smir_internal.rs | 4 +-- 3 files changed, 6 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 873bd94e88fb..b99640d2f2d6 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -24,35 +24,11 @@ use std::ops::Index; mod internal; pub mod pretty; -/// Convert an internal Rust compiler item into its stable counterpart, if one exists. -/// -/// # Warning -/// -/// This function is unstable, and its behavior may change at any point. -/// E.g.: Items that were previously supported, may no longer be supported, or its translation may -/// change. -/// -/// # Panics -/// -/// This function will panic if StableMIR has not been properly initialized. pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { with_tables(|tables| item.stable(tables)) } -/// Convert a stable item into its internal Rust compiler counterpart, if one exists. -/// -/// # Warning -/// -/// This function is unstable, and it's behavior may change at any point. -/// Not every stable item can be converted to an internal one. -/// Furthermore, items that were previously supported, may no longer be supported in newer versions. -/// -/// # Panics -/// -/// This function will panic if StableMIR has not been properly initialized. -pub fn internal<'tcx, S: RustcInternal<'tcx>>(tcx: TyCtxt<'tcx>, item: S) -> S::T { - // The tcx argument ensures that the item won't outlive the type context. - let _ = tcx; +pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T { with_tables(|tables| item.internal(tables)) } @@ -293,7 +269,7 @@ macro_rules! optional { }; } -/// Prefer using [run] and [run_with_tcx] instead. +/// Prefer using [run!] and [run_with_tcx] instead. /// /// This macro implements the instantiation of a StableMIR driver, and it will invoke /// the given callback after the compiler analyses. diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 2a2626654a01..fffc454804d2 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -29,7 +29,7 @@ use stable_mir::{Crate, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, S use std::cell::RefCell; use std::iter; -use crate::rustc_internal::RustcInternal; +use crate::rustc_internal::{internal, RustcInternal}; use crate::rustc_smir::builder::BodyBuilder; use crate::rustc_smir::{alloc, new_item_kind, smir_crate, Stable, Tables}; @@ -322,8 +322,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { } fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String { - let mut tables = self.0.borrow_mut(); - cnst.internal(&mut *tables).to_string() + internal(cnst).to_string() } fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index b0811364c09f..b4faaeb4fc06 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -26,11 +26,11 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_translation(tcx: TyCtxt) -> ControlFlow<()> { +fn test_translation(_tcx: TyCtxt) -> ControlFlow<()> { let main_fn = stable_mir::entry_fn().unwrap(); let body = main_fn.body(); let orig_ty = body.locals()[0].ty; - let rustc_ty = rustc_internal::internal(tcx, &orig_ty); + let rustc_ty = rustc_internal::internal(&orig_ty); assert!(rustc_ty.is_unit()); ControlFlow::Continue(()) } From 9650c30fbb9e3741fbc4d01bc64496f7d725212e Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 18 Jan 2024 06:50:06 +0000 Subject: [PATCH 237/297] fix(rust-analyzer): use new pkgid spec to compare Starting from cargo#13311, Cargo's compiler artifact message uses Package ID specification as package's identifier format. --- .../proc-macro-srv/proc-macro-test/build.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs index 6cf2b5643e57..e6903fb8d4ae 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs @@ -92,12 +92,24 @@ fn main() { panic!("proc-macro-test-impl failed to build"); } + // Old Package ID Spec + let repr = format!("{name} {version}"); + // New Package Id Spec since rust-lang/cargo#13311 + let pkgid = String::from_utf8( + Command::new(toolchain::cargo()) + .current_dir(&staging_dir) + .args(["pkgid", name]) + .output() + .unwrap().stdout, + ) + .unwrap(); + let pkgid = pkgid.trim(); + let mut artifact_path = None; for message in Message::parse_stream(output.stdout.as_slice()) { if let Message::CompilerArtifact(artifact) = message.unwrap() { if artifact.target.kind.contains(&"proc-macro".to_string()) { - let repr = format!("{name} {version}"); - if artifact.package_id.repr.starts_with(&repr) { + if artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid { artifact_path = Some(PathBuf::from(&artifact.filenames[0])); } } From 2cc81baaf4b71cb2903f93cfe2222d37feb9a34d Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 18 Jan 2024 12:48:38 +0000 Subject: [PATCH 238/297] tests/ui/asm/inline-syntax: adapt for LLVM 18 --- tests/ui/asm/inline-syntax.arm.stderr | 12 +-- tests/ui/asm/inline-syntax.arm_llvm_18.stderr | 90 +++++++++++++++++++ tests/ui/asm/inline-syntax.rs | 14 ++- tests/ui/asm/inline-syntax.x86_64.stderr | 14 +-- 4 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 tests/ui/asm/inline-syntax.arm_llvm_18.stderr diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr index 1352fb3771be..6bc38811f1b5 100644 --- a/tests/ui/asm/inline-syntax.arm.stderr +++ b/tests/ui/asm/inline-syntax.arm.stderr @@ -13,7 +13,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:32:15 + --> $DIR/inline-syntax.rs:38:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^ @@ -25,7 +25,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:35:15 + --> $DIR/inline-syntax.rs:42:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^ @@ -37,7 +37,7 @@ LL | .intel_syntax aaa noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:46:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^ @@ -49,7 +49,7 @@ LL | .att_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:41:15 + --> $DIR/inline-syntax.rs:50:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^ @@ -61,7 +61,7 @@ LL | .att_syntax bbb noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:44:15 + --> $DIR/inline-syntax.rs:54:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^ @@ -73,7 +73,7 @@ LL | .intel_syntax noprefix; nop | ^ error: unknown directive - --> $DIR/inline-syntax.rs:50:13 + --> $DIR/inline-syntax.rs:61:13 | LL | .intel_syntax noprefix | ^ diff --git a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr new file mode 100644 index 000000000000..4926293bb88a --- /dev/null +++ b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr @@ -0,0 +1,90 @@ +error: unknown directive + | +note: instantiated into assembly here + --> :1:1 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + | +note: instantiated into assembly here + --> :1:1 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:38:15 + | +LL | asm!(".intel_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:42:15 + | +LL | asm!(".intel_syntax aaa noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax aaa noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:46:15 + | +LL | asm!(".att_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .att_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:50:15 + | +LL | asm!(".att_syntax bbb noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .att_syntax bbb noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:54:15 + | +LL | asm!(".intel_syntax noprefix; nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax noprefix; nop + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:61:13 + | +LL | .intel_syntax noprefix + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | .intel_syntax noprefix + | ^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs index d06796e33d51..9398a87df627 100644 --- a/tests/ui/asm/inline-syntax.rs +++ b/tests/ui/asm/inline-syntax.rs @@ -1,4 +1,4 @@ -// revisions: x86_64 arm +// revisions: x86_64 arm arm_llvm_18 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //[x86_64] check-pass //[x86_64] needs-llvm-components: x86 @@ -8,6 +8,12 @@ //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf //[arm] build-fail //[arm] needs-llvm-components: arm +//[arm] ignore-llvm-version: 18 - 99 +// Newer LLVM produces extra error notes. +//[arm_llvm_18] compile-flags: --target armv7-unknown-linux-gnueabihf +//[arm_llvm_18] build-fail +//[arm_llvm_18] needs-llvm-components: arm +//[arm_llvm_18] min-llvm-version: 18 // needs-asm-support #![feature(no_core, lang_items, rustc_attrs)] @@ -32,18 +38,23 @@ pub fn main() { asm!(".intel_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".intel_syntax aaa noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".att_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.att_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".att_syntax bbb noprefix", "nop"); //[x86_64]~^ WARN avoid using `.att_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".intel_syntax noprefix; nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!( r" @@ -52,6 +63,7 @@ pub fn main() { ); //[x86_64]~^^^ WARN avoid using `.intel_syntax` //[arm]~^^^^ ERROR unknown directive + //[arm_llvm_18]~^^^^^ ERROR unknown directive } } diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr index 840b250f87d7..b54b3560447c 100644 --- a/tests/ui/asm/inline-syntax.x86_64.stderr +++ b/tests/ui/asm/inline-syntax.x86_64.stderr @@ -1,5 +1,5 @@ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:58:14 + --> $DIR/inline-syntax.rs:70:14 | LL | global_asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop"); = note: `#[warn(bad_asm_style)]` on by default warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:32:15 + --> $DIR/inline-syntax.rs:38:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:35:15 + --> $DIR/inline-syntax.rs:42:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:46:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:41:15 + --> $DIR/inline-syntax.rs:50:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:44:15 + --> $DIR/inline-syntax.rs:54:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:50:13 + --> $DIR/inline-syntax.rs:61:13 | LL | .intel_syntax noprefix | ^^^^^^^^^^^^^^^^^^^^^^ From c13c746b477cfa3887bd88236c452bb57048f6c6 Mon Sep 17 00:00:00 2001 From: James Dietz Date: Thu, 18 Jan 2024 09:39:38 -0500 Subject: [PATCH 239/297] change unwrap to `?` on write where result is returned --- compiler/rustc_middle/src/mir/pretty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 239929a2c0ef..f74715468a02 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1116,10 +1116,10 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> | ProjectionElem::Subtype(_) | ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { - write!(fmt, "(").unwrap(); + write!(fmt, "(")?; } ProjectionElem::Deref => { - write!(fmt, "(*").unwrap(); + write!(fmt, "(*")?; } ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } From 96b8eb78febe0ff146573b6e7557425a853e612e Mon Sep 17 00:00:00 2001 From: Samuel Moelius <35515885+smoelius@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:32:57 -0500 Subject: [PATCH 240/297] Apply suggestions from code review Co-authored-by: fee1-dead --- src/tools/clippy/clippy_utils/src/ty.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index a07d6587bf97..59ebe685c11e 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -219,7 +219,7 @@ pub fn implements_trait<'tcx>( /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. /// -/// The `callee_id` argument is used to determine the "effect arg", if one is needed. +/// The `callee_id` argument is used to determine whether this is a function call in a `const fn` environment, used for checking const traits. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, @@ -243,7 +243,9 @@ pub fn implements_trait_with_env_from_iter<'tcx>( // Clippy shouldn't have infer types assert!(!ty.has_infer()); - // If a `callee_id` is passed, then "assert" it is a body owner. + // If a `callee_id` is passed, then we assert that it is a body owner + // through calling `body_owner_kind`, which would panic if the callee + // does not have a body. if let Some(callee_id) = callee_id { let _ = tcx.hir().body_owner_kind(callee_id); } From e532b0dd7e632fc017f9f66a1fb24c7183a40dff Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 1 Feb 2023 14:23:51 +0000 Subject: [PATCH 241/297] Don't forget that the lifetime on hir types is `'tcx` --- compiler/rustc_hir/src/hir.rs | 2 +- .../rustc_hir_analysis/src/astconv/bounds.rs | 8 ++- .../src/astconv/generics.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 61 ++++++++++--------- .../src/astconv/object_safety.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 14 ++--- compiler/rustc_hir_analysis/src/lib.rs | 4 +- compiler/rustc_hir_typeck/src/closure.rs | 14 ++--- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 12 ++-- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 6 +- .../rustc_hir_typeck/src/method/confirm.rs | 14 ++--- compiler/rustc_hir_typeck/src/method/mod.rs | 4 +- compiler/rustc_hir_typeck/src/pat.rs | 2 +- .../src/default_union_representation.rs | 2 +- .../clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy/clippy_lints/src/types/mod.rs | 18 +++--- .../src/types/redundant_allocation.rs | 2 +- .../clippy/clippy_lints/src/types/vec_box.rs | 6 +- .../src/unconditional_recursion.rs | 4 +- .../src/uninhabited_references.rs | 6 +- src/tools/clippy/clippy_lints/src/use_self.rs | 2 +- .../clippy_lints/src/zero_sized_map_values.rs | 4 +- 26 files changed, 105 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6b347f7035a3..f1baa0e4dcc1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -248,7 +248,7 @@ pub struct InferArg { } impl InferArg { - pub fn to_ty(&self) -> Ty<'_> { + pub fn to_ty(&self) -> Ty<'static> { Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id } } } diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 2ad96a248912..401efff9242e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -108,14 +108,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. #[instrument(level = "debug", skip(self, ast_bounds, bounds))] - pub(crate) fn add_bounds<'hir, I: Iterator>>( + pub(crate) fn add_bounds<'hir, I: Iterator>>( &self, param_ty: Ty<'tcx>, ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, only_self_bounds: OnlySelfBounds, - ) { + ) where + 'tcx: 'hir, + { for ast_bound in ast_bounds { match ast_bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { @@ -179,7 +181,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { pub(crate) fn compute_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'tcx>], filter: PredicateFilter, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index e2cd4d5f21c7..f9628d1d6f3e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -168,7 +168,7 @@ fn generic_arg_mismatch_err( /// instantiate a `GenericArg`. /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then /// creates a suitable inference variable. -pub fn create_args_for_parent_generic_args<'tcx, 'a>( +pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( tcx: TyCtxt<'tcx>, def_id: DefId, parent_args: &[ty::GenericArg<'tcx>], diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9f4f1413650f..671194611082 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -122,7 +122,7 @@ pub trait AstConv<'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>; @@ -156,14 +156,14 @@ struct ConvertedBinding<'a, 'tcx> { hir_id: hir::HirId, item_name: Ident, kind: ConvertedBindingKind<'a, 'tcx>, - gen_args: &'a GenericArgs<'a>, + gen_args: &'tcx GenericArgs<'tcx>, span: Span, } #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { Equality(Spanned>), - Constraint(&'a [hir::GenericBound<'a>]), + Constraint(&'a [hir::GenericBound<'tcx>]), } /// New-typed boolean indicating whether explicit late-bound lifetimes @@ -215,12 +215,12 @@ pub struct GenericArgCountResult { } pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { - fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool); + fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool); fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx>; fn inferred_kind( @@ -294,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, ) -> GenericArgsRef<'tcx> { let (args, _) = self.create_args_for_ast_path( span, @@ -351,7 +351,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, parent_args: &[ty::GenericArg<'tcx>], seg: &hir::PathSegment<'_>, - generic_args: &'a hir::GenericArgs<'_>, + generic_args: &'a hir::GenericArgs<'tcx>, infer_args: bool, self_ty: Option>, constness: ty::BoundConstness, @@ -406,14 +406,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { struct SubstsForAstPathCtxt<'a, 'tcx> { astconv: &'a (dyn AstConv<'tcx> + 'a), def_id: DefId, - generic_args: &'a GenericArgs<'a>, + generic_args: &'a GenericArgs<'tcx>, span: Span, inferred_params: Vec, infer_args: bool, } impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> { - fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) { + fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) { if did == self.def_id { (Some(self.generic_args), self.infer_args) } else { @@ -425,11 +425,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { let tcx = self.astconv.tcx(); - let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| { + let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { if has_default { tcx.check_optional_stability( param.def_id, @@ -592,7 +592,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn create_assoc_bindings_for_generic_args<'a>( &self, - generic_args: &'a hir::GenericArgs<'_>, + generic_args: &'a hir::GenericArgs<'tcx>, ) -> Vec> { // Convert associated-type bindings or constraints into a separate vector. // Example: Given this: @@ -640,7 +640,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, parent_args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { debug!( @@ -673,7 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// are disallowed. Otherwise, they are pushed onto the vector given. pub fn instantiate_mono_trait_ref( &self, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, ) -> ty::TraitRef<'tcx> { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); @@ -710,7 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))] pub(crate) fn instantiate_poly_trait_ref( &self, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &hir::TraitRef<'tcx>, span: Span, constness: ty::BoundConstness, polarity: ty::ImplPolarity, @@ -788,7 +788,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, - trait_segment: &hir::PathSegment<'_>, + trait_segment: &hir::PathSegment<'tcx>, is_impl: bool, // FIXME(effects) move all host param things in astconv to hir lowering constness: ty::BoundConstness, @@ -813,7 +813,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, - trait_segment: &'a hir::PathSegment<'a>, + trait_segment: &'a hir::PathSegment<'tcx>, is_impl: bool, constness: ty::BoundConstness, ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) { @@ -847,7 +847,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, did: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx(); let args = self.ast_path_args_for_ty(span, did, item_segment); @@ -1153,7 +1153,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, qself_ty: Ty<'tcx>, qself: &hir::Ty<'_>, - assoc_segment: &hir::PathSegment<'_>, + assoc_segment: &hir::PathSegment<'tcx>, permit_variants: bool, ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> { let tcx = self.tcx(); @@ -1428,7 +1428,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn lookup_inherent_assoc_ty( &self, name: Ident, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, adt_did: DefId, self_ty: Ty<'tcx>, block: hir::HirId, @@ -1702,8 +1702,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, opt_self_ty: Option>, item_def_id: DefId, - trait_segment: &hir::PathSegment<'_>, - item_segment: &hir::PathSegment<'_>, + trait_segment: &hir::PathSegment<'tcx>, + item_segment: &hir::PathSegment<'tcx>, constness: ty::BoundConstness, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2021,7 +2021,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn res_to_ty( &self, opt_self_ty: Option>, - path: &hir::Path<'_>, + path: &hir::Path<'tcx>, hir_id: hir::HirId, permit_variants: bool, ) -> Ty<'tcx> { @@ -2311,13 +2311,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Parses the programmer's textual representation of a type into our /// internal notion of a type. - pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false, false) } /// Parses the programmer's textual representation of a type into our /// internal notion of a type. This is meant to be used within a path. - pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false, true) } @@ -2432,7 +2432,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[instrument(level = "debug", skip(self), ret)] - fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> { + fn ast_ty_to_ty_inner( + &self, + ast_ty: &hir::Ty<'tcx>, + borrowed: bool, + in_path: bool, + ) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match &ast_ty.kind { @@ -2609,7 +2614,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { + pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option>) -> Ty<'tcx> { match ty.kind { hir::TyKind::Infer if expected_ty.is_some() => { self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); @@ -2625,7 +2630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir_id: hir::HirId, unsafety: hir::Unsafety, abi: abi::Abi, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, generics: Option<&hir::Generics<'_>>, hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index f77f250cd288..8967b51749c8 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -22,7 +22,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, hir_id: hir::HirId, - hir_trait_bounds: &[hir::PolyTraitRef<'_>], + hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, borrowed: bool, representation: DynKind, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4772bae58c47..2a55a58a668a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1736,7 +1736,7 @@ fn receiver_is_implemented<'tcx>( fn check_variances_for_type_defn<'tcx>( tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, - hir_generics: &hir::Generics<'_>, + hir_generics: &hir::Generics<'tcx>, ) { let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e557f36037b6..d8ce2307995c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -348,7 +348,7 @@ impl<'tcx> ItemCtxt<'tcx> { ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) } } - pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.astconv().ast_ty_to_ty(ast_ty) } @@ -412,7 +412,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { @@ -1148,7 +1148,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder( tcx: TyCtxt<'tcx>, - sig: &hir::FnSig<'_>, + sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'_>, def_id: LocalDefId, icx: &ItemCtxt<'tcx>, @@ -1352,14 +1352,14 @@ fn impl_trait_ref( let last_arg = args.args.len() - 1; assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects)); args.args = &args.args[..args.args.len() - 1]; - path_segments[last_segment].args = Some(&args); + path_segments[last_segment].args = Some(tcx.hir_arena.alloc(args)); let path = hir::Path { span: ast_trait_ref.path.span, res: ast_trait_ref.path.res, - segments: &path_segments, + segments: tcx.hir_arena.alloc_slice(&path_segments), }; - let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id }; - icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty) + let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: ast_trait_ref.hir_ref_id }); + icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty) } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f5abb7261c00..4b371a4d2e67 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -225,7 +225,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { /// A quasi-deprecated helper used in rustdoc and clippy to get /// the type from a HIR node. -pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { // In case there are any projections, etc., find the "environment" // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. @@ -236,7 +236,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { pub fn hir_trait_to_predicates<'tcx>( tcx: TyCtxt<'tcx>, - hir_trait: &hir::TraitRef<'_>, + hir_trait: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, ) -> Bounds<'tcx> { // In case there are any projections, etc., find the "environment" diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index d11198d7fd4e..210d383ac7ff 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -373,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { @@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_no_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, ) -> ClosureSignatures<'tcx> { let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, closure_kind); @@ -449,7 +449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_with_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { @@ -506,7 +506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_with_mismatched_number_of_arguments( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { let expr_map_node = self.tcx.hir_node_by_def_id(expr_def_id); @@ -547,7 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn merge_supplied_sig_with_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, mut expected_sigs: ClosureSignatures<'tcx>, ) -> InferResult<'tcx, ClosureSignatures<'tcx>> { @@ -641,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn supplied_sig_of_closure( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; @@ -837,7 +837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// all parameters are of type `ty::Error`. fn error_sig_of_closure( &self, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, guar: ErrorGuaranteed, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 0576ab3b80c4..e15754877d9f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1315,7 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_method_call( &self, expr: &'tcx hir::Expr<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, rcvr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, @@ -1627,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &hir::Expr<'_>, expected: Expectation<'tcx>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a4cd9ccc984e..3ea409827b4b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -377,13 +377,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { RawTy { raw: ty, normalized: self.normalize(span, ty) } } - pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> { + pub fn to_ty(&self, ast_t: &hir::Ty<'tcx>) -> RawTy<'tcx> { let t = self.astconv().ast_ty_to_ty(ast_t); self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None)); self.handle_raw_ty(ast_t.span, t) } - pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); @@ -1073,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self, span), level = "debug")] pub fn instantiate_value_path( &self, - segments: &[hir::PathSegment<'_>], + segments: &'tcx [hir::PathSegment<'tcx>], self_ty: Option>, res: Res, span: Span, @@ -1260,13 +1260,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, path_segs: &'a [PathSeg], infer_args_for_err: &'a FxHashSet, - segments: &'a [hir::PathSegment<'a>], + segments: &'tcx [hir::PathSegment<'tcx>], } impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, - ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { + ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) { if let Some(&PathSeg(_, index)) = self.path_segs.iter().find(|&PathSeg(did, _)| *did == def_id) { @@ -1287,7 +1287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f42f58322dce..ddb4224b60db 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1327,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_struct_path( &self, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, hir_id: hir::HirId, ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> { let path_span = qpath.span(); @@ -1783,7 +1783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The newly resolved definition is written into `type_dependent_defs`. fn finish_resolving_struct_path( &self, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, path_span: Span, hir_id: hir::HirId, ) -> (Res, RawTy<'tcx>) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index fde3d41faecf..40a40b0a73f6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -287,7 +287,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { let trait_ref = self.instantiate_binder_with_fresh_vars( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 81b7de7f6349..2778ada655e3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -784,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn suggest_missing_return_type( &self, err: &mut Diagnostic, - fn_decl: &hir::FnDecl<'_>, + fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool, @@ -995,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, expr: &'tcx hir::Expr<'tcx>, - fn_decl: &hir::FnDecl<'_>, + fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, id: hir::HirId, @@ -1468,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn suggest_associated_const( &self, err: &mut Diagnostic, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { let Some((DefKind::AssocFn, old_def_id)) = diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index b2ead3cd40b7..6f18cc51b11c 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { debug!( "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", @@ -68,7 +68,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); confirm_cx.skip_record_for_diagnostics = true; @@ -90,7 +90,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { &mut self, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick); @@ -346,7 +346,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn instantiate_method_args( &mut self, pick: &probe::Pick<'tcx>, - seg: &hir::PathSegment<'_>, + seg: &hir::PathSegment<'tcx>, parent_args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { // Determine the values for the generic parameters of the method. @@ -370,13 +370,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { struct MethodSubstsCtxt<'a, 'tcx> { cfcx: &'a ConfirmContext<'a, 'tcx>, pick: &'a probe::Pick<'tcx>, - seg: &'a hir::PathSegment<'a>, + seg: &'a hir::PathSegment<'tcx>, } impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, - ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { + ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) { if def_id == self.pick.item.def_id { if let Some(data) = self.seg.args { return (Some(data), false); @@ -388,7 +388,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index c746fb8af89a..af172b59a146 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lookup_method( &self, self_ty: Ty<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, @@ -255,7 +255,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lookup_method_for_diagnostic( &self, self_ty: Ty<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 95813cb68a66..b87f9bc8b19e 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -856,7 +856,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_struct( &self, pat: &'tcx Pat<'tcx>, - qpath: &hir::QPath<'_>, + qpath: &hir::QPath<'tcx>, fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, expected: Ty<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index db01ff2cd220..bfd89bfd2c72 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { /// (ZST fields having an arbitrary offset is completely inconsequential, and /// if there is only one field left after ignoring ZST fields then the offset /// of that field does not matter either.) -fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool { +fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { if let ItemKind::Union(..) = &item.kind && let ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() { diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 788fe8287278..87f6f5e7959e 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -210,7 +210,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a `BuildHasher`. - fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option { + fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Option { if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind { let params: Vec<_> = path .segments diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 81efec65343d..7882bfdd09fa 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -314,9 +314,9 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, fn_kind: FnKind<'_>, - decl: &FnDecl<'_>, + decl: &FnDecl<'tcx>, _: &Body<'_>, _: Span, def_id: LocalDefId, @@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { @@ -363,7 +363,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) { match item.kind { ImplItemKind::Const(ty, _) => { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx @@ -391,7 +391,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { + fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(field.def_id); self.check_ty( @@ -404,7 +404,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); let context = CheckTyContext { @@ -421,7 +421,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { if let Some(ty) = local.ty { self.check_ty( cx, @@ -444,7 +444,7 @@ impl Types { } } - fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) { + fn check_fn_decl<'tcx>(&mut self, cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, context: CheckTyContext) { // Ignore functions in trait implementations as they are usually forced by the trait definition. // // FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard @@ -466,7 +466,7 @@ impl Types { /// lint found. /// /// The parameter `is_local` distinguishes the context of the type. - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, mut context: CheckTyContext) { if hir_ty.span.from_expansion() { return; } diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 5a986254fad5..a0d609501a0c 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::sym; use super::{utils, REDUNDANT_ALLOCATION}; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool { let mut applicability = Applicability::MaybeIncorrect; let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() { "Box" diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 9d5066199bde..a285f771f1b1 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -13,10 +13,10 @@ use rustc_span::symbol::sym; use super::VEC_BOX; -pub(super) fn check( - cx: &LateContext<'_>, +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, def_id: DefId, box_size_threshold: u64, ) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index e90306ded61c..b418db53ea47 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -77,7 +77,7 @@ fn get_ty_def_id(ty: Ty<'_>) -> Option { } } -fn get_hir_ty_def_id(tcx: TyCtxt<'_>, hir_ty: rustc_hir::Ty<'_>) -> Option { +fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Option { let TyKind::Path(qpath) = hir_ty.kind else { return None }; match qpath { QPath::Resolved(_, path) => path.res.opt_def_id(), @@ -229,7 +229,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local } } -fn is_default_method_on_current_ty(tcx: TyCtxt<'_>, qpath: QPath<'_>, implemented_ty_id: DefId) -> bool { +fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>, implemented_ty_id: DefId) -> bool { match qpath { QPath::Resolved(_, path) => match path.segments { [first, .., last] => last.ident.name == kw::Default && first.res.opt_def_id() == Some(implemented_ty_id), diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs index 903593ecfd7d..6732a43a19ec 100644 --- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs +++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs @@ -57,11 +57,11 @@ impl LateLintPass<'_> for UninhabitedReferences { } } - fn check_fn( + fn check_fn<'tcx>( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, kind: FnKind<'_>, - fndecl: &'_ FnDecl<'_>, + fndecl: &'_ FnDecl<'tcx>, _: &'_ Body<'_>, span: Span, _: LocalDefId, diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index fa033838ef35..a1b08d105b9d 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if !hir_ty.span.from_expansion() && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index b36c4ef91dc6..81d4a26e9da4 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); impl LateLintPass<'_> for ZeroSizedMapValues { - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if !hir_ty.span.from_expansion() && !in_trait_impl(cx, hir_ty.hir_id) && let ty = ty_from_hir_ty(cx, hir_ty) @@ -82,7 +82,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { false } -fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { cx.maybe_typeck_results() .and_then(|results| { if results.hir_owner == hir_ty.hir_id.owner { From 108732590d010c701dd6f665b5ebddff52ef0ab0 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Fri, 19 Jan 2024 01:25:15 +0900 Subject: [PATCH 242/297] Fix typo in munmap_partial.rs addres -> address --- src/tools/miri/tests/fail-dep/shims/munmap_partial.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs index 1d6e4796d0a5..d7aef47235f1 100644 --- a/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs +++ b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs @@ -1,5 +1,5 @@ //! The man pages for mmap/munmap suggest that it is possible to partly unmap a previously-mapped -//! region of addres space, but to LLVM that would be partial deallocation, which LLVM does not +//! region of address space, but to LLVM that would be partial deallocation, which LLVM does not //! support. So even though the man pages say this sort of use is possible, we must report UB. //@ignore-target-windows: No libc on Windows //@normalize-stderr-test: "size [0-9]+ and alignment" -> "size SIZE and alignment" From 21b4fe222f73e5f2b1791004071d73c19a63d08c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 18 Jan 2024 15:50:40 +0300 Subject: [PATCH 243/297] Set RUSTC_BOOTSTRAP=1 consistently Signed-off-by: onur-ozkan --- src/bootstrap/bootstrap.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6f3be1f6e938..28d96cb1cfe5 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -924,14 +924,17 @@ class RustBuild(object): # default toolchain is not nightly. # # But that setting has the collateral effect of rust-analyzer also - # passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various - # overrideCommand). For compiling bootstrap, that is unwanted and can - # cause spurious rebuilding of bootstrap when rust-analyzer x.py - # invocations are interleaved with handwritten ones on the command line. - env.pop("RUSTC_BOOTSTRAP", None) + # passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various overrideCommand). + # For compiling bootstrap that can cause spurious rebuilding of bootstrap when + # rust-analyzer x.py invocations are interleaved with handwritten ones on the + # command line. + # + # Set RUSTC_BOOTSTRAP=1 consistently. + env["RUSTC_BOOTSTRAP"] = "1" - # preserve existing RUSTFLAGS - env.setdefault("RUSTFLAGS", "") + default_rustflags = "" if env.get("RUSTFLAGS_BOOTSTRAP", "") else "-Zallow-features=" + + env.setdefault("RUSTFLAGS", default_rustflags) target_features = [] if self.get_toml("crt-static", build_section) == "true": From d95d6ceecb372c66ed18a4e7a0bbb79e74ee8fed Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 12:54:01 -0500 Subject: [PATCH 244/297] `dead_code` treats `#[repr(transparent)]` the same as `#[repr(C)]` Fixes #119659 --- compiler/rustc_passes/src/dead.rs | 18 ++++++++++-------- tests/ui/lint/dead-code/type-in-transparent.rs | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 tests/ui/lint/dead-code/type-in-transparent.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9422a5944881..d7f17ac4547a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> { tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, live_symbols: LocalDefIdSet, - repr_has_repr_c: bool, + repr_unconditionally_treats_fields_as_live: bool, repr_has_repr_simd: bool, in_pat: bool, ignore_variant_stack: Vec, @@ -365,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return; } - let had_repr_c = self.repr_has_repr_c; + let unconditionally_treated_fields_as_live = + self.repr_unconditionally_treats_fields_as_live; let had_repr_simd = self.repr_has_repr_simd; - self.repr_has_repr_c = false; + self.repr_unconditionally_treats_fields_as_live = false; self.repr_has_repr_simd = false; match node { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(item.owner_id); - self.repr_has_repr_c = def.repr().c(); + self.repr_unconditionally_treats_fields_as_live = + def.repr().c() || def.repr().transparent(); self.repr_has_repr_simd = def.repr().simd(); intravisit::walk_item(self, item) @@ -411,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { _ => {} } self.repr_has_repr_simd = had_repr_simd; - self.repr_has_repr_c = had_repr_c; + self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live; } fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) { @@ -435,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) { let tcx = self.tcx; - let has_repr_c = self.repr_has_repr_c; + let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live; let has_repr_simd = self.repr_has_repr_simd; let live_fields = def.fields().iter().filter_map(|f| { let def_id = f.def_id; - if has_repr_c || (f.is_positional() && has_repr_simd) { + if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) { return Some(def_id); } if !tcx.visibility(f.hir_id.owner.def_id).is_public() { @@ -741,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits( tcx, maybe_typeck_results: None, live_symbols: Default::default(), - repr_has_repr_c: false, + repr_unconditionally_treats_fields_as_live: false, repr_has_repr_simd: false, in_pat: false, ignore_variant_stack: vec![], diff --git a/tests/ui/lint/dead-code/type-in-transparent.rs b/tests/ui/lint/dead-code/type-in-transparent.rs new file mode 100644 index 000000000000..5dd6f93fd031 --- /dev/null +++ b/tests/ui/lint/dead-code/type-in-transparent.rs @@ -0,0 +1,14 @@ +// Verify that we do not warn on fields that are part of transparent types. +// check-pass +#![deny(dead_code)] + +#[repr(transparent)] +struct NamedStruct { field: u8 } + +#[repr(transparent)] +struct TupleStruct(u8); + +fn main() { + let _ = NamedStruct { field: 1 }; + let _ = TupleStruct(1); +} From fb7762b1c51d67a56324b92fd79c85b33d5d1d3b Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:14 -0500 Subject: [PATCH 245/297] Remove no-longer-needed `allow(dead_code)` from the standard library `repr(transparent)` now silences the lint. --- library/alloc/src/boxed/thin.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 9463b73b574f..f83c8f83cc98 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -171,7 +171,6 @@ struct WithHeader(NonNull, PhantomData); /// An opaque representation of `WithHeader` to avoid the /// projection invariance of `::Metadata`. #[repr(transparent)] -#[allow(dead_code)] // Field only used through `WithHeader` type above. struct WithOpaqueHeader(NonNull); impl WithOpaqueHeader { From 92cc57bafcea1380e2a8f7a6a732302b04c28c5f Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:35 -0500 Subject: [PATCH 246/297] Remove no-longer-needed `allow(dead_code)` from the tests `repr(transparent)` now silences the lint. --- tests/ui/consts/transmute-const.rs | 2 +- tests/ui/layout/unsafe-cell-hides-niche.rs | 2 +- tests/ui/packed/packed-struct-drop-aligned.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/consts/transmute-const.rs b/tests/ui/consts/transmute-const.rs index 65e5700d083f..5044d99ec518 100644 --- a/tests/ui/consts/transmute-const.rs +++ b/tests/ui/consts/transmute-const.rs @@ -3,7 +3,7 @@ use std::mem; #[repr(transparent)] -struct Foo(#[allow(dead_code)] u32); +struct Foo(u32); const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) }; diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs index 8d6cea109336..e87c402f8f96 100644 --- a/tests/ui/layout/unsafe-cell-hides-niche.rs +++ b/tests/ui/layout/unsafe-cell-hides-niche.rs @@ -17,7 +17,7 @@ use std::sync::{Mutex, RwLock}; struct Wrapper(#[allow(dead_code)] T); #[repr(transparent)] -struct Transparent(#[allow(dead_code)] T); +struct Transparent(T); struct NoNiche(UnsafeCell); diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs index 6c2907c86e91..ddfc86f74d3c 100644 --- a/tests/ui/packed/packed-struct-drop-aligned.rs +++ b/tests/ui/packed/packed-struct-drop-aligned.rs @@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> { } #[repr(transparent)] -struct NotCopy(#[allow(dead_code)] u8); +struct NotCopy(u8); #[repr(packed)] struct Packed<'a>(NotCopy, Aligned<'a>); From aeeaed9ce137d489f7157202548d2ce3d65c60ae Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:24 -0500 Subject: [PATCH 247/297] Remove no-longer-needed `allow(dead_code)` from Miri tests `repr(transparent)` now silences the lint. --- src/tools/miri/tests/fail/issue-miri-1112.rs | 2 +- src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/fail/issue-miri-1112.rs b/src/tools/miri/tests/fail/issue-miri-1112.rs index 9542673b0d9e..387253a3f987 100644 --- a/src/tools/miri/tests/fail/issue-miri-1112.rs +++ b/src/tools/miri/tests/fail/issue-miri-1112.rs @@ -1,7 +1,7 @@ trait Empty {} #[repr(transparent)] -pub struct FunnyPointer(#[allow(dead_code)] dyn Empty); +pub struct FunnyPointer(dyn Empty); #[repr(C)] pub struct Meta { diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs index 2283231eb010..d71d5954a40c 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs @@ -1,7 +1,7 @@ //@compile-flags: -Cdebug-assertions=no #[repr(transparent)] -struct HasDrop(#[allow(dead_code)] u8); +struct HasDrop(u8); impl Drop for HasDrop { fn drop(&mut self) {} From 9d15b5037f7b263a6e9e4a675f026851578be744 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Jan 2024 00:41:56 +0000 Subject: [PATCH 248/297] Remove next_root_ty_var --- compiler/rustc_hir_typeck/src/closure.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index d11198d7fd4e..a67def2f5b1f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let parent_args = GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id())); - let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { + let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, }); @@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create a type variable (for now) to represent the closure kind. // It will be unified during the upvar inference phase (`upvar.rs`) - None => self.next_root_ty_var(TypeVariableOrigin { + None => self.next_ty_var(TypeVariableOrigin { // FIXME(eddyb) distinguish closure kind inference variables from the rest. kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index fde3d41faecf..f3d70867e375 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -190,10 +190,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn errors_reported_since_creation(&self) -> bool { self.dcx().err_count() > self.err_count_on_creation } - - pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - Ty::new_var(self.tcx, self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) - } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { From 7fead95cec9a4a0c05de6d1d22a6fbe0b8594dd8 Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Thu, 18 Jan 2024 21:04:31 +0100 Subject: [PATCH 249/297] Remove myself from review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index bd14640e280e..b3f3051e177f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -644,7 +644,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", - "@WaffleLapkin", "@b-naber", ] compiler = [ From a947c4c2c34a5bc1f25d5e9fd5cc269b4ae0d330 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 17:19:28 +0100 Subject: [PATCH 250/297] Add tests --- tests/ui/pattern/never_patterns.stderr | 17 ----- .../rfc-0000-never_patterns/typeck.rs} | 64 +++++++++++++++---- 2 files changed, 51 insertions(+), 30 deletions(-) delete mode 100644 tests/ui/pattern/never_patterns.stderr rename tests/ui/{pattern/never_patterns.rs => rfcs/rfc-0000-never_patterns/typeck.rs} (62%) diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr deleted file mode 100644 index 20eeb01cf714..000000000000 --- a/tests/ui/pattern/never_patterns.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0005]: refutable pattern in local binding - --> $DIR/never_patterns.rs:10:9 - | -LL | let Ok(_x) = res; - | ^^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: the matched value is of type `Result` -help: you might want to use `let else` to handle the variant that isn't matched - | -LL | let Ok(_x) = res else { todo!() }; - | ++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs similarity index 62% rename from tests/ui/pattern/never_patterns.rs rename to tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 8f44f8a65593..90ff34e2f02b 100644 --- a/tests/ui/pattern/never_patterns.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -1,63 +1,84 @@ +// check-pass #![feature(never_patterns)] +#![feature(exhaustive_patterns)] #![allow(incomplete_features)] +#[derive(Copy, Clone)] enum Void {} fn main() {} // The classic use for empty types. -fn safe_unwrap_result(res: Result) { - let Ok(_x) = res; //~ ERROR refutable pattern in local binding +fn safe_unwrap_result(res: Result) { + let Ok(_x) = res; let (Ok(_x) | Err(!)) = &res; - let (Ok(_x) | Err(&!)) = res.as_ref(); + let (Ok(_x) | Err(!)) = res.as_ref(); } // Check we only accept `!` where we want to. -fn never_pattern_location(void: Void) { +fn never_pattern_typeck(void: Void) { // FIXME(never_patterns): Don't accept on a non-empty type. + match () { + !, + } + match (0, false) { + !, + } + match (0, false) { + (_, !), + } match Some(0) { None => {} Some(!), } + // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches. match () { () => {} !, } + // FIXME(never_patterns): Don't accept even on an empty branch. match None:: { None => {} !, } + match (&[] as &[Void]) { + [] => {} + !, + } // FIXME(never_patterns): Let alone if the emptiness is behind a reference. match None::<&Void> { None => {} !, } + // Participate in match ergonomics. match &void { - ! + !, } match &&void { - ! + !, } match &&void { - &! + &!, } match &None:: { None => {} - Some(!) + Some(!), } match None::<&Void> { None => {} Some(!), } - // Accept on a composite empty type. - match None::<&(u32, Void)> { - None => {} - Some(&!), + + // Accept on a directly empty type. + match void { + !, + } + match &void { + &!, } - // Accept on an simple empty type. match None:: { None => {} Some(!), @@ -70,4 +91,21 @@ fn never_pattern_location(void: Void) { None => {} Some(&(_, !)), } + match (&[] as &[Void]) { + [] => {} + [!], + } + // Accept on a composite empty type. + match None::<&(u32, Void)> { + None => {} + Some(&!), + } + match None::<&(u32, Void)> { + None => {} + Some(!), + } + match None::<&Result> { + None => {} + Some(!), + } } From d8b72e796e4e2bc31701e2197c4bc6f324adbf64 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 17:21:09 +0100 Subject: [PATCH 251/297] Typecheck never patterns --- compiler/rustc_hir_typeck/src/pat.rs | 3 +- compiler/rustc_mir_build/messages.ftl | 5 ++ compiler/rustc_mir_build/src/errors.rs | 10 +++ .../src/thir/pattern/check_match.rs | 16 +++++ .../ui/rfcs/rfc-0000-never_patterns/typeck.rs | 17 +++-- .../rfc-0000-never_patterns/typeck.stderr | 66 +++++++++++++++++++ 6 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index fe8c36dbe069..2060e01e1d61 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -178,8 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = match pat.kind { PatKind::Wild | PatKind::Err(_) => expected, - // FIXME(never_patterns): check the type is uninhabited. If that is not possible within - // typeck, do that in a later phase. + // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti), PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 615b553434fe..2f11cb123ee1 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -234,6 +234,11 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa mir_build_non_const_path = runtime values cannot be referenced in patterns +mir_build_non_empty_never_pattern = + mismatched types + .label = a never pattern must be used on an uninhabited type + .note = the matched value is of type `{$ty}` + mir_build_non_exhaustive_match_all_arms_guarded = match arms with guards don't count towards exhaustivity diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 61ad99acf38a..e3cc21cef11c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -788,6 +788,16 @@ pub struct FloatPattern; #[diag(mir_build_pointer_pattern)] pub struct PointerPattern; +#[derive(Diagnostic)] +#[diag(mir_build_non_empty_never_pattern)] +#[note] +pub struct NonEmptyNeverPattern<'tcx> { + #[primary_span] + #[label] + pub span: Span, + pub ty: Ty<'tcx>, +} + #[derive(LintDiagnostic)] #[diag(mir_build_indirect_structural_match)] #[note(mir_build_type_not_structural_tip)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f6c5e4a5cd6e..6b08f6eb7c58 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -276,10 +276,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { } else { // Check the pattern for some things unrelated to exhaustiveness. let refutable = if cx.refutable { Refutable } else { Irrefutable }; + let mut err = Ok(()); pat.walk_always(|pat| { check_borrow_conflicts_in_at_patterns(self, pat); check_for_bindings_named_same_as_variants(self, pat, refutable); + err = err.and(check_never_pattern(cx, pat)); }); + err?; Ok(cx.pattern_arena.alloc(cx.lower_pat(pat))) } } @@ -811,6 +814,19 @@ fn check_for_bindings_named_same_as_variants( } } +/// Check that never patterns are only used on inhabited types. +fn check_never_pattern<'tcx>( + cx: &MatchCheckCtxt<'_, 'tcx>, + pat: &Pat<'tcx>, +) -> Result<(), ErrorGuaranteed> { + if let PatKind::Never = pat.kind { + if !cx.is_uninhabited(pat.ty) { + return Err(cx.tcx.dcx().emit_err(NonEmptyNeverPattern { span: pat.span, ty: pat.ty })); + } + } + Ok(()) +} + fn report_irrefutable_let_patterns( tcx: TyCtxt<'_>, id: HirId, diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 90ff34e2f02b..333108e92c0c 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(never_patterns)] #![feature(exhaustive_patterns)] #![allow(incomplete_features)] @@ -17,40 +16,48 @@ fn safe_unwrap_result(res: Result) { // Check we only accept `!` where we want to. fn never_pattern_typeck(void: Void) { - // FIXME(never_patterns): Don't accept on a non-empty type. + // Don't accept on a non-empty type. match () { !, + //~^ ERROR: mismatched types } match (0, false) { !, + //~^ ERROR: mismatched types } match (0, false) { (_, !), + //~^ ERROR: mismatched types } match Some(0) { None => {} Some(!), + //~^ ERROR: mismatched types } - // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches. + // Don't accept on an arbitrary type, even if there are no more branches. match () { () => {} !, + //~^ ERROR: mismatched types } - // FIXME(never_patterns): Don't accept even on an empty branch. + // Don't accept even on an empty branch. match None:: { None => {} !, + //~^ ERROR: mismatched types } match (&[] as &[Void]) { [] => {} !, + //~^ ERROR: mismatched types } - // FIXME(never_patterns): Let alone if the emptiness is behind a reference. + // Let alone if the emptiness is behind a reference. match None::<&Void> { None => {} !, + //~^ ERROR: mismatched types } // Participate in match ergonomics. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr new file mode 100644 index 000000000000..8c0475894de3 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr @@ -0,0 +1,66 @@ +error: mismatched types + --> $DIR/typeck.rs:21:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `()` + +error: mismatched types + --> $DIR/typeck.rs:25:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `(i32, bool)` + +error: mismatched types + --> $DIR/typeck.rs:29:13 + | +LL | (_, !), + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `bool` + +error: mismatched types + --> $DIR/typeck.rs:34:14 + | +LL | Some(!), + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `i32` + +error: mismatched types + --> $DIR/typeck.rs:41:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `()` + +error: mismatched types + --> $DIR/typeck.rs:48:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `Option` + +error: mismatched types + --> $DIR/typeck.rs:53:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `[Void]` + +error: mismatched types + --> $DIR/typeck.rs:59:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `Option<&Void>` + +error: aborting due to 8 previous errors + From ff6fa67a9dd61cafe44446ff2910e14ad78584c2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 16 Jan 2024 16:39:38 +0100 Subject: [PATCH 252/297] Split-off the passing tests to ensure they pass --- .../{typeck.stderr => typeck.fail.stderr} | 16 ++++++------ .../ui/rfcs/rfc-0000-never_patterns/typeck.rs | 25 ++++++++++++------- 2 files changed, 24 insertions(+), 17 deletions(-) rename tests/ui/rfcs/rfc-0000-never_patterns/{typeck.stderr => typeck.fail.stderr} (88%) diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr similarity index 88% rename from tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr rename to tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr index 8c0475894de3..013a8b53a550 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr @@ -1,5 +1,5 @@ error: mismatched types - --> $DIR/typeck.rs:21:9 + --> $DIR/typeck.rs:25:9 | LL | !, | ^ a never pattern must be used on an uninhabited type @@ -7,7 +7,7 @@ LL | !, = note: the matched value is of type `()` error: mismatched types - --> $DIR/typeck.rs:25:9 + --> $DIR/typeck.rs:29:9 | LL | !, | ^ a never pattern must be used on an uninhabited type @@ -15,7 +15,7 @@ LL | !, = note: the matched value is of type `(i32, bool)` error: mismatched types - --> $DIR/typeck.rs:29:13 + --> $DIR/typeck.rs:33:13 | LL | (_, !), | ^ a never pattern must be used on an uninhabited type @@ -23,7 +23,7 @@ LL | (_, !), = note: the matched value is of type `bool` error: mismatched types - --> $DIR/typeck.rs:34:14 + --> $DIR/typeck.rs:38:14 | LL | Some(!), | ^ a never pattern must be used on an uninhabited type @@ -31,7 +31,7 @@ LL | Some(!), = note: the matched value is of type `i32` error: mismatched types - --> $DIR/typeck.rs:41:9 + --> $DIR/typeck.rs:45:9 | LL | !, | ^ a never pattern must be used on an uninhabited type @@ -39,7 +39,7 @@ LL | !, = note: the matched value is of type `()` error: mismatched types - --> $DIR/typeck.rs:48:9 + --> $DIR/typeck.rs:52:9 | LL | !, | ^ a never pattern must be used on an uninhabited type @@ -47,7 +47,7 @@ LL | !, = note: the matched value is of type `Option` error: mismatched types - --> $DIR/typeck.rs:53:9 + --> $DIR/typeck.rs:57:9 | LL | !, | ^ a never pattern must be used on an uninhabited type @@ -55,7 +55,7 @@ LL | !, = note: the matched value is of type `[Void]` error: mismatched types - --> $DIR/typeck.rs:59:9 + --> $DIR/typeck.rs:63:9 | LL | !, | ^ a never pattern must be used on an uninhabited type diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 333108e92c0c..31a23fa002c3 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -1,3 +1,6 @@ +// revisions: pass fail +//[pass] check-pass +//[fail] check-fail #![feature(never_patterns)] #![feature(exhaustive_patterns)] #![allow(incomplete_features)] @@ -15,51 +18,55 @@ fn safe_unwrap_result(res: Result) { } // Check we only accept `!` where we want to. -fn never_pattern_typeck(void: Void) { +#[cfg(fail)] +fn never_pattern_typeck_fail(void: Void) { // Don't accept on a non-empty type. match () { !, - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } match (0, false) { !, - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } match (0, false) { (_, !), - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } match Some(0) { None => {} Some(!), - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } // Don't accept on an arbitrary type, even if there are no more branches. match () { () => {} !, - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } // Don't accept even on an empty branch. match None:: { None => {} !, - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } match (&[] as &[Void]) { [] => {} !, - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } // Let alone if the emptiness is behind a reference. match None::<&Void> { None => {} !, - //~^ ERROR: mismatched types + //[fail]~^ ERROR: mismatched types } +} +#[cfg(pass)] +fn never_pattern_typeck_pass(void: Void) { // Participate in match ergonomics. match &void { !, From b28a95391b85e17b1d2f7edc1115291d8a86bcd2 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Jan 2024 22:47:20 +0100 Subject: [PATCH 253/297] update internal ASCII art comment for vec specializations --- library/alloc/src/vec/spec_from_iter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index e976552cf2b9..33dd4139bc08 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -13,13 +13,13 @@ use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; /// +-+-----------+ /// | /// v -/// +-+-------------------------------+ +---------------------+ -/// |SpecFromIter +---->+SpecFromIterNested | -/// |where I: | | |where I: | -/// | Iterator (default)----------+ | | Iterator (default) | -/// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | +---------------------+ -/// +---------------------------------+ +/// +-+---------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)------------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | InPlaceCollect--(fallback to)-+ | +---------------------+ +/// +-----------------------------------+ /// ``` pub(super) trait SpecFromIter { fn from_iter(iter: I) -> Self; From 85d17879623116be76a68c2170c4cb6ff58f4ceb Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Jan 2024 22:50:14 +0100 Subject: [PATCH 254/297] remove alignment-changing in-place collect Currently stable users can't benefit from this because GlobaAlloc doesn't support alignment-changing realloc and neither do most posix allocators. So in practice it always results in an extra memcpy. --- library/alloc/src/vec/in_place_collect.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index ec5f32539f2c..5a783e667521 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -168,7 +168,9 @@ const fn in_place_collectible( step_merge: Option, step_expand: Option, ) -> bool { - if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() < mem::align_of::() } { + // Require matching alignments because an alignment-changing realloc is inefficient on many + // system allocators and better implementations would require the unstable Allocator trait. + if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() != mem::align_of::() } { return false; } @@ -188,7 +190,8 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - return src_cap > 0; + // FIXME: use unreachable! once that works in const + panic!("in_place_collectible() prevents this"); } // If src type size is an integer multiple of the destination type size then @@ -276,8 +279,8 @@ where let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap }; src.forget_allocation_drop_remaining(); - // Adjust the allocation if the alignment didn't match or the source had a capacity in bytes - // that wasn't a multiple of the destination type size. + // Adjust the allocation if the source had a capacity in bytes that wasn't a multiple + // of the destination type size. // Since the discrepancy should generally be small this should only result in some // bookkeeping updates and no memmove. if needs_realloc::(src_cap, dst_cap) { @@ -290,7 +293,7 @@ where let src_size = mem::size_of::().unchecked_mul(src_cap); let old_layout = Layout::from_size_align_unchecked(src_size, src_align); - // The must be equal or smaller for in-place iteration to be possible + // The allocation must be equal or smaller for in-place iteration to be possible // therefore the new layout must be ≤ the old one and therefore valid. let dst_align = mem::align_of::(); let dst_size = mem::size_of::().unchecked_mul(dst_cap); From be9668d3989b721bfaa2ec517b307965476431fa Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 31 Dec 2023 01:53:51 +0000 Subject: [PATCH 255/297] Use an interpreter in jump threading. --- .../rustc_mir_transform/src/jump_threading.rs | 102 +++++++++++++----- ...g.aggregate.JumpThreading.panic-abort.diff | 52 +++++++++ ....aggregate.JumpThreading.panic-unwind.diff | 52 +++++++++ tests/mir-opt/jump_threading.rs | 18 ++++ 4 files changed, 197 insertions(+), 27 deletions(-) create mode 100644 tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff create mode 100644 tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index dcab124505e2..fc77076e4e7a 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -36,16 +36,21 @@ //! cost by `MAX_COST`. use rustc_arena::DroplessArena; +use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; use rustc_data_structures::fx::FxHashSet; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem}; +use rustc_span::DUMMY_SP; use rustc_target::abi::{TagEncoding, Variants}; use crate::cost_checker::CostChecker; +use crate::dataflow_const_prop::DummyMachine; pub struct JumpThreading; @@ -71,6 +76,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { let mut finder = TOFinder { tcx, param_env, + ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), body, arena: &arena, map: &map, @@ -88,7 +94,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { debug!(?discr, ?bb); let discr_ty = discr.ty(body, tcx).ty; - let Ok(discr_layout) = tcx.layout_of(param_env.and(discr_ty)) else { continue }; + let Ok(discr_layout) = finder.ecx.layout_of(discr_ty) else { continue }; let Some(discr) = finder.map.find(discr.as_ref()) else { continue }; debug!(?discr); @@ -142,6 +148,7 @@ struct ThreadingOpportunity { struct TOFinder<'tcx, 'a> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + ecx: InterpCx<'tcx, 'tcx, DummyMachine>, body: &'a Body<'tcx>, map: &'a Map, loop_headers: &'a BitSet, @@ -329,11 +336,11 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } #[instrument(level = "trace", skip(self))] - fn process_operand( + fn process_immediate( &mut self, bb: BasicBlock, lhs: PlaceIndex, - rhs: &Operand<'tcx>, + rhs: ImmTy<'tcx>, state: &mut State>, ) -> Option { let register_opportunity = |c: Condition| { @@ -341,13 +348,60 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) }; + let conditions = state.try_get_idx(lhs, self.map)?; + if let Immediate::Scalar(Scalar::Int(int)) = *rhs { + conditions.iter_matches(int).for_each(register_opportunity); + } + + None + } + + #[instrument(level = "trace", skip(self))] + fn process_operand( + &mut self, + bb: BasicBlock, + lhs: PlaceIndex, + rhs: &Operand<'tcx>, + state: &mut State>, + ) -> Option { match rhs { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let constant = - constant.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?; - conditions.iter_matches(constant).for_each(register_opportunity); + let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?; + self.map.for_each_projection_value( + lhs, + constant, + &mut |elem, op| match elem { + TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), + TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), + TrackElem::Discriminant => { + let variant = self.ecx.read_discriminant(op).ok()?; + let discr_value = + self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?; + Some(discr_value.into()) + } + TrackElem::DerefLen => { + let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into(); + let len_usize = op.len(&self.ecx).ok()?; + let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); + Some(ImmTy::from_uint(len_usize, layout).into()) + } + }, + &mut |place, op| { + if let Some(conditions) = state.try_get_idx(place, self.map) + && let Ok(imm) = self.ecx.read_immediate_raw(op) + && let Some(imm) = imm.right() + && let Immediate::Scalar(Scalar::Int(int)) = *imm + { + conditions.iter_matches(int).for_each(|c: Condition| { + self.opportunities.push(ThreadingOpportunity { + chain: vec![bb], + target: c.target, + }) + }) + } + }, + ); } // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { @@ -374,18 +428,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // Below, `lhs` is the return value of `mutated_statement`, // the place to which `conditions` apply. - let discriminant_for_variant = |enum_ty: Ty<'tcx>, variant_index| { - let discr = enum_ty.discriminant_for_variant(self.tcx, variant_index)?; - let discr_layout = self.tcx.layout_of(self.param_env.and(discr.ty)).ok()?; - let scalar = ScalarInt::try_from_uint(discr.val, discr_layout.size)?; - Some(Operand::const_from_scalar( - self.tcx, - discr.ty, - scalar.into(), - rustc_span::DUMMY_SP, - )) - }; - match &stmt.kind { // If we expect `discriminant(place) ?= A`, // we have an opportunity if `variant_index ?= A`. @@ -395,7 +437,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant // of a niche encoding. If we cannot ensure that we write to the discriminant, do // nothing. - let enum_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?; + let enum_layout = self.ecx.layout_of(enum_ty).ok()?; let writes_discriminant = match enum_layout.variants { Variants::Single { index } => { assert_eq!(index, *variant_index); @@ -408,8 +450,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } => *variant_index != untagged_variant, }; if writes_discriminant { - let discr = discriminant_for_variant(enum_ty, *variant_index)?; - self.process_operand(bb, discr_target, &discr, state)?; + let discr = self.ecx.discriminant_for_variant(enum_ty, *variant_index).ok()?; + self.process_immediate(bb, discr_target, discr, state)?; } } // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`. @@ -440,10 +482,16 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) - && let Some(discr_value) = - discriminant_for_variant(agg_ty, *variant_index) + && let Ok(discr_value) = self + .ecx + .discriminant_for_variant(agg_ty, *variant_index) { - self.process_operand(bb, discr_target, &discr_value, state); + self.process_immediate( + bb, + discr_target, + discr_value, + state, + ); } self.map.apply(lhs, TrackElem::Variant(*variant_index))? } @@ -577,7 +625,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { let discr = discr.place()?; let discr_ty = discr.ty(self.body, self.tcx).ty; - let discr_layout = self.tcx.layout_of(self.param_env.and(discr_ty)).ok()?; + let discr_layout = self.ecx.layout_of(discr_ty).ok()?; let conditions = state.try_get(discr.as_ref(), self.map)?; if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) { diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff new file mode 100644 index 000000000000..66aa892c6f33 --- /dev/null +++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff @@ -0,0 +1,52 @@ +- // MIR for `aggregate` before JumpThreading ++ // MIR for `aggregate` after JumpThreading + + fn aggregate(_1: u8) -> u8 { + debug x => _1; + let mut _0: u8; + let _2: u8; + let _3: u8; + let mut _4: (u8, u8); + let mut _5: bool; + let mut _6: u8; + scope 1 { + debug a => _2; + debug b => _3; + } + + bb0: { + StorageLive(_4); + _4 = const _; + StorageLive(_2); + _2 = (_4.0: u8); + StorageLive(_3); + _3 = (_4.1: u8); + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); + _6 = _2; + _5 = Eq(move _6, const 7_u8); +- switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; + } + + bb1: { + StorageDead(_6); + _0 = _3; + goto -> bb3; + } + + bb2: { + StorageDead(_6); + _0 = _2; + goto -> bb3; + } + + bb3: { + StorageDead(_5); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff new file mode 100644 index 000000000000..66aa892c6f33 --- /dev/null +++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff @@ -0,0 +1,52 @@ +- // MIR for `aggregate` before JumpThreading ++ // MIR for `aggregate` after JumpThreading + + fn aggregate(_1: u8) -> u8 { + debug x => _1; + let mut _0: u8; + let _2: u8; + let _3: u8; + let mut _4: (u8, u8); + let mut _5: bool; + let mut _6: u8; + scope 1 { + debug a => _2; + debug b => _3; + } + + bb0: { + StorageLive(_4); + _4 = const _; + StorageLive(_2); + _2 = (_4.0: u8); + StorageLive(_3); + _3 = (_4.1: u8); + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); + _6 = _2; + _5 = Eq(move _6, const 7_u8); +- switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; + } + + bb1: { + StorageDead(_6); + _0 = _3; + goto -> bb3; + } + + bb2: { + StorageDead(_6); + _0 = _2; + goto -> bb3; + } + + bb3: { + StorageDead(_5); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 0cbdaa085bc9..7c2fa42828be 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -453,7 +453,23 @@ fn disappearing_bb(x: u8) -> u8 { ) } +/// Verify that we can thread jumps when we assign from an aggregate constant. +fn aggregate(x: u8) -> u8 { + // CHECK-LABEL: fn aggregate( + // CHECK-NOT: switchInt( + + const FOO: (u8, u8) = (5, 13); + + let (a, b) = FOO; + if a == 7 { + b + } else { + a + } +} + fn main() { + // CHECK-LABEL: fn main( too_complex(Ok(0)); identity(Ok(0)); custom_discr(false); @@ -464,6 +480,7 @@ fn main() { mutable_ref(); renumbered_bb(true); disappearing_bb(7); + aggregate(7); } // EMIT_MIR jump_threading.too_complex.JumpThreading.diff @@ -476,3 +493,4 @@ fn main() { // EMIT_MIR jump_threading.mutable_ref.JumpThreading.diff // EMIT_MIR jump_threading.renumbered_bb.JumpThreading.diff // EMIT_MIR jump_threading.disappearing_bb.JumpThreading.diff +// EMIT_MIR jump_threading.aggregate.JumpThreading.diff From b22742e8f3ddc9370d149ff89be47603b0f80ff8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 31 Dec 2023 02:00:30 +0000 Subject: [PATCH 256/297] Extract process_constant. --- .../rustc_mir_transform/src/jump_threading.rs | 78 +++++++++++-------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index fc77076e4e7a..c491cb22cbe7 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -356,6 +356,49 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { None } + /// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. + #[instrument(level = "trace", skip(self))] + fn process_constant( + &mut self, + bb: BasicBlock, + lhs: PlaceIndex, + constant: OpTy<'tcx>, + state: &mut State>, + ) { + self.map.for_each_projection_value( + lhs, + constant, + &mut |elem, op| match elem { + TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), + TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), + TrackElem::Discriminant => { + let variant = self.ecx.read_discriminant(op).ok()?; + let discr_value = + self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?; + Some(discr_value.into()) + } + TrackElem::DerefLen => { + let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into(); + let len_usize = op.len(&self.ecx).ok()?; + let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); + Some(ImmTy::from_uint(len_usize, layout).into()) + } + }, + &mut |place, op| { + if let Some(conditions) = state.try_get_idx(place, self.map) + && let Ok(imm) = self.ecx.read_immediate_raw(op) + && let Some(imm) = imm.right() + && let Immediate::Scalar(Scalar::Int(int)) = *imm + { + conditions.iter_matches(int).for_each(|c: Condition| { + self.opportunities + .push(ThreadingOpportunity { chain: vec![bb], target: c.target }) + }) + } + }, + ); + } + #[instrument(level = "trace", skip(self))] fn process_operand( &mut self, @@ -368,40 +411,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?; - self.map.for_each_projection_value( - lhs, - constant, - &mut |elem, op| match elem { - TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), - TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), - TrackElem::Discriminant => { - let variant = self.ecx.read_discriminant(op).ok()?; - let discr_value = - self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?; - Some(discr_value.into()) - } - TrackElem::DerefLen => { - let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into(); - let len_usize = op.len(&self.ecx).ok()?; - let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); - Some(ImmTy::from_uint(len_usize, layout).into()) - } - }, - &mut |place, op| { - if let Some(conditions) = state.try_get_idx(place, self.map) - && let Ok(imm) = self.ecx.read_immediate_raw(op) - && let Some(imm) = imm.right() - && let Immediate::Scalar(Scalar::Int(int)) = *imm - { - conditions.iter_matches(int).for_each(|c: Condition| { - self.opportunities.push(ThreadingOpportunity { - chain: vec![bb], - target: c.target, - }) - }) - } - }, - ); + self.process_constant(bb, lhs, constant, state); } // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { From e72b2b18c01919e9146e2bfb7b6ea0f0ea72997c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 31 Dec 2023 02:04:09 +0000 Subject: [PATCH 257/297] Extract process_assign. --- .../rustc_mir_transform/src/jump_threading.rs | 168 ++++++++---------- 1 file changed, 79 insertions(+), 89 deletions(-) diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index c491cb22cbe7..e87f68a09057 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -423,6 +423,84 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { None } + #[instrument(level = "trace", skip(self))] + fn process_assign( + &mut self, + bb: BasicBlock, + lhs_place: &Place<'tcx>, + rhs: &Rvalue<'tcx>, + state: &mut State>, + ) -> Option { + let lhs = self.map.find(lhs_place.as_ref())?; + match rhs { + Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?, + // Transfer the conditions on the copy rhs. + Rvalue::CopyForDeref(rhs) => { + self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)? + } + Rvalue::Discriminant(rhs) => { + let rhs = self.map.find_discr(rhs.as_ref())?; + state.insert_place_idx(rhs, lhs, self.map); + } + // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. + Rvalue::Aggregate(box ref kind, ref operands) => { + let agg_ty = lhs_place.ty(self.body, self.tcx).ty; + let lhs = match kind { + // Do not support unions. + AggregateKind::Adt(.., Some(_)) => return None, + AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { + if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) + && let Ok(discr_value) = + self.ecx.discriminant_for_variant(agg_ty, *variant_index) + { + self.process_immediate(bb, discr_target, discr_value, state); + } + self.map.apply(lhs, TrackElem::Variant(*variant_index))? + } + _ => lhs, + }; + for (field_index, operand) in operands.iter_enumerated() { + if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) { + self.process_operand(bb, field, operand, state); + } + } + } + // Transfer the conditions on the copy rhs, after inversing polarity. + Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { + let conditions = state.try_get_idx(lhs, self.map)?; + let place = self.map.find(place.as_ref())?; + let conds = conditions.map(self.arena, Condition::inv); + state.insert_value_idx(place, conds, self.map); + } + // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. + // Create a condition on `rhs ?= B`. + Rvalue::BinaryOp( + op, + box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value)) + | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)), + ) => { + let conditions = state.try_get_idx(lhs, self.map)?; + let place = self.map.find(place.as_ref())?; + let equals = match op { + BinOp::Eq => ScalarInt::TRUE, + BinOp::Ne => ScalarInt::FALSE, + _ => return None, + }; + let value = value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?; + let conds = conditions.map(self.arena, |c| Condition { + value, + polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, + ..c + }); + state.insert_value_idx(place, conds, self.map); + } + + _ => {} + } + + None + } + #[instrument(level = "trace", skip(self))] fn process_statement( &mut self, @@ -472,95 +550,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity); } StatementKind::Assign(box (lhs_place, rhs)) => { - if let Some(lhs) = self.map.find(lhs_place.as_ref()) { - match rhs { - Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?, - // Transfer the conditions on the copy rhs. - Rvalue::CopyForDeref(rhs) => { - self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)? - } - Rvalue::Discriminant(rhs) => { - let rhs = self.map.find_discr(rhs.as_ref())?; - state.insert_place_idx(rhs, lhs, self.map); - } - // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. - Rvalue::Aggregate(box ref kind, ref operands) => { - let agg_ty = lhs_place.ty(self.body, self.tcx).ty; - let lhs = match kind { - // Do not support unions. - AggregateKind::Adt(.., Some(_)) => return None, - AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { - if let Some(discr_target) = - self.map.apply(lhs, TrackElem::Discriminant) - && let Ok(discr_value) = self - .ecx - .discriminant_for_variant(agg_ty, *variant_index) - { - self.process_immediate( - bb, - discr_target, - discr_value, - state, - ); - } - self.map.apply(lhs, TrackElem::Variant(*variant_index))? - } - _ => lhs, - }; - for (field_index, operand) in operands.iter_enumerated() { - if let Some(field) = - self.map.apply(lhs, TrackElem::Field(field_index)) - { - self.process_operand(bb, field, operand, state); - } - } - } - // Transfer the conditions on the copy rhs, after inversing polarity. - Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let place = self.map.find(place.as_ref())?; - let conds = conditions.map(self.arena, Condition::inv); - state.insert_value_idx(place, conds, self.map); - } - // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. - // Create a condition on `rhs ?= B`. - Rvalue::BinaryOp( - op, - box ( - Operand::Move(place) | Operand::Copy(place), - Operand::Constant(value), - ) - | box ( - Operand::Constant(value), - Operand::Move(place) | Operand::Copy(place), - ), - ) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let place = self.map.find(place.as_ref())?; - let equals = match op { - BinOp::Eq => ScalarInt::TRUE, - BinOp::Ne => ScalarInt::FALSE, - _ => return None, - }; - let value = value - .const_ - .normalize(self.tcx, self.param_env) - .try_to_scalar_int()?; - let conds = conditions.map(self.arena, |c| Condition { - value, - polarity: if c.matches(equals) { - Polarity::Eq - } else { - Polarity::Ne - }, - ..c - }); - state.insert_value_idx(place, conds, self.map); - } - - _ => {} - } - } + self.process_assign(bb, lhs_place, rhs, state)?; } _ => {} } From 35a9fc3472b232b924b843c468399ca44320a55d Mon Sep 17 00:00:00 2001 From: invpt <57822954+invpt@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:40:56 -0500 Subject: [PATCH 258/297] Clarify docs for Vec::into_boxed_slice, Vec::shrink_to_fit --- library/alloc/src/vec/mod.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8aa0c6e7ed62..35ea97bfe609 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -358,7 +358,7 @@ mod spec_extend; /// /// `vec![x; n]`, `vec![a, b, c, d]`, and /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` -/// with exactly the requested capacity. If [len] == [capacity], +/// with at least the requested capacity. If [len] == [capacity], /// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to /// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. /// @@ -1023,8 +1023,11 @@ impl Vec { /// Shrinks the capacity of the vector as much as possible. /// - /// It will drop down as close as possible to the length but the allocator - /// may still inform the vector that there is space for a few more elements. + /// The behavior of this method depends on the allocator, which may either shrink the vector + /// in-place or reallocate. The resulting vector might still have some excess capacity, just as + /// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details. + /// + /// [`with_capacity`]: Vec::with_capacity /// /// # Examples /// @@ -1074,10 +1077,10 @@ impl Vec { /// Converts the vector into [`Box<[T]>`][owned slice]. /// - /// If the vector has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. /// /// [owned slice]: Box + /// [`shrink_to_fit`]: Vec::shrink_to_fit /// /// # Examples /// @@ -3290,8 +3293,10 @@ impl From> for Vec { impl From> for Box<[T], A> { /// Convert a vector into a boxed slice. /// - /// If `v` has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. + /// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`]. + /// + /// [owned slice]: Box + /// [`Vec::shrink_to_fit`]: Vec::shrink_to_fit /// /// # Examples /// From 1a343424f3ba3ce230b2b9ceeff9cc7449f354d3 Mon Sep 17 00:00:00 2001 From: kapilsinha Date: Thu, 18 Jan 2024 17:49:06 -0800 Subject: [PATCH 259/297] Fix typo in documentation in base.rs --- compiler/rustc_expand/src/base.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0a1c44303970..054ab2d126a4 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -664,8 +664,8 @@ pub enum SyntaxExtensionKind { /// A token-based attribute macro. Attr( /// An expander with signature (TokenStream, TokenStream) -> TokenStream. - /// The first TokenSteam is the attribute itself, the second is the annotated item. - /// The produced TokenSteam replaces the input TokenSteam. + /// The first TokenStream is the attribute itself, the second is the annotated item. + /// The produced TokenStream replaces the input TokenStream. Box, ), @@ -685,7 +685,7 @@ pub enum SyntaxExtensionKind { /// A token-based derive macro. Derive( /// An expander with signature TokenStream -> TokenStream. - /// The produced TokenSteam is appended to the input TokenSteam. + /// The produced TokenStream is appended to the input TokenStream. /// /// FIXME: The text above describes how this should work. Currently it /// is handled identically to `LegacyDerive`. It should be migrated to From 841e9f51876954a83430af4221606bed6b3e126c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:29:42 +0100 Subject: [PATCH 260/297] Don't add needs-triage to A-diagnostics A-diagnostics is already labeled correctly thanks to the template and there usually isn't much to do on those issues, so it's fine to just add them to the pile. --- triagebot.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index bd14640e280e..0e60153ce2e6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -364,7 +364,8 @@ new_pr = true [autolabel."needs-triage"] new_issue = true exclude_labels = [ - "C-tracking-issue" + "C-tracking-issue", + "A-diagnostics", ] [autolabel."WG-trait-system-refactor"] From f9faf161817eef2b885bd47908ceaeef675ea72f Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Thu, 11 Jan 2024 21:02:43 -0800 Subject: [PATCH 261/297] Suggest .swap() instead of mem::swap() in more cases --- .../src/diagnostics/conflict_errors.rs | 99 +++++++++++++++++-- tests/ui/suggestions/suggest-slice-swap.fixed | 9 ++ tests/ui/suggestions/suggest-slice-swap.rs | 9 ++ .../ui/suggestions/suggest-slice-swap.stderr | 17 ++++ 4 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 tests/ui/suggestions/suggest-slice-swap.fixed create mode 100644 tests/ui/suggestions/suggest-slice-swap.rs create mode 100644 tests/ui/suggestions/suggest-slice-swap.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5baa108ed3cc..a230ba0e439f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + use either::Either; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; @@ -24,6 +26,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::FindExprBySpan; use rustc_trait_selection::traits::ObligationCtxt; use std::iter; @@ -1295,14 +1298,96 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place: Place<'tcx>, borrowed_place: Place<'tcx>, ) { - if let ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) = - (&place.projection[..], &borrowed_place.projection[..]) + let tcx = self.infcx.tcx; + let hir = tcx.hir(); + + if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)]) + | ( + [ProjectionElem::Deref, ProjectionElem::Index(index1)], + [ProjectionElem::Deref, ProjectionElem::Index(index2)], + ) = (&place.projection[..], &borrowed_place.projection[..]) { - err.help( - "consider using `.split_at_mut(position)` or similar method to obtain \ - two mutable non-overlapping sub-slices", - ) - .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices"); + let mut note_default_suggestion = || { + err.help( + "consider using `.split_at_mut(position)` or similar method to obtain \ + two mutable non-overlapping sub-slices", + ) + .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices"); + }; + + let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { + note_default_suggestion(); + return; + }; + + let mut expr_finder = + FindExprBySpan::new(self.body.local_decls[*index1].source_info.span); + expr_finder.visit_expr(hir.body(body_id).value); + let Some(index1) = expr_finder.result else { + note_default_suggestion(); + return; + }; + + expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span); + expr_finder.visit_expr(hir.body(body_id).value); + let Some(index2) = expr_finder.result else { + note_default_suggestion(); + return; + }; + + let sm = tcx.sess.source_map(); + + let Ok(index1_str) = sm.span_to_snippet(index1.span) else { + note_default_suggestion(); + return; + }; + + let Ok(index2_str) = sm.span_to_snippet(index2.span) else { + note_default_suggestion(); + return; + }; + + let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| { + if let hir::Node::Expr(expr) = tcx.hir_node(id) + && let hir::ExprKind::Index(obj, ..) = expr.kind + { + Some(obj) + } else { + None + } + }) else { + note_default_suggestion(); + return; + }; + + let Ok(obj_str) = sm.span_to_snippet(object.span) else { + note_default_suggestion(); + return; + }; + + let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| { + if let hir::Node::Expr(call) = tcx.hir_node(id) + && let hir::ExprKind::Call(callee, ..) = call.kind + && let hir::ExprKind::Path(qpath) = callee.kind + && let hir::QPath::Resolved(None, res) = qpath + && let hir::def::Res::Def(_, did) = res.res + && tcx.is_diagnostic_item(sym::mem_swap, did) + { + Some(call) + } else { + None + } + }) else { + note_default_suggestion(); + return; + }; + + err.span_suggestion( + swap_call.span, + "use `.swap()` to swap elements at the specified indices instead", + format!("{obj_str}.swap({index1_str}, {index2_str})"), + Applicability::MachineApplicable, + ); } } diff --git a/tests/ui/suggestions/suggest-slice-swap.fixed b/tests/ui/suggestions/suggest-slice-swap.fixed new file mode 100644 index 000000000000..05b7ec263798 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(dead_code)] + +fn swap(arr: &mut [u32; 2]) { + arr.swap(1, 0); + //~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-slice-swap.rs b/tests/ui/suggestions/suggest-slice-swap.rs new file mode 100644 index 000000000000..9f3659aac163 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.rs @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(dead_code)] + +fn swap(arr: &mut [u32; 2]) { + std::mem::swap(&mut arr[0], &mut arr[1]); + //~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-slice-swap.stderr b/tests/ui/suggestions/suggest-slice-swap.stderr new file mode 100644 index 000000000000..2840fc0a7611 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `arr[_]` as mutable more than once at a time + --> $DIR/suggest-slice-swap.rs:5:33 + | +LL | std::mem::swap(&mut arr[0], &mut arr[1]); + | -------------- ----------- ^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + | +help: use `.swap()` to swap elements at the specified indices instead + | +LL | arr.swap(1, 0); + | ~~~~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. From dbff90c2a7c751cf9d6843cd585429beb100c17d Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 12 Oct 2023 17:36:01 +0000 Subject: [PATCH 262/297] LLVM 18 x86 data layout update With https://reviews.llvm.org/D86310 LLVM now has i128 aligned to 16-bytes on x86 based platforms. This will be in LLVM-18. This patch updates all our spec targets to be 16-byte aligned, and removes the alignment when speaking to older LLVM. This results in Rust overaligning things relative to LLVM on older LLVMs. This alignment change was discussed in rust-lang/compiler-team#683 See #54341 for additional information about why this is happening and where this will be useful in the future. This *does not* stabilize `i128`/`u128` for FFI. --- compiler/rustc_ast/src/ast.rs | 8 ++++++-- compiler/rustc_codegen_llvm/src/context.rs | 8 ++++++++ compiler/rustc_middle/src/mir/mod.rs | 12 +++++++++--- .../rustc_target/src/spec/targets/i386_apple_ios.rs | 2 +- .../src/spec/targets/i686_apple_darwin.rs | 2 +- .../src/spec/targets/i686_linux_android.rs | 2 +- .../src/spec/targets/i686_pc_windows_gnu.rs | 2 +- .../src/spec/targets/i686_pc_windows_gnullvm.rs | 2 +- .../src/spec/targets/i686_pc_windows_msvc.rs | 2 +- .../src/spec/targets/i686_unknown_freebsd.rs | 2 +- .../src/spec/targets/i686_unknown_haiku.rs | 2 +- .../src/spec/targets/i686_unknown_hurd_gnu.rs | 2 +- .../src/spec/targets/i686_unknown_linux_gnu.rs | 2 +- .../src/spec/targets/i686_unknown_linux_musl.rs | 2 +- .../src/spec/targets/i686_unknown_netbsd.rs | 2 +- .../src/spec/targets/i686_unknown_openbsd.rs | 2 +- .../src/spec/targets/i686_uwp_windows_gnu.rs | 2 +- .../src/spec/targets/i686_uwp_windows_msvc.rs | 2 +- .../src/spec/targets/i686_wrs_vxworks.rs | 2 +- .../src/spec/targets/x86_64_apple_darwin.rs | 4 ++-- .../src/spec/targets/x86_64_apple_ios.rs | 4 ++-- .../src/spec/targets/x86_64_apple_ios_macabi.rs | 4 ++-- .../src/spec/targets/x86_64_apple_tvos.rs | 4 ++-- .../src/spec/targets/x86_64_apple_watchos_sim.rs | 4 ++-- .../src/spec/targets/x86_64_fortanix_unknown_sgx.rs | 4 ++-- .../src/spec/targets/x86_64_linux_android.rs | 4 ++-- .../src/spec/targets/x86_64_pc_nto_qnx710.rs | 4 ++-- .../src/spec/targets/x86_64_pc_solaris.rs | 4 ++-- .../src/spec/targets/x86_64_pc_windows_gnu.rs | 4 ++-- .../src/spec/targets/x86_64_pc_windows_gnullvm.rs | 4 ++-- .../src/spec/targets/x86_64_pc_windows_msvc.rs | 4 ++-- .../src/spec/targets/x86_64_unikraft_linux_musl.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_dragonfly.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_freebsd.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_fuchsia.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_haiku.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_hermit.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_illumos.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_l4re_uclibc.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_linux_gnu.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_linux_musl.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_linux_ohos.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_netbsd.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_none.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_openbsd.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_redox.rs | 4 ++-- .../src/spec/targets/x86_64_unknown_uefi.rs | 4 ++-- .../src/spec/targets/x86_64_uwp_windows_gnu.rs | 4 ++-- .../src/spec/targets/x86_64_uwp_windows_msvc.rs | 4 ++-- .../src/spec/targets/x86_64_wrs_vxworks.rs | 4 ++-- .../src/spec/targets/x86_64h_apple_darwin.rs | 4 ++-- 51 files changed, 103 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index d0d98eb3d62d..7f5213431f7d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3304,9 +3304,13 @@ mod size_asserts { static_assert_size!(Impl, 136); static_assert_size!(Item, 136); static_assert_size!(ItemKind, 64); - static_assert_size!(LitKind, 24); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(LitKind, 32); static_assert_size!(Local, 72); - static_assert_size!(MetaItemLit, 40); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(MetaItemLit, 48); static_assert_size!(Param, 40); static_assert_size!(Pat, 72); static_assert_size!(Path, 24); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1d1b6e6148dd..f3b2caf9b803 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -145,6 +145,14 @@ pub unsafe fn create_module<'ll>( .replace("-Fi64", ""); } } + if llvm_version < (18, 0, 0) { + if sess.target.arch == "x86" || sess.target.arch == "x86_64" { + // LLVM 18 adjusts i128 to be 128-bit aligned on x86 variants. + // Earlier LLVMs leave this as default alignment, so remove it. + // See https://reviews.llvm.org/D86310 + target_data_layout = target_data_layout.replace("-i128:128", ""); + } + } // Ensure the data-layout values hardcoded remain the defaults. if sess.target.is_builtin { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 36f5ba161d5f..624ae8c22f9d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1672,13 +1672,19 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(BasicBlockData<'_>, 136); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 40); static_assert_size!(SourceScopeData<'_>, 72); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); - static_assert_size!(Terminator<'_>, 104); - static_assert_size!(TerminatorKind<'_>, 88); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(Terminator<'_>, 112); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(TerminatorKind<'_>, 96); static_assert_size!(VarDebugInfo<'_>, 88); // tidy-alphabetical-end } diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 13f8b6b5a0a0..a221538b9022 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:128-n8:16:32-S128" + i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch) }, diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index 59069fe4e3a9..25617b4436cb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { llvm_target: macos_llvm_target(Arch::I686).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:128-n8:16:32-S128" + i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs index 79471040f0da..12ebf0c72f83 100644 --- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { llvm_target: "i686-linux-android".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs index 8d4a39b58114..118180344143 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs @@ -19,7 +19,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs index bb410cd8caf2..f4e33b881788 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index 5abc3017bf80..9f1c8f4676cb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -25,7 +25,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-msvc".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs index 927b2ab877dd..d90f481c68cf 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-freebsd".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs index bc7fd6fbc68c..330a390c9817 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-haiku".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs index 6884e078c27e..c32f7177c1a0 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-hurd-gnu".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs index 3b7be48dbbc5..9bc38a72f4d3 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs @@ -12,7 +12,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-linux-gnu".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs index ef58b4fb4588..4a82e0986c72 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs @@ -25,7 +25,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-linux-musl".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs index 5f3afbe5afdc..ea72656607e4 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-netbsdelf".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { mcount: "__mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs index f44584a10be5..945dc0f89670 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-openbsd".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs index ec211a710eb0..0830033dc23d 100644 --- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs index 7cca2fc6b9f7..534dd6ee54fb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs @@ -9,7 +9,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-msvc".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs index ee501c5165e0..30c2295e4021 100644 --- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-linux-gnu".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 59df3937ea6f..356c67218681 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -17,8 +17,8 @@ pub fn target() -> Target { // correctly, we do too. llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index d0e2ac44a2a2..55165ea4ec68 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -9,8 +9,8 @@ pub fn target() -> Target { Target { llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index 8ef4b88b8b1c..ff21e4893332 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: llvm_target.into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 17efd437f2fc..20b016125531 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -6,8 +6,8 @@ pub fn target() -> Target { Target { llvm_target: tvos_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch) }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index b1f72ee2f212..806a58e980be 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs @@ -6,8 +6,8 @@ pub fn target() -> Target { Target { llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..opts("watchos", arch) }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index f4117edc3ff5..c38a1a08536b 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs @@ -75,8 +75,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-elf".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: opts, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs index 0e6d41abc9b4..30b1ee73630e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs @@ -16,8 +16,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-linux-android".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 93aec4c425a2..0ef015973998 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -4,8 +4,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-unknown".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: TargetOptions { cpu: "x86-64".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index f15ad8dda63b..ade4dd6d4319 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs @@ -13,8 +13,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-solaris".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs index 6d3e07270517..9e964d248bf8 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs @@ -16,8 +16,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-gnu".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs index a56ebfa585e2..1facf9450cd2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-gnu".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index 3a4da91c2443..357261073a8f 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs index e6159fca3aea..6c9d11475487 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs @@ -5,8 +5,8 @@ pub fn target() -> Target { llvm_target: "x86_64-unknown-linux-musl".into(), pointer_width: 64, arch: "x86_64".into(), - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), options: TargetOptions { cpu: "x86-64".into(), plt_by_default: false, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs index 80adb8fa2d95..ce682bb80056 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-dragonfly".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs index fa3210353670..6d6940e7891c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs @@ -14,8 +14,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-freebsd".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index 5b19ed1b5ff1..50139e5c1d83 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-fuchsia".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs index 0f927be962bf..c00c689f7ef7 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs @@ -13,8 +13,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-haiku".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs index df191f515bd6..fb46848ba8c0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs @@ -5,8 +5,8 @@ pub fn target() -> Target { llvm_target: "x86_64-unknown-hermit".into(), pointer_width: 64, arch: "x86_64".into(), - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), options: TargetOptions { cpu: "x86-64".into(), features: "+rdrnd,+rdseed".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs index eb2b13cb5c26..3e3f4921322c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs @@ -13,8 +13,8 @@ pub fn target() -> Target { // so we still pass Solaris to it llvm_target: "x86_64-pc-solaris".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index 7b86fe738b1e..646623668c6c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-l4re-uclibc".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index bf10f7e5d2de..2296b58f45dc 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -19,8 +19,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs index 8dc5503e336a..c71dc65670c2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs @@ -18,8 +18,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs index 35862656aa2f..c25105f6e35c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs @@ -18,8 +18,8 @@ pub fn target() -> Target { // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead. llvm_target: "x86_64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs index e2cee0513bab..466498acb0b7 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs @@ -19,8 +19,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-netbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: TargetOptions { mcount: "__mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index 8f7655d8ccd3..ceded7790a64 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -30,8 +30,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-none-elf".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: opts, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs index 1133b50f3d22..b542a569bbd2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-openbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs index c1f573112920..550b7a3d2823 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-redox".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 5abfb8162f70..95847e57a0fb 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -32,8 +32,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-windows".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs index a46d3a0e27bc..c2981ddbad69 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs @@ -15,8 +15,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-gnu".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs index a3bc27aa0650..3f0702c7ad60 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs @@ -9,8 +9,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs index 765239bdd39c..f7a78b48f95d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index 0c731e369ebc..e0e4cb93e31e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -35,8 +35,8 @@ pub fn target() -> Target { // correctly, we do too. llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } From 7a0415ce3728cb29e313429118cd113405273745 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 18 Jan 2024 14:34:17 +0100 Subject: [PATCH 263/297] Add codegen test for ScalarPair with i128 on LLVM 17 --- tests/codegen/i128-x86-align.rs | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 tests/codegen/i128-x86-align.rs diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs new file mode 100644 index 000000000000..ef1313ddb676 --- /dev/null +++ b/tests/codegen/i128-x86-align.rs @@ -0,0 +1,101 @@ +// only-x86_64 +// compile-flags: -O -C no-prepopulate-passes --crate-type=lib + +// On LLVM 17 and earlier LLVM's own data layout specifies that i128 has 8 byte alignment, +// while rustc wants it to have 16 byte alignment. This test checks that we handle this +// correctly. + +// CHECK: %ScalarPair = type { i32, [3 x i32], i128 } +// CHECK: %Struct = type { i32, i32, [2 x i32], i128 } + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ScalarPair { + a: i32, + b: i128, +} + +#[no_mangle] +pub fn load(x: &ScalarPair) -> ScalarPair { + // CHECK-LABEL: @load( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: [[A:%.*]] = load i32, ptr %x, align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 + // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16 + // CHECK-NEXT: [[IV1:%.*]] = insertvalue { i32, i128 } poison, i32 [[A]], 0 + // CHECK-NEXT: [[IV2:%.*]] = insertvalue { i32, i128 } [[IV1]], i128 [[B]], 1 + // CHECK-NEXT: ret { i32, i128 } [[IV2]] + *x +} + +#[no_mangle] +pub fn store(x: &mut ScalarPair) { + // CHECK-LABEL: @store( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: store i32 1, ptr %x, align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 + // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16 + *x = ScalarPair { a: 1, b: 2 }; +} + +#[no_mangle] +pub fn alloca() { + // CHECK-LABEL: @alloca( + // CHECK: [[X:%.*]] = alloca %ScalarPair, align 16 + // CHECK: store i32 1, ptr %x, align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 + // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16 + let mut x = ScalarPair { a: 1, b: 2 }; + store(&mut x); +} + +#[no_mangle] +pub fn load_volatile(x: &ScalarPair) -> ScalarPair { + // CHECK-LABEL: @load_volatile( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: [[TMP:%.*]] = alloca %ScalarPair, align 16 + // CHECK: [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16 + // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr [[TMP]], align 16 + // CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP]], align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 + // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16 + unsafe { std::ptr::read_volatile(x) } +} + +#[no_mangle] +pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit, i128) { + // CHECK-LABEL: define { i128, i128 } @transmute(i32 noundef %x.0, i128 noundef %x.1) + // CHECK: [[TMP:%.*]] = alloca { i128, i128 }, align 16 + // CHECK-NEXT: store i32 %x.0, ptr [[TMP]], align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 + // CHECK-NEXT: store i128 %x.1, ptr [[GEP]], align 16 + // CHECK-NEXT: [[LOAD1:%.*]] = load i128, ptr %_0, align 16 + // CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 + // CHECK-NEXT: [[LOAD2:%.*]] = load i128, ptr [[GEP2]], align 16 + // CHECK-NEXT: [[IV1:%.*]] = insertvalue { i128, i128 } poison, i128 [[LOAD1]], 0 + // CHECK-NEXT: [[IV2:%.*]] = insertvalue { i128, i128 } [[IV1]], i128 [[LOAD2]], 1 + // CHECK-NEXT: ret { i128, i128 } [[IV2]] + unsafe { std::mem::transmute(x) } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Struct { + a: i32, + b: i32, + c: i128, +} + +#[no_mangle] +pub fn store_struct(x: &mut Struct) { + // CHECK-LABEL: @store_struct( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: [[TMP:%.*]] = alloca %Struct, align 16 + // CHECK: store i32 1, ptr [[TMP]], align 16 + // CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds %Struct, ptr [[TMP]], i32 0, i32 1 + // CHECK-NEXT: store i32 2, ptr [[GEP1]], align 4 + // CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds %Struct, ptr [[TMP]], i32 0, i32 3 + // CHECK-NEXT: store i128 3, ptr [[GEP2]], align 16 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %x, ptr align 16 [[TMP]], i64 32, i1 false) + *x = Struct { a: 1, b: 2, c: 3 }; +} From ce2d91dccd48b1adc7224993829394682fd5ce19 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 19 Jan 2024 09:28:42 +0100 Subject: [PATCH 264/297] Directly use volatile_load intrinsic This makes the test work if libstd is compiled with debug assertions. --- tests/codegen/i128-x86-align.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs index ef1313ddb676..aaf5785dc9ff 100644 --- a/tests/codegen/i128-x86-align.rs +++ b/tests/codegen/i128-x86-align.rs @@ -8,6 +8,8 @@ // CHECK: %ScalarPair = type { i32, [3 x i32], i128 } // CHECK: %Struct = type { i32, i32, [2 x i32], i128 } +#![feature(core_intrinsics)] + #[repr(C)] #[derive(Clone, Copy)] pub struct ScalarPair { @@ -59,7 +61,7 @@ pub fn load_volatile(x: &ScalarPair) -> ScalarPair { // CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP]], align 16 // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16 - unsafe { std::ptr::read_volatile(x) } + unsafe { std::intrinsics::volatile_load(x) } } #[no_mangle] From ec55a05374d89d206be5140a4759af92f1b42f15 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 19 Jan 2024 11:09:30 +0100 Subject: [PATCH 265/297] Update more data layouts --- compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs | 2 +- compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs | 2 +- compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs | 2 +- .../rustc_target/src/spec/targets/i686_win7_windows_msvc.rs | 2 +- .../src/spec/targets/x86_64_unknown_linux_gnux32.rs | 2 +- .../rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 3ebf4bcf5231..ea8b919e7480 100644 --- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs @@ -5,7 +5,7 @@ pub fn target() -> Target { llvm_target: "i586-pc-unknown".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs index 8375fa4c0c0f..574dc658b78c 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { llvm_target: "i586-unknown-netbsdelf".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { mcount: "__mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index 25315e19cddb..37d57c1cdf30 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs @@ -80,7 +80,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index 5b91682e168a..35ad81dc052b 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -25,7 +25,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-msvc".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs index 1856c6afd52b..d4b6519262e9 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs @@ -16,7 +16,7 @@ pub fn target() -> Target { llvm_target: "x86_64-unknown-linux-gnux32".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32:64-S128" + i64:64-i128:128-f80:128-n8:16:32:64-S128" .into(), arch: "x86_64".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs index 5a59839ebc68..fd26b6e8caea 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-win7-windows-msvc".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } From 867831a1703c0ea7c062a5139538ea20f5921b62 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:54:43 +0000 Subject: [PATCH 266/297] Always use RevealAll for const eval queries --- .../src/const_eval/eval_queries.rs | 36 +++---------- .../rustc_middle/src/mir/interpret/queries.rs | 4 +- ...9-assoc-const-static-recursion-impl.stderr | 5 -- ...onst-static-recursion-trait-default.stderr | 5 -- ...-assoc-const-static-recursion-trait.stderr | 5 -- .../const-eval/const-eval-query-stack.stderr | 5 +- tests/ui/consts/const-size_of-cycle.stderr | 5 -- tests/ui/consts/issue-36163.stderr | 14 ++++-- tests/ui/consts/issue-44415.stderr | 5 -- .../recursive-zst-static.default.stderr | 9 +--- .../recursive-zst-static.unleash.stderr | 9 +--- .../write-to-static-mut-in-static.stderr | 9 +--- .../impl-trait/in-ctfe/array-len-size-of.rs | 16 ++++++ tests/ui/impl-trait/in-ctfe/array-len.rs | 22 ++++++++ tests/ui/impl-trait/in-ctfe/enum-discr.rs | 26 ++++++++++ .../in-ctfe/fully_monomorphic_const_eval.rs | 29 +++++++++++ .../in-ctfe/match-arm-exhaustive.rs | 24 +++++++++ .../impl-trait/transmute/in-defining-scope.rs | 14 ++++++ .../transmute/in-defining-scope.stderr | 29 +++++++++++ .../transmute/outside-of-defining-scope.rs | 12 +++++ tests/ui/issues/issue-23302-1.stderr | 12 +++-- tests/ui/issues/issue-23302-2.stderr | 13 +++-- tests/ui/issues/issue-23302-3.stderr | 10 ++-- .../recursive-static-definition.stderr | 9 +--- .../ctfe/default-assoc-const.rs | 18 +++++++ .../ctfe/default-assoc-const.stderr | 12 +++++ .../specialization/ctfe/default-assoc-type.rs | 27 ++++++++++ .../ctfe/default-assoc-type.stderr | 12 +++++ tests/ui/treat-err-as-bug/err.stderr | 2 +- .../self-in-enum-definition.stderr | 5 -- .../type-alias-impl-trait/in-where-clause.rs | 16 ++++++ .../in-where-clause.stderr | 50 +++++++++++++++++++ 32 files changed, 362 insertions(+), 107 deletions(-) create mode 100644 tests/ui/impl-trait/in-ctfe/array-len-size-of.rs create mode 100644 tests/ui/impl-trait/in-ctfe/array-len.rs create mode 100644 tests/ui/impl-trait/in-ctfe/enum-discr.rs create mode 100644 tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs create mode 100644 tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs create mode 100644 tests/ui/impl-trait/transmute/in-defining-scope.rs create mode 100644 tests/ui/impl-trait/transmute/in-defining-scope.stderr create mode 100644 tests/ui/impl-trait/transmute/outside-of-defining-scope.rs create mode 100644 tests/ui/specialization/ctfe/default-assoc-const.rs create mode 100644 tests/ui/specialization/ctfe/default-assoc-const.stderr create mode 100644 tests/ui/specialization/ctfe/default-assoc-type.rs create mode 100644 tests/ui/specialization/ctfe/default-assoc-type.stderr create mode 100644 tests/ui/type-alias-impl-trait/in-where-clause.rs create mode 100644 tests/ui/type-alias-impl-trait/in-where-clause.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 9d22df50d4f3..4236117d75b9 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -225,17 +225,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { - // see comment in eval_to_allocation_raw_provider for what we're doing here - if key.param_env.reveal() == Reveal::All { - let mut key = key; - key.param_env = key.param_env.with_user_facing(); - match tcx.eval_to_const_value_raw(key) { - // try again with reveal all as requested - Err(ErrorHandled::TooGeneric(_)) => {} - // deduplicate calls - other => return other, - } - } + // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of + // opaque types. This is needed for trivial things like `size_of`, but also for using associated + // types that are not specified in the opaque type. + assert_eq!(key.param_env.reveal(), Reveal::All); // 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. @@ -265,24 +258,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { - // Because the constant is computed twice (once per value of `Reveal`), we are at risk of - // reporting the same error twice here. To resolve this, we check whether we can evaluate the - // constant in the more restrictive `Reveal::UserFacing`, which most likely already was - // computed. For a large percentage of constants that will already have succeeded. Only - // associated constants of generic functions will fail due to not enough monomorphization - // information being available. + // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of + // opaque types. This is needed for trivial things like `size_of`, but also for using associated + // types that are not specified in the opaque type. - // In case we fail in the `UserFacing` variant, we just do the real computation. - if key.param_env.reveal() == Reveal::All { - let mut key = key; - key.param_env = key.param_env.with_user_facing(); - match tcx.eval_to_allocation_raw(key) { - // try again with reveal all as requested - Err(ErrorHandled::TooGeneric(_)) => {} - // deduplicate calls - other => return other, - } - } + assert_eq!(key.param_env.reveal(), Reveal::All); if cfg!(debug_assertions) { // Make sure we format the instance even if we do not print it. // This serves as a regression test against an ICE on printing. diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 092b59deeff3..b20df1b23434 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -145,7 +145,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> EvalToConstValueResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.and(cid)); + let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); if let Some(span) = span { // The query doesn't know where it is being invoked, so we need to fix the span. self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span)) @@ -164,7 +164,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> EvalToValTreeResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.and(cid)); + let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); debug!(?inputs); if let Some(span) = span { // The query doesn't know where it is being invoked, so we need to fix the span. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 21062fdaf585..88b17be601ce 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`. | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 - | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27 | diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index e4abf6203e8f..fd1b4f2f964b 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `DEFAULT_REF_BA | LL | const DEFAULT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 - | -LL | const DEFAULT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30 | diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 05ebd76f5001..303400f928e6 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR` | LL | const TRAIT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 - | -LL | const TRAIT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28 | diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr index 01fb8153cf38..1b60f7f3f2d3 100644 --- a/tests/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr @@ -7,7 +7,6 @@ LL | const X: i32 = 1 / 0; query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `X` #1 [eval_to_const_value_raw] simplifying constant for the type system `X` -#2 [eval_to_const_value_raw] simplifying constant for the type system `X` -#3 [lint_mod] linting top-level module -#4 [analysis] running analysis passes on this crate +#2 [lint_mod] linting top-level module +#3 [analysis] running analysis passes on this crate end of query stack diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr index a5679400c2f0..cd0ea5564254 100644 --- a/tests/ui/consts/const-size_of-cycle.stderr +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::()] note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/const-size_of-cycle.rs:4:17 | -LL | bytes: [u8; std::mem::size_of::()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/const-size_of-cycle.rs:4:17 - | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 4f2d92ba3cde..de70a457f16f 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -20,11 +20,17 @@ note: ...which requires const-evaluating + checking `A`... LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}` - --> $DIR/issue-36163.rs:4:9 +note: cycle used when collecting item types in top-level module + --> $DIR/issue-36163.rs:1:1 | -LL | B = A, - | ^ +LL | / const A: isize = Foo::B as isize; +LL | | +LL | | enum Foo { +LL | | B = A, +LL | | } +LL | | +LL | | fn main() {} + | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-44415.stderr b/tests/ui/consts/issue-44415.stderr index adb5747c4240..641945fce9fd 100644 --- a/tests/ui/consts/issue-44415.stderr +++ b/tests/ui/consts/issue-44415.stderr @@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/issue-44415.rs:6:17 | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/issue-44415.rs:6:17 - | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... diff --git a/tests/ui/consts/recursive-zst-static.default.stderr b/tests/ui/consts/recursive-zst-static.default.stderr index 3bbb685a6781..5b4a0418b1e9 100644 --- a/tests/ui/consts/recursive-zst-static.default.stderr +++ b/tests/ui/consts/recursive-zst-static.default.stderr @@ -1,15 +1,10 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` - --> $DIR/recursive-zst-static.rs:10:1 - | -LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 | LL | static FOO: () = FOO; | ^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/recursive-zst-static.unleash.stderr b/tests/ui/consts/recursive-zst-static.unleash.stderr index 3bbb685a6781..5b4a0418b1e9 100644 --- a/tests/ui/consts/recursive-zst-static.unleash.stderr +++ b/tests/ui/consts/recursive-zst-static.unleash.stderr @@ -1,15 +1,10 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` - --> $DIR/recursive-zst-static.rs:10:1 - | -LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 | LL | static FOO: () = FOO; | ^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/write-to-static-mut-in-static.stderr b/tests/ui/consts/write-to-static-mut-in-static.stderr index 5665e56439e0..caee433a6813 100644 --- a/tests/ui/consts/write-to-static-mut-in-static.stderr +++ b/tests/ui/consts/write-to-static-mut-in-static.stderr @@ -5,17 +5,12 @@ LL | pub static mut B: () = unsafe { A = 1; }; | ^^^^^ modifying a static's initial value from another static's initializer error[E0391]: cycle detected when const-evaluating + checking `C` - --> $DIR/write-to-static-mut-in-static.rs:5:1 - | -LL | pub static mut C: u32 = unsafe { C = 1; 0 }; - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `C`... --> $DIR/write-to-static-mut-in-static.rs:5:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ - = note: ...which again requires const-evaluating + checking `C`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `C` again note: cycle used when linting top-level module --> $DIR/write-to-static-mut-in-static.rs:1:1 | diff --git a/tests/ui/impl-trait/in-ctfe/array-len-size-of.rs b/tests/ui/impl-trait/in-ctfe/array-len-size-of.rs new file mode 100644 index 000000000000..01ba902ef0c0 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/array-len-size-of.rs @@ -0,0 +1,16 @@ +//! Check that const eval can use the size of opaque types. +// check-pass +use std::mem; +fn returns_opaque() -> impl Sized { + 0u8 +} + +struct NamedOpaqueType { + data: [mem::MaybeUninit; size_of_fut(returns_opaque)], +} + +const fn size_of_fut(x: fn() -> FUT) -> usize { + mem::size_of::() +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-ctfe/array-len.rs b/tests/ui/impl-trait/in-ctfe/array-len.rs new file mode 100644 index 000000000000..73ae20495d57 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/array-len.rs @@ -0,0 +1,22 @@ +//! Check that array lengths can observe associated types of opaque types +// check-pass +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +fn main() { + let x = [0u8; output(yeet())]; + println!("{:?}", x); +} diff --git a/tests/ui/impl-trait/in-ctfe/enum-discr.rs b/tests/ui/impl-trait/in-ctfe/enum-discr.rs new file mode 100644 index 000000000000..8e4384adaa4c --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/enum-discr.rs @@ -0,0 +1,26 @@ +//! check that const eval can observe associated types of opaque types. +// check-pass +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +#[repr(usize)] +enum Foo { + Bar = output(yeet()), +} + +fn main() { + println!("{}", Foo::Bar as usize); +} diff --git a/tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs b/tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs new file mode 100644 index 000000000000..82a9a30a6236 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs @@ -0,0 +1,29 @@ +//! This test ensures that we do look at the hidden types of +//! opaque types during const eval in order to obtain the exact type +//! of associated types. + +// check-pass + +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +struct Foo<'a>(&'a ()); +const NEED_REVEAL_ALL: usize = output(yeet()); + +fn promote_div() -> &'static usize { + &(10 / NEED_REVEAL_ALL) +} +fn main() {} diff --git a/tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs b/tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs new file mode 100644 index 000000000000..8e3269726fc4 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs @@ -0,0 +1,24 @@ +//! Check that pattern matching can observe the hidden type of opaque types. +// check-pass +trait MyTrait: Copy { + const ASSOC: u8; +} + +impl MyTrait for () { + const ASSOC: u8 = 0; +} + +const fn yeet() -> impl MyTrait {} + +const fn output(_: T) -> u8 { + ::ASSOC +} + +const CT: u8 = output(yeet()); + +fn main() { + match 0 { + CT => (), + 1.. => (), + } +} diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.rs b/tests/ui/impl-trait/transmute/in-defining-scope.rs new file mode 100644 index 000000000000..b0b77d60b245 --- /dev/null +++ b/tests/ui/impl-trait/transmute/in-defining-scope.rs @@ -0,0 +1,14 @@ +// This causes a query cycle due to using `Reveal::All`, +// in #119821 const eval was changed to always use `Reveal::All` +// +// See that PR for more details. +use std::mem::transmute; +fn foo() -> impl Sized { + //~^ ERROR cycle detected when computing type of + unsafe { + transmute::<_, u8>(foo()); + } + 0u8 +} + +fn main() {} diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.stderr b/tests/ui/impl-trait/transmute/in-defining-scope.stderr new file mode 100644 index 000000000000..69812f43072b --- /dev/null +++ b/tests/ui/impl-trait/transmute/in-defining-scope.stderr @@ -0,0 +1,29 @@ +error[E0391]: cycle detected when computing type of `foo::{opaque#0}` + --> $DIR/in-defining-scope.rs:6:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ + | +note: ...which requires computing type of opaque `foo::{opaque#0}`... + --> $DIR/in-defining-scope.rs:6:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires type-checking `foo`... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `foo::{opaque#0}`... + = note: ...which requires normalizing `foo::{opaque#0}`... + = note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle +note: cycle used when checking that `foo::{opaque#0}` is well-formed + --> $DIR/in-defining-scope.rs:6:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/transmute/outside-of-defining-scope.rs b/tests/ui/impl-trait/transmute/outside-of-defining-scope.rs new file mode 100644 index 000000000000..7bc22ea416f0 --- /dev/null +++ b/tests/ui/impl-trait/transmute/outside-of-defining-scope.rs @@ -0,0 +1,12 @@ +//! Check that typeck can observe the size of an opaque type. +// check-pass +use std::mem::transmute; +fn foo() -> impl Sized { + 0u8 +} + +fn main() { + unsafe { + transmute::<_, u8>(foo()); + } +} diff --git a/tests/ui/issues/issue-23302-1.stderr b/tests/ui/issues/issue-23302-1.stderr index 5c2758dc6090..53131f9130d9 100644 --- a/tests/ui/issues/issue-23302-1.stderr +++ b/tests/ui/issues/issue-23302-1.stderr @@ -10,11 +10,15 @@ note: ...which requires const-evaluating + checking `X::A::{constant#0}`... LL | A = X::A as isize, | ^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `X::A::{constant#0}` - --> $DIR/issue-23302-1.rs:4:9 +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23302-1.rs:3:1 | -LL | A = X::A as isize, - | ^^^^^^^^^^^^^ +LL | / enum X { +LL | | A = X::A as isize, +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23302-2.stderr b/tests/ui/issues/issue-23302-2.stderr index 93665af69dd8..d55d88762be4 100644 --- a/tests/ui/issues/issue-23302-2.stderr +++ b/tests/ui/issues/issue-23302-2.stderr @@ -10,11 +10,16 @@ note: ...which requires const-evaluating + checking `Y::A::{constant#0}`... LL | A = Y::B as isize, | ^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `Y::A::{constant#0}` - --> $DIR/issue-23302-2.rs:4:9 +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23302-2.rs:3:1 | -LL | A = Y::B as isize, - | ^^^^^^^^^^^^^ +LL | / enum Y { +LL | | A = Y::B as isize, +LL | | B, +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23302-3.stderr b/tests/ui/issues/issue-23302-3.stderr index b3e933a21718..e23957c6de75 100644 --- a/tests/ui/issues/issue-23302-3.stderr +++ b/tests/ui/issues/issue-23302-3.stderr @@ -20,11 +20,15 @@ note: ...which requires const-evaluating + checking `B`... LL | const B: i32 = A; | ^ = note: ...which again requires simplifying constant for the type system `A`, completing the cycle -note: cycle used when simplifying constant for the type system `A` +note: cycle used when linting top-level module --> $DIR/issue-23302-3.rs:1:1 | -LL | const A: i32 = B; - | ^^^^^^^^^^^^ +LL | / const A: i32 = B; +LL | | +LL | | const B: i32 = A; +LL | | +LL | | fn main() { } + | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/recursion/recursive-static-definition.stderr b/tests/ui/recursion/recursive-static-definition.stderr index 570d203d07f7..4fc3ee68ebc2 100644 --- a/tests/ui/recursion/recursive-static-definition.stderr +++ b/tests/ui/recursion/recursive-static-definition.stderr @@ -1,15 +1,10 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` - --> $DIR/recursive-static-definition.rs:1:1 - | -LL | pub static FOO: u32 = FOO; - | ^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-static-definition.rs:1:23 | LL | pub static FOO: u32 = FOO; | ^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-static-definition.rs:1:1 | diff --git a/tests/ui/specialization/ctfe/default-assoc-const.rs b/tests/ui/specialization/ctfe/default-assoc-const.rs new file mode 100644 index 000000000000..bb3b735caa31 --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-const.rs @@ -0,0 +1,18 @@ +//! Regression test for revealing associated types through specialization during const eval. +// check-pass +#![feature(specialization)] +//~^ WARNING the feature `specialization` is incomplete and may not be safe to use + +trait Foo { + const ASSOC: usize; +} + +impl Foo for u32 { + default const ASSOC: usize = 0; +} + +fn foo() -> [u8; 0] { + [0; ::ASSOC] +} + +fn main() {} diff --git a/tests/ui/specialization/ctfe/default-assoc-const.stderr b/tests/ui/specialization/ctfe/default-assoc-const.stderr new file mode 100644 index 000000000000..933b6dcf8f99 --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-const.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-assoc-const.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/ctfe/default-assoc-type.rs b/tests/ui/specialization/ctfe/default-assoc-type.rs new file mode 100644 index 000000000000..3624a0f160c5 --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-type.rs @@ -0,0 +1,27 @@ +//! Regression test showing that we can access associated types during const eval, +//! even if they rely on specialization. +// check-pass +#![feature(specialization)] +//~^ WARNING the feature `specialization` is incomplete and may not be safe to use + +trait Foo { + type Assoc: Trait; +} + +impl Foo for Vec { + default type Assoc = u32; +} + +trait Trait { + const ASSOC: usize; +} + +impl Trait for u32 { + const ASSOC: usize = 0; +} + +fn foo() -> [u8; 0] { + [0; < as Foo>::Assoc as Trait>::ASSOC] +} + +fn main() {} diff --git a/tests/ui/specialization/ctfe/default-assoc-type.stderr b/tests/ui/specialization/ctfe/default-assoc-type.stderr new file mode 100644 index 000000000000..23fa213caffb --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-type.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-assoc-type.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index 3a56445a26b5..7eeec4604c4d 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -8,5 +8,5 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `C` -#1 [eval_to_allocation_raw] const-evaluating + checking `C` +#1 [lint_mod] linting top-level module end of query stack diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr index 94113b336c33..7f80c3cfaba4 100644 --- a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph LL | V3 = Self::V1 {} as u8 + 2, | ^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`... - --> $DIR/self-in-enum-definition.rs:5:10 - | -LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`... --> $DIR/self-in-enum-definition.rs:5:10 | diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs new file mode 100644 index 000000000000..0ad6e7a6f601 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs @@ -0,0 +1,16 @@ +//! We evaluate `1 + 2` with `Reveal::All` during typeck, causing +//! us to to get the concrete type of `Bar` while computing it. +//! This again requires type checking `foo`. +#![feature(type_alias_impl_trait)] +type Bar = impl Sized; +//~^ ERROR: cycle +//~| ERROR: cycle + +fn foo() -> Bar +where + Bar: Send, +{ + [0; 1 + 2] +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr new file mode 100644 index 000000000000..9c08b8f127d2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -0,0 +1,50 @@ +error[E0391]: cycle detected when computing type of `Bar::{opaque#0}` + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + | +note: ...which requires computing type of opaque `Bar::{opaque#0}`... + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ +note: ...which requires type-checking `foo`... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ + = note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }]`... + = note: ...which again requires computing type of `Bar::{opaque#0}`, completing the cycle +note: cycle used when checking that `Bar::{opaque#0}` is well-formed + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}` + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `foo`... + --> $DIR/in-where-clause.rs:13:9 + | +LL | [0; 1 + 2] + | ^^^^^ + = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`... + = note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle +note: cycle used when computing type of `Bar::{opaque#0}` + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. From 058ab53dc58b70d4b0b60374d4f7ddfede4dae65 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 19 Jan 2024 08:19:18 +0100 Subject: [PATCH 267/297] use implied bounds compat mode in MIR borrowck --- .../query/type_op/implied_outlives_bounds.rs | 12 ++++++++++-- .../issue-111404-1.rs | 1 - .../issue-111404-1.stderr | 10 +--------- tests/ui/implied-bounds/bevy_world_query.rs | 4 +++- .../normalization-nested.lifetime.stderr | 10 ++++++++++ .../ui/implied-bounds/normalization-nested.rs | 14 ++++++++++---- ...09.stderr => issue-80409.no-compat.stderr} | 0 tests/ui/inference/issue-80409.rs | 19 ++++++++++++------- 8 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 tests/ui/implied-bounds/normalization-nested.lifetime.stderr rename tests/ui/inference/{issue-80409.stderr => issue-80409.no-compat.stderr} (100%) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 2fdb63d7deeb..83d23597c0cd 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -48,14 +48,22 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { param_env.and(ty) }); - tcx.implied_outlives_bounds(canonicalized) + if tcx.sess.opts.unstable_opts.no_implied_bounds_compat { + tcx.implied_outlives_bounds(canonicalized) + } else { + tcx.implied_outlives_bounds_compat(canonicalized) + } } fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, ) -> Result { - compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty) + if ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat { + compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty) + } else { + compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty) + } } } diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index 74f9434b8818..dd62e59f07d2 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -10,6 +10,5 @@ impl<'a> Foo { fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} //~^ ERROR higher-ranked subtype error //~| ERROR higher-ranked subtype error -//~| ERROR higher-ranked subtype error fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr index 1613161a873f..cf4d4a5f19b1 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr @@ -12,13 +12,5 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 - | -LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs index d5de0e9ef217..2e3d4e6a7c66 100644 --- a/tests/ui/implied-bounds/bevy_world_query.rs +++ b/tests/ui/implied-bounds/bevy_world_query.rs @@ -19,7 +19,9 @@ impl SystemParam for Query { pub struct ParamSet(T) where T::State: Sized; -fn handler<'a>(_: ParamSet>) {} +fn handler<'a>(x: ParamSet>) { + let _: ParamSet<_> = x; +} fn ref_handler<'a>(_: &ParamSet>) {} diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr new file mode 100644 index 000000000000..c43cc0999f1d --- /dev/null +++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/normalization-nested.rs:40:5 + | +LL | pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { + | -- lifetime `'x` defined here +LL | s + | ^ returning this value requires that `'x` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs index 3f569aa1acea..6ceb13e94731 100644 --- a/tests/ui/implied-bounds/normalization-nested.rs +++ b/tests/ui/implied-bounds/normalization-nested.rs @@ -1,14 +1,19 @@ // Test for normalization of projections that appear in the item bounds // (versus those that appear directly in the input types). // -// revisions: param_ty lifetime -// check-pass +// revisions: param_ty lifetime param_ty_no_compat lifetime_no_compat + +//[param_ty] check-pass +//[param_ty_no_compat] check-pass +//[lifetime_no_compat] check-pass +//[param_ty_no_compat] compile-flags: -Zno-implied-bounds-compat +//[lifetime_no_compat] compile-flags: -Zno-implied-bounds-compat pub trait Iter { type Item; } -#[cfg(param_ty)] +#[cfg(any(param_ty, param_ty_no_compat))] impl Iter for I where I: IntoIterator, @@ -16,7 +21,7 @@ where type Item = X; } -#[cfg(lifetime)] +#[cfg(any(lifetime, lifetime_no_compat))] impl<'x, I> Iter for I where I: IntoIterator, @@ -33,6 +38,7 @@ pub fn test_wfcheck<'x>(_: Map>) {} pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { s + //[lifetime]~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/inference/issue-80409.stderr b/tests/ui/inference/issue-80409.no-compat.stderr similarity index 100% rename from tests/ui/inference/issue-80409.stderr rename to tests/ui/inference/issue-80409.no-compat.stderr diff --git a/tests/ui/inference/issue-80409.rs b/tests/ui/inference/issue-80409.rs index d36688978e9f..49c9978fe155 100644 --- a/tests/ui/inference/issue-80409.rs +++ b/tests/ui/inference/issue-80409.rs @@ -1,12 +1,17 @@ // This should not pass, because `usize: Fsm` does not hold. However, it currently ICEs. -// check-fail -// known-bug: #80409 -// failure-status: 101 -// normalize-stderr-test "note: .*\n\n" -> "" -// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" -// normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -// rustc-env:RUST_BACKTRACE=0 +// ignore-tidy-linelength + +// revisions: compat no-compat +//[compat] check-pass +//[no-compat] compile-flags: -Zno-implied-bounds-compat +//[no-compat] check-fail +//[no-compat] known-bug: #80409 +//[no-compat] failure-status: 101 +//[no-compat] normalize-stderr-test "note: .*\n\n" -> "" +//[no-compat] normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +//[no-compat] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//[no-compat] rustc-env:RUST_BACKTRACE=0 #![allow(unreachable_code, unused)] From 130b7e713e879c4c989186d94643be8c834de355 Mon Sep 17 00:00:00 2001 From: Gavin Gray Date: Tue, 21 Nov 2023 20:37:36 +0100 Subject: [PATCH 268/297] Add trait obligation tracking to FulfillCtxt and expose FnCtxt in rustc_infer using callback. Pass each obligation to an fn callback with its respective inference context. This avoids needing to keep around copies of obligations or inference contexts. Specify usability of inspect_typeck in comment. --- compiler/rustc_hir_typeck/src/lib.rs | 24 +++- compiler/rustc_infer/src/infer/at.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 16 ++- compiler/rustc_infer/src/traits/mod.rs | 8 ++ .../src/solve/fulfill.rs | 136 ++++++++++-------- 5 files changed, 121 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 67c35d717a1e..80467ca9381e 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -60,6 +60,7 @@ use rustc_hir::{HirIdMap, Node}; use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::check_abi; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::ObligationInspector; use rustc_middle::query::Providers; use rustc_middle::traits; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -139,7 +140,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); - typeck_with_fallback(tcx, def_id, fallback) + typeck_with_fallback(tcx, def_id, fallback, None) } /// Used only to get `TypeckResults` for type inference during error recovery. @@ -149,14 +150,28 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") }; - typeck_with_fallback(tcx, def_id, fallback) + typeck_with_fallback(tcx, def_id, fallback, None) } -#[instrument(level = "debug", skip(tcx, fallback), ret)] +/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation. +/// Inspecting obligations only works with the new trait solver. +/// This function is *only to be used* by external tools, it should not be +/// called from within rustc. Note, this is not a query, and thus is not cached. +pub fn inspect_typeck<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + inspect: ObligationInspector<'tcx>, +) -> &'tcx ty::TypeckResults<'tcx> { + let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); + typeck_with_fallback(tcx, def_id, fallback, Some(inspect)) +} + +#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, fallback: impl Fn() -> Ty<'tcx> + 'tcx, + inspector: Option>, ) -> &'tcx ty::TypeckResults<'tcx> { // Closures' typeck results come from their outermost function, // as they are part of the same "inference environment". @@ -178,6 +193,9 @@ fn typeck_with_fallback<'tcx>( let param_env = tcx.param_env(def_id); let inh = Inherited::new(tcx, def_id); + if let Some(inspector) = inspector { + inh.infcx.attach_obligation_inspector(inspector); + } let mut fcx = FnCtxt::new(&inh, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index e60e3ffeaa72..0f1af81d9f04 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -90,6 +90,7 @@ impl<'tcx> InferCtxt<'tcx> { universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, + obligation_inspector: self.obligation_inspector.clone(), } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e164041c5991..39c41a93c3bd 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -13,7 +13,9 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; -use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; +use crate::traits::{ + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, +}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -334,6 +336,8 @@ pub struct InferCtxt<'tcx> { pub intercrate: bool, next_trait_solver: bool, + + pub obligation_inspector: Cell>>, } impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { @@ -708,6 +712,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, + obligation_inspector: Cell::new(None), } } } @@ -1724,6 +1729,15 @@ impl<'tcx> InferCtxt<'tcx> { } } } + + /// Attach a callback to be invoked on each root obligation evaluated in the new trait solver. + pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) { + debug_assert!( + self.obligation_inspector.get().is_none(), + "shouldn't override a set obligation inspector" + ); + self.obligation_inspector.set(Some(inspector)); + } } impl<'tcx> TypeErrCtxt<'_, 'tcx> { diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index fdae093aac8b..72ec07375ac0 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -13,12 +13,15 @@ use std::hash::{Hash, Hasher}; use hir::def_id::LocalDefId; use rustc_hir as hir; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::Certainty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; pub use self::ImplSource::*; pub use self::SelectionError::*; +use crate::infer::InferCtxt; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::project::MismatchedProjectionTypes; @@ -116,6 +119,11 @@ pub type PredicateObligations<'tcx> = Vec>; pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; +/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation +/// of root obligations. +pub type ObligationInspector<'tcx> = + fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result); + pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index c847425ebf46..f08622816ec2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -11,7 +11,7 @@ use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use super::eval_ctxt::GenerateProofTree; -use super::{Certainty, InferCtxtEvalExt}; +use super::{Certainty, Goal, InferCtxtEvalExt}; /// A trait engine using the new trait solver. /// @@ -43,6 +43,21 @@ impl<'tcx> FulfillmentCtxt<'tcx> { ); FulfillmentCtxt { obligations: Vec::new(), usable_in_snapshot: infcx.num_open_snapshots() } } + + fn inspect_evaluated_obligation( + &self, + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, + result: &Result<(bool, Certainty, Vec>>), NoSolution>, + ) { + if let Some(inspector) = infcx.obligation_inspector.get() { + let result = match result { + Ok((_, c, _)) => Ok(*c), + Err(NoSolution) => Err(NoSolution), + }; + (inspector)(infcx, &obligation, result); + } + } } impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { @@ -100,65 +115,66 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut has_changed = false; for obligation in mem::take(&mut self.obligations) { let goal = obligation.clone().into(); - let (changed, certainty, nested_goals) = - match infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0 { - Ok(result) => result, - Err(NoSolution) => { - errors.push(FulfillmentError { - obligation: obligation.clone(), - code: match goal.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { - FulfillmentErrorCode::ProjectionError( - // FIXME: This could be a `Sorts` if the term is a type - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::ProjectionError( - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::ProjectionError( - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( - goal.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(true, a, b); - FulfillmentErrorCode::SubtypeError( - expected_found, - TypeError::Sorts(expected_found), - ) - } - ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( - goal.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(false, a, b); - FulfillmentErrorCode::SubtypeError( - expected_found, - TypeError::Sorts(expected_found), - ) - } - ty::PredicateKind::Clause(_) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::Ambiguous => { - FulfillmentErrorCode::SelectionError( - SelectionError::Unimplemented, - ) - } - ty::PredicateKind::ConstEquate(..) => { - bug!("unexpected goal: {goal:?}") - } - }, - root_obligation: obligation, - }); - continue; - } - }; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0; + self.inspect_evaluated_obligation(infcx, &obligation, &result); + let (changed, certainty, nested_goals) = match result { + Ok(result) => result, + Err(NoSolution) => { + errors.push(FulfillmentError { + obligation: obligation.clone(), + code: match goal.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { + FulfillmentErrorCode::ProjectionError( + // FIXME: This could be a `Sorts` if the term is a type + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::NormalizesTo(..) => { + FulfillmentErrorCode::ProjectionError( + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::AliasRelate(_, _, _) => { + FulfillmentErrorCode::ProjectionError( + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::Subtype(pred) => { + let (a, b) = infcx.instantiate_binder_with_placeholders( + goal.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(true, a, b); + FulfillmentErrorCode::SubtypeError( + expected_found, + TypeError::Sorts(expected_found), + ) + } + ty::PredicateKind::Coerce(pred) => { + let (a, b) = infcx.instantiate_binder_with_placeholders( + goal.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(false, a, b); + FulfillmentErrorCode::SubtypeError( + expected_found, + TypeError::Sorts(expected_found), + ) + } + ty::PredicateKind::Clause(_) + | ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::Ambiguous => { + FulfillmentErrorCode::SelectionError( + SelectionError::Unimplemented, + ) + } + ty::PredicateKind::ConstEquate(..) => { + bug!("unexpected goal: {goal:?}") + } + }, + root_obligation: obligation, + }); + continue; + } + }; // Push any nested goals that we get from unifying our canonical response // with our obligation onto the fulfillment context. self.obligations.extend(nested_goals.into_iter().map(|goal| { From 50b4ca637d5d24e47df5cd453d136185d5ece7df Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 18 Jan 2024 16:43:49 +0000 Subject: [PATCH 269/297] Teach tidy about line/col information for malformed features --- src/tools/tidy/src/features.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 8e791a7dc69c..d673ce7a736d 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -15,7 +15,7 @@ use std::ffi::OsStr; use std::fmt; use std::fs; use std::num::NonZeroU32; -use std::path::Path; +use std::path::{Path, PathBuf}; use regex::Regex; @@ -52,6 +52,8 @@ pub struct Feature { pub since: Option, pub has_gate_test: bool, pub tracking_issue: Option, + pub file: PathBuf, + pub line: usize, } impl Feature { fn tracking_issue_display(&self) -> impl fmt::Display { @@ -184,23 +186,25 @@ pub fn check( .chain(lib_features.iter().map(|feat| (feat, "lib"))); for ((feature_name, feature), kind) in all_features_iter { let since = if let Some(since) = feature.since { since } else { continue }; + let file = feature.file.display(); + let line = feature.line; if since > version && since != Version::CurrentPlaceholder { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" ); } if channel == "nightly" && since == version { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", version::VERSION_PLACEHOLDER ); } if channel != "nightly" && since == Version::CurrentPlaceholder { tidy_error!( bad, - "The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", + "{file}:{line}: The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", ); } } @@ -433,7 +437,14 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba ); } Entry::Vacant(e) => { - e.insert(Feature { level, since, has_gate_test: false, tracking_issue }); + e.insert(Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: path.to_path_buf(), + line: line_number, + }); } } } @@ -559,6 +570,8 @@ fn map_lib_features( since: None, has_gate_test: false, tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), + file: file.to_path_buf(), + line: i + 1, }; mf(Ok((feature_name, feature)), file, i + 1); continue; @@ -588,7 +601,14 @@ fn map_lib_features( }; let tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); - let feature = Feature { level, since, has_gate_test: false, tracking_issue }; + let feature = Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: file.to_path_buf(), + line: i + 1, + }; if line.contains(']') { mf(Ok((feature_name, feature)), file, i + 1); } else { From 93740f94938bc0b082514736be0051946ec8d732 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 31 Jan 2023 12:44:15 +0000 Subject: [PATCH 270/297] Restrict access to the private field of newtype indexes --- compiler/rustc_index_macros/src/newtype.rs | 10 +++++----- compiler/rustc_type_ir/src/lib.rs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index ede8416125d6..0b25628b9e19 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -104,7 +104,7 @@ impl Parse for Newtype { #gate_rustc_only impl ::rustc_serialize::Encodable for #name { fn encode(&self, e: &mut E) { - e.emit_u32(self.private); + e.emit_u32(self.as_u32()); } } } @@ -164,7 +164,7 @@ impl Parse for Newtype { #[inline] fn eq(l: &Option, r: &Option) -> bool { if #max_val < u32::MAX { - l.map(|i| i.private).unwrap_or(#max_val+1) == r.map(|i| i.private).unwrap_or(#max_val+1) + l.map(|i| i.as_u32()).unwrap_or(#max_val+1) == r.map(|i| i.as_u32()).unwrap_or(#max_val+1) } else { match (l, r) { (Some(l), Some(r)) => r == l, @@ -188,7 +188,7 @@ impl Parse for Newtype { #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))] #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)] #vis struct #name { - private: u32, + private_use_as_methods_instead: u32, } #(#consts)* @@ -238,7 +238,7 @@ impl Parse for Newtype { /// Prefer using `from_u32`. #[inline] #vis const unsafe fn from_u32_unchecked(value: u32) -> Self { - Self { private: value } + Self { private_use_as_methods_instead: value } } /// Extracts the value of this index as a `usize`. @@ -250,7 +250,7 @@ impl Parse for Newtype { /// Extracts the value of this index as a `u32`. #[inline] #vis const fn as_u32(self) -> u32 { - self.private + self.private_use_as_methods_instead } /// Extracts the value of this index as a `usize`. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index bff938596458..83efbfb855f9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -327,21 +327,21 @@ impl UniverseIndex { /// name the region `'a`, but that region was not nameable from /// `U` because it was not in scope there. pub fn next_universe(self) -> UniverseIndex { - UniverseIndex::from_u32(self.private.checked_add(1).unwrap()) + UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap()) } /// Returns `true` if `self` can name a name from `other` -- in other words, /// if the set of names in `self` is a superset of those in /// `other` (`self >= other`). pub fn can_name(self, other: UniverseIndex) -> bool { - self.private >= other.private + self >= other } /// Returns `true` if `self` cannot name some names from `other` -- in other /// words, if the set of names in `self` is a strict subset of /// those in `other` (`self < other`). pub fn cannot_name(self, other: UniverseIndex) -> bool { - self.private < other.private + self < other } } From 225f0b9fef38bd7b841bff9911e0ced586dce812 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 19 Jan 2024 16:37:50 +0000 Subject: [PATCH 271/297] Make the remaining "private" fields actually private --- compiler/stable_mir/src/ty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index eba2ac57012b..b0a08cd9b792 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -12,7 +12,7 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct Ty(pub usize); +pub struct Ty(usize); impl Debug for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -138,7 +138,7 @@ impl Const { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ConstId(pub usize); +pub struct ConstId(usize); type Ident = Opaque; From 5afe1399b582434cfdfa2130353a8b03d885685c Mon Sep 17 00:00:00 2001 From: trevyn <230691+trevyn@users.noreply.github.com> Date: Fri, 19 Jan 2024 23:46:17 +0400 Subject: [PATCH 272/297] Increase vscode `git.detectSubmodulesLimit` --- src/bootstrap/src/core/build_steps/setup.rs | 1 + src/etc/rust_analyzer_settings.json | 1 + 2 files changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 9c897ae1bb78..dd9c68aba7f7 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[ "3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541", "47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923", "b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a", + "828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000", ]; static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json"); diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index 32a04cfd5d16..d329fe997cd7 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -1,4 +1,5 @@ { + "git.detectSubmodulesLimit": 20, "rust-analyzer.check.invocationLocation": "root", "rust-analyzer.check.invocationStrategy": "once", "rust-analyzer.check.overrideCommand": [ From 615946db4fc812bff3bb015dfe860c10da4b20c1 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Tue, 5 Dec 2023 22:15:26 +0000 Subject: [PATCH 273/297] Stabilize simple offset_of --- .../src/error_codes/E0795.md | 4 +- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_typeck/src/expr.rs | 12 ++++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/lib.rs | 2 +- library/core/src/mem/mod.rs | 14 ++--- library/core/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - .../feature-gate-offset-of-enum.rs | 2 +- .../feature-gate-offset-of-nested.rs | 28 ++++++++++ .../feature-gate-offset-of-nested.stderr | 55 +++++++++++++++++++ .../dead-code/offset-of-correct-param-env.rs | 2 +- tests/ui/lint/dead-code/offset-of.rs | 2 +- tests/ui/offset-of/offset-of-arg-count.rs | 2 - tests/ui/offset-of/offset-of-arg-count.stderr | 14 ++--- tests/ui/offset-of/offset-of-dst-field.rs | 2 +- tests/ui/offset-of/offset-of-enum.rs | 2 +- tests/ui/offset-of/offset-of-inference.rs | 2 - tests/ui/offset-of/offset-of-inference.stderr | 2 +- tests/ui/offset-of/offset-of-must-use.rs | 1 - tests/ui/offset-of/offset-of-must-use.stderr | 4 +- tests/ui/offset-of/offset-of-output-type.rs | 2 - .../ui/offset-of/offset-of-output-type.stderr | 12 ++-- tests/ui/offset-of/offset-of-private.rs | 2 +- tests/ui/offset-of/offset-of-self.rs | 2 +- tests/ui/offset-of/offset-of-tuple-nested.rs | 2 +- tests/ui/offset-of/offset-of-tuple.rs | 2 +- tests/ui/offset-of/offset-of-unsized.rs | 2 - .../offset-of-unstable-with-feature.rs | 2 +- tests/ui/offset-of/offset-of-unstable.rs | 2 +- 30 files changed, 134 insertions(+), 49 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-offset-of-nested.rs create mode 100644 tests/ui/feature-gates/feature-gate-offset-of-nested.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index 20f51441c291..ad77d72c913a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 2f2b551e6ecf..c512ccc90db5 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -550,6 +550,8 @@ declare_features! ( (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(106655)), + /// Allows using multiple nested field accesses in offset_of! + (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(106655)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows macro attributes on expressions, statements and non-inline modules. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4b1ad28f0941..242e8dc95e23 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3246,6 +3246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let container = self.to_ty(container).normalized; + if let Some(ident_2) = fields.get(1) + && !self.tcx.features().offset_of_nested + { + rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::offset_of_nested, + ident_2.span, + "only a single ident or integer is stable as the field in offset_of", + ) + .emit(); + } + let mut field_indices = Vec::with_capacity(fields.len()); let mut current_container = container; let mut fields = fields.into_iter(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 44795022cbab..7b0138d50bae 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1153,6 +1153,7 @@ symbols! { offset, offset_of, offset_of_enum, + offset_of_nested, ok_or_else, omit_gdb_pretty_printer_section, on, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1a8f245c8be3..81bf6f28693f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -111,6 +111,7 @@ // // Library features: // tidy-alphabetical-start +#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] @@ -176,7 +177,6 @@ #![feature(isqrt)] #![feature(maybe_uninit_uninit_array)] #![feature(non_null_convenience)] -#![feature(offset_of)] #![feature(offset_of_enum)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 407954001e4c..f04ccce40f10 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1303,11 +1303,12 @@ impl SizedTypeProperties for T {} /// Enum variants may be traversed as if they were fields. Variants themselves do /// not have an offset. /// +/// However, on stable only a single field name is supported, which blocks the use of +/// enum support. +/// /// Visibility is respected - all types and fields must be visible to the call site: /// /// ``` -/// #![feature(offset_of)] -/// /// mod nested { /// #[repr(C)] /// pub struct Struct { @@ -1330,8 +1331,6 @@ impl SizedTypeProperties for T {} /// not *identical*, e.g.: /// /// ``` -/// #![feature(offset_of)] -/// /// struct Wrapper(T, U); /// /// type A = Wrapper; @@ -1359,8 +1358,7 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// #![feature(offset_of)] -/// # #![feature(offset_of_enum)] +/// #![feature(offset_of_enum, offset_of_nested)] /// /// use std::mem; /// #[repr(C)] @@ -1396,7 +1394,7 @@ impl SizedTypeProperties for T {} /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` #[cfg(not(bootstrap))] -#[unstable(feature = "offset_of", issue = "106655")] +#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { // The `{}` is for better error messages @@ -1404,7 +1402,7 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { } #[cfg(bootstrap)] -#[unstable(feature = "offset_of", issue = "106655")] +#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] #[allow(missing_docs)] pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8604d41eb686..02af3e6f9476 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -115,7 +115,6 @@ #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] -#![feature(offset_of)] #![feature(iter_map_windows)] #![allow(internal_features)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7a8d9d0ceeca..4b33ad5dfe09 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -329,7 +329,6 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] -#![feature(offset_of)] #![feature(panic_can_unwind)] #![feature(panic_info_message)] #![feature(panic_internals)] diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs index e19dcf9f6a54..1f2f7ee1e191 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs new file mode 100644 index 000000000000..c4eb4720fde5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs @@ -0,0 +1,28 @@ +#![feature(offset_of_enum)] + +use std::mem::offset_of; + +struct S { + a: u8, + b: (u8, u8), + c: T, +} + +struct T { + t: &'static str, +} + +enum Alpha { + One(u8), + Two(u8), +} + +fn main() { + offset_of!(Alpha, Two.0); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, a); + offset_of!((u8, S), 1); + offset_of!((u32, (S, T)), 1.1); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, b.0); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!((S, ()), 0.c); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, c.t); //~ ERROR only a single ident or integer is stable as the field in offset_of +} diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr new file mode 100644 index 000000000000..ebc251fd6630 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr @@ -0,0 +1,55 @@ +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:21:27 + | +LL | offset_of!(Alpha, Two.0); + | ^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:24:33 + | +LL | offset_of!((u32, (S, T)), 1.1); + | _____----------------------------^- + | | | + | | in this macro invocation +LL | | offset_of!(S, b.0); +LL | | offset_of!((S, ()), 0.c); +LL | | offset_of!(S, c.t); +... | + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:25:21 + | +LL | offset_of!(S, b.0); + | ^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:26:27 + | +LL | offset_of!((S, ()), 0.c); + | ^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:27:21 + | +LL | offset_of!(S, c.t); + | ^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs index 2c6fcef25004..ae81a2524396 100644 --- a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs +++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(offset_of)] +#![feature(offset_of_nested)] #![deny(dead_code)] // This struct contains a projection that can only be normalized after getting the field type. diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs index da91de3862fc..5269426d2ff3 100644 --- a/tests/ui/lint/dead-code/offset-of.rs +++ b/tests/ui/lint/dead-code/offset-of.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] #![deny(dead_code)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs index 7b92698c25e8..c86e61a61a72 100644 --- a/tests/ui/offset-of/offset-of-arg-count.rs +++ b/tests/ui/offset-of/offset-of-arg-count.rs @@ -1,5 +1,3 @@ -#![feature(offset_of)] - use std::mem::offset_of; fn main() { diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr index af0d42de30d6..4cb24b3d034b 100644 --- a/tests/ui/offset-of/offset-of-arg-count.stderr +++ b/tests/ui/offset-of/offset-of-arg-count.stderr @@ -1,5 +1,5 @@ error: unexpected end of macro invocation - --> $DIR/offset-of-arg-count.rs:6:34 + --> $DIR/offset-of-arg-count.rs:4:34 | LL | offset_of!(NotEnoughArguments); | ^ missing tokens in macro arguments @@ -8,7 +8,7 @@ note: while trying to match `,` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: unexpected end of macro invocation - --> $DIR/offset-of-arg-count.rs:7:45 + --> $DIR/offset-of-arg-count.rs:5:45 | LL | offset_of!(NotEnoughArgumentsWithAComma, ); | ^ missing tokens in macro arguments @@ -17,7 +17,7 @@ note: while trying to match meta-variable `$fields:expr` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: no rules expected the token `too` - --> $DIR/offset-of-arg-count.rs:8:34 + --> $DIR/offset-of-arg-count.rs:6:34 | LL | offset_of!(Container, field, too many arguments); | ^^^ no rules expected this token in macro call @@ -25,25 +25,25 @@ LL | offset_of!(Container, field, too many arguments); = note: while trying to match sequence end error: unexpected token: `)` - --> $DIR/offset-of-arg-count.rs:11:21 + --> $DIR/offset-of-arg-count.rs:9:21 | LL | offset_of!(S, f.); | ^ error: unexpected token: `,` - --> $DIR/offset-of-arg-count.rs:12:21 + --> $DIR/offset-of-arg-count.rs:10:21 | LL | offset_of!(S, f.,); | ^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-arg-count.rs:13:19 + --> $DIR/offset-of-arg-count.rs:11:19 | LL | offset_of!(S, f..); | ^^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-arg-count.rs:14:19 + --> $DIR/offset-of-arg-count.rs:12:19 | LL | offset_of!(S, f..,); | ^^^ diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs index e393b159e64d..016ebfadd142 100644 --- a/tests/ui/offset-of/offset-of-dst-field.rs +++ b/tests/ui/offset-of/offset-of-dst-field.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, extern_types)] +#![feature(extern_types)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index a2d6aace47da..cb2f04786ac5 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs index ba87574eae04..1b1ae25e1ee6 100644 --- a/tests/ui/offset-of/offset-of-inference.rs +++ b/tests/ui/offset-of/offset-of-inference.rs @@ -1,7 +1,5 @@ // Test that inference types in `offset_of!` don't ICE. -#![feature(offset_of)] - struct Foo { x: T, } diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr index 1845822f11db..8bd104ed7e27 100644 --- a/tests/ui/offset-of/offset-of-inference.stderr +++ b/tests/ui/offset-of/offset-of-inference.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/offset-of-inference.rs:10:35 + --> $DIR/offset-of-inference.rs:8:35 | LL | let _ = core::mem::offset_of!(Foo<_>, x); | ^^^^^^ cannot infer type diff --git a/tests/ui/offset-of/offset-of-must-use.rs b/tests/ui/offset-of/offset-of-must-use.rs index e30145d7a2fe..e4b092fcedf3 100644 --- a/tests/ui/offset-of/offset-of-must-use.rs +++ b/tests/ui/offset-of/offset-of-must-use.rs @@ -1,6 +1,5 @@ // check-pass -#![feature(offset_of)] #![warn(unused)] fn main() { diff --git a/tests/ui/offset-of/offset-of-must-use.stderr b/tests/ui/offset-of/offset-of-must-use.stderr index 5fe387a72553..b6d88e098d00 100644 --- a/tests/ui/offset-of/offset-of-must-use.stderr +++ b/tests/ui/offset-of/offset-of-must-use.stderr @@ -1,11 +1,11 @@ warning: unused return value of `must_use` that must be used - --> $DIR/offset-of-must-use.rs:7:5 + --> $DIR/offset-of-must-use.rs:6:5 | LL | core::mem::offset_of!((String,), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/offset-of-must-use.rs:4:9 + --> $DIR/offset-of-must-use.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs index 50c2e93841f9..76a33154ba3d 100644 --- a/tests/ui/offset-of/offset-of-output-type.rs +++ b/tests/ui/offset-of/offset-of-output-type.rs @@ -1,5 +1,3 @@ -#![feature(offset_of)] - use std::mem::offset_of; struct S { diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr index 233d49876436..34ad931d0caa 100644 --- a/tests/ui/offset-of/offset-of-output-type.stderr +++ b/tests/ui/offset-of/offset-of-output-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:12:17 + --> $DIR/offset-of-output-type.rs:10:17 | LL | let _: u8 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u8`, found `usize` @@ -7,7 +7,7 @@ LL | let _: u8 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:13:18 + --> $DIR/offset-of-output-type.rs:11:18 | LL | let _: u16 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u16`, found `usize` @@ -15,7 +15,7 @@ LL | let _: u16 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:14:18 + --> $DIR/offset-of-output-type.rs:12:18 | LL | let _: u32 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u32`, found `usize` @@ -23,7 +23,7 @@ LL | let _: u32 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:15:18 + --> $DIR/offset-of-output-type.rs:13:18 | LL | let _: u64 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u64`, found `usize` @@ -31,7 +31,7 @@ LL | let _: u64 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:16:20 + --> $DIR/offset-of-output-type.rs:14:20 | LL | let _: isize = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `isize`, found `usize` @@ -39,7 +39,7 @@ LL | let _: isize = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:19:5 + --> $DIR/offset-of-output-type.rs:17:5 | LL | fn main() { | - expected `()` because of default return type diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index b7affdb79439..1c326b5c79a5 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs index 04dcaf7c0a6b..1558e13b5309 100644 --- a/tests/ui/offset-of/offset-of-self.rs +++ b/tests/ui/offset-of/offset-of-self.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs index 59b02e3c5c43..212176b24271 100644 --- a/tests/ui/offset-of/offset-of-tuple-nested.rs +++ b/tests/ui/offset-of/offset-of-tuple-nested.rs @@ -2,7 +2,7 @@ // Test for issue #112204 -- make sure this goes through the entire compilation pipeline, // similar to why `offset-of-unsized.rs` is also build-pass -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index b6fc1e32229a..75ba8d77f2fb 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] #![feature(builtin_syntax)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unsized.rs b/tests/ui/offset-of/offset-of-unsized.rs index 49c8328da5c5..b70529ed7b85 100644 --- a/tests/ui/offset-of/offset-of-unsized.rs +++ b/tests/ui/offset-of/offset-of-unsized.rs @@ -2,8 +2,6 @@ // regression test for #112051, not in `offset-of-dst` as the issue is in codegen, // and isn't triggered in the presence of typeck errors -#![feature(offset_of)] - struct S { a: u64, b: T, diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs index 7d2eb46c056e..be275564a0a4 100644 --- a/tests/ui/offset-of/offset-of-unstable-with-feature.rs +++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs @@ -1,7 +1,7 @@ // check-pass // aux-build:offset-of-staged-api.rs -#![feature(offset_of, unstable_test_feature)] +#![feature(offset_of_nested, unstable_test_feature)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs index 1e19f2091f29..da0882abd228 100644 --- a/tests/ui/offset-of/offset-of-unstable.rs +++ b/tests/ui/offset-of/offset-of-unstable.rs @@ -1,6 +1,6 @@ // aux-build:offset-of-staged-api.rs -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; From 803b810eac520c11c7f1ea0a81af535ee9bddd61 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 5 Jan 2024 21:25:01 +0000 Subject: [PATCH 274/297] Remove feature(offset_of) from tests --- library/core/tests/lib.rs | 1 + tests/mir-opt/const_prop/offset_of.rs | 2 +- tests/mir-opt/dataflow-const-prop/offset_of.rs | 2 +- tests/pretty/offset_of.rs | 1 - tests/ui/layout/issue-112048-unsizing-niche.rs | 1 - 5 files changed, 3 insertions(+), 4 deletions(-) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 02af3e6f9476..13fb97fdc7f3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -59,6 +59,7 @@ #![feature(noop_waker)] #![feature(numfmt)] #![feature(num_midpoint)] +#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 43ecbbed186f..f15d15bfcb26 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index e71b3f59ecab..c1be69102580 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/pretty/offset_of.rs b/tests/pretty/offset_of.rs index e1783432857e..1307c335ad32 100644 --- a/tests/pretty/offset_of.rs +++ b/tests/pretty/offset_of.rs @@ -1,4 +1,3 @@ // pp-exact -#![feature(offset_of)] fn main() { std::mem::offset_of!(std :: ops :: Range < usize >, end); } diff --git a/tests/ui/layout/issue-112048-unsizing-niche.rs b/tests/ui/layout/issue-112048-unsizing-niche.rs index 23588ba36ee5..e59e063df99b 100644 --- a/tests/ui/layout/issue-112048-unsizing-niche.rs +++ b/tests/ui/layout/issue-112048-unsizing-niche.rs @@ -2,7 +2,6 @@ // Check that unsizing does not change which field is considered for niche layout. -#![feature(offset_of)] #![allow(dead_code)] #[derive(Clone)] From 7924c9bcdfa0ec5980474ac680439d7fc2a4690f Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 19 Jan 2024 20:29:40 +0000 Subject: [PATCH 275/297] Split remaining offset_of features into new tracking issues --- compiler/rustc_feature/src/unstable.rs | 4 ++-- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../feature-gate-offset-of-enum.stderr | 4 ++-- .../feature-gate-offset-of-nested.stderr | 15 ++++++++++----- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c512ccc90db5..371b651f5e85 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -549,9 +549,9 @@ declare_features! ( /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! - (unstable, offset_of_enum, "1.75.0", Some(106655)), + (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using multiple nested field accesses in offset_of! - (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(106655)), + (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows macro attributes on expressions, statements and non-inline modules. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 242e8dc95e23..33d7ba6268a2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3250,7 +3250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && !self.tcx.features().offset_of_nested { rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::offset_of_nested, ident_2.span, "only a single ident or integer is stable as the field in offset_of", diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr index 02ee54e8607a..fc7dd7923f7a 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -13,7 +13,7 @@ error[E0658]: using enums in offset_of is experimental LL | offset_of!(Alpha, One); | ^^^ | - = note: see issue #106655 for more information + = note: see issue #120141 for more information = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -29,7 +29,7 @@ error[E0658]: using enums in offset_of is experimental LL | offset_of!(Alpha, Two.0); | ^^^ | - = note: see issue #106655 for more information + = note: see issue #120141 for more information = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr index ebc251fd6630..f367fc9fa0dd 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr @@ -4,8 +4,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of LL | offset_of!(Alpha, Two.0); | ^ | - = note: see issue #106655 for more information + = note: see issue #120140 for more information = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: only a single ident or integer is stable as the field in offset_of --> $DIR/feature-gate-offset-of-nested.rs:24:33 @@ -19,8 +20,9 @@ LL | | offset_of!((S, ()), 0.c); LL | | offset_of!(S, c.t); ... | | - = note: see issue #106655 for more information + = note: see issue #120140 for more information = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: only a single ident or integer is stable as the field in offset_of @@ -29,8 +31,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of LL | offset_of!(S, b.0); | ^ | - = note: see issue #106655 for more information + = note: see issue #120140 for more information = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: only a single ident or integer is stable as the field in offset_of --> $DIR/feature-gate-offset-of-nested.rs:26:27 @@ -38,8 +41,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of LL | offset_of!((S, ()), 0.c); | ^ | - = note: see issue #106655 for more information + = note: see issue #120140 for more information = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: only a single ident or integer is stable as the field in offset_of --> $DIR/feature-gate-offset-of-nested.rs:27:21 @@ -47,8 +51,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of LL | offset_of!(S, c.t); | ^ | - = note: see issue #106655 for more information + = note: see issue #120140 for more information = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 5 previous errors From 0943a6b188e11339d217d43f39322f51d2d8187d Mon Sep 17 00:00:00 2001 From: trevyn <230691+trevyn@users.noreply.github.com> Date: Sat, 20 Jan 2024 01:22:52 +0400 Subject: [PATCH 276/297] add test issue-117965 --- tests/ui/single-use-lifetime/issue-117965.rs | 18 ++++++++++++++++ .../single-use-lifetime/issue-117965.stderr | 21 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/ui/single-use-lifetime/issue-117965.rs create mode 100644 tests/ui/single-use-lifetime/issue-117965.stderr diff --git a/tests/ui/single-use-lifetime/issue-117965.rs b/tests/ui/single-use-lifetime/issue-117965.rs new file mode 100644 index 000000000000..5eb2a03e13da --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-117965.rs @@ -0,0 +1,18 @@ +#![deny(single_use_lifetimes)] + +pub enum Data<'a> { + Borrowed(&'a str), + Owned(String), +} + +impl<'a> Data<'a> { + pub fn get<'b: 'a>(&'b self) -> &'a str { + //~^ ERROR lifetime parameter `'b` only used once + match &self { + Self::Borrowed(val) => val, + Self::Owned(val) => &val, + } + } +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/issue-117965.stderr b/tests/ui/single-use-lifetime/issue-117965.stderr new file mode 100644 index 000000000000..e789e1835462 --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-117965.stderr @@ -0,0 +1,21 @@ +error: lifetime parameter `'b` only used once + --> $DIR/issue-117965.rs:9:16 + | +LL | pub fn get<'b: 'a>(&'b self) -> &'a str { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/issue-117965.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - pub fn get<'b: 'a>(&'b self) -> &'a str { +LL + pub fn get(&self) -> &'a str { + | + +error: aborting due to 1 previous error + From 4459be7bd59c781c850ab48679ef3a1e420e9f99 Mon Sep 17 00:00:00 2001 From: SOFe Date: Sat, 29 Oct 2022 22:15:04 +0800 Subject: [PATCH 277/297] Added NonZeroXxx::from_mut(_unchecked)? --- library/core/src/num/nonzero.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7d60686597a0..582c6796781a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -171,6 +171,32 @@ macro_rules! nonzero_integer { } } + /// Converts a primitive mutable reference to a non-zero mutable reference + /// if the referenced integer is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "none")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { + // SAFETY: Self is repr(transparent), and the value is non-zero. + // As long as the returned reference is alive, + // the user cannot `*n = 0` directly. + (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) + } + + /// Converts a primitive mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if `*n` is zero. + /// + /// # Safety + /// The referenced value must not be currently zero. + #[unstable(feature = "nonzero_from_mut", issue = "none")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { + // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. + unsafe { &mut *(n as *mut $Int as *mut Self) } + } + /// Returns the value as a primitive type. #[$stability] #[inline] From 3acb445f15d69c982c37df15a27d06b43ca6e388 Mon Sep 17 00:00:00 2001 From: SOFe Date: Sun, 30 Oct 2022 14:49:24 +0800 Subject: [PATCH 278/297] Added assert_unsafe_precondition! check for NonZeroXxx::from_mut_unchecked --- library/core/src/num/nonzero.rs | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 582c6796781a..53ee6efcba7c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -171,18 +171,6 @@ macro_rules! nonzero_integer { } } - /// Converts a primitive mutable reference to a non-zero mutable reference - /// if the referenced integer is not zero. - #[unstable(feature = "nonzero_from_mut", issue = "none")] - #[must_use] - #[inline] - pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { - // SAFETY: Self is repr(transparent), and the value is non-zero. - // As long as the returned reference is alive, - // the user cannot `*n = 0` directly. - (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) - } - /// Converts a primitive mutable reference to a non-zero mutable reference /// without checking whether the referenced value is non-zero. /// This results in undefined behavior if `*n` is zero. @@ -194,7 +182,26 @@ macro_rules! nonzero_integer { #[inline] pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. - unsafe { &mut *(n as *mut $Int as *mut Self) } + unsafe { + let n_alias = &mut *n; + core::intrinsics::assert_unsafe_precondition!( + concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"), + (n_alias: &mut $Int) => *n_alias != 0 + ); + &mut *(n as *mut $Int as *mut Self) + } + } + + /// Converts a primitive mutable reference to a non-zero mutable reference + /// if the referenced integer is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "none")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { + // SAFETY: Self is repr(transparent), and the value is non-zero. + // As long as the returned reference is alive, + // the user cannot `*n = 0` directly. + (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) } /// Returns the value as a primitive type. From 596410eb36c90c501fc57f68d81a57b6e0053a5c Mon Sep 17 00:00:00 2001 From: SOFe Date: Fri, 30 Dec 2022 22:50:41 +0800 Subject: [PATCH 279/297] Assign tracking issue number for feature(nonzero_from_mut) --- library/core/src/num/nonzero.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 53ee6efcba7c..bda691b16d4a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -177,7 +177,7 @@ macro_rules! nonzero_integer { /// /// # Safety /// The referenced value must not be currently zero. - #[unstable(feature = "nonzero_from_mut", issue = "none")] + #[unstable(feature = "nonzero_from_mut", issue = "106290")] #[must_use] #[inline] pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { @@ -194,7 +194,7 @@ macro_rules! nonzero_integer { /// Converts a primitive mutable reference to a non-zero mutable reference /// if the referenced integer is not zero. - #[unstable(feature = "nonzero_from_mut", issue = "none")] + #[unstable(feature = "nonzero_from_mut", issue = "106290")] #[must_use] #[inline] pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { From de2575f35d46dfa2b24eb205ef133a679bff1b31 Mon Sep 17 00:00:00 2001 From: trevyn <230691+trevyn@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:30:58 +0400 Subject: [PATCH 280/297] Don't delete any lifetimes with bounds --- compiler/rustc_resolve/src/late/diagnostics.rs | 3 ++- tests/ui/single-use-lifetime/issue-117965.stderr | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 5a95f2083f66..abb0a7a465aa 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2567,8 +2567,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { debug!(?param.ident, ?param.ident.span, ?use_span); let elidable = matches!(use_ctxt, LifetimeCtxt::Ref); + let deletion_span = + if param.bounds.is_empty() { deletion_span() } else { None }; - let deletion_span = deletion_span(); self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::SINGLE_USE_LIFETIMES, param.id, diff --git a/tests/ui/single-use-lifetime/issue-117965.stderr b/tests/ui/single-use-lifetime/issue-117965.stderr index e789e1835462..ed14ab92f4d1 100644 --- a/tests/ui/single-use-lifetime/issue-117965.stderr +++ b/tests/ui/single-use-lifetime/issue-117965.stderr @@ -11,11 +11,6 @@ note: the lint level is defined here | LL | #![deny(single_use_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^ -help: elide the single-use lifetime - | -LL - pub fn get<'b: 'a>(&'b self) -> &'a str { -LL + pub fn get(&self) -> &'a str { - | error: aborting due to 1 previous error From b72af9fe9b01002fd0e352cd7e98ab811a014452 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 19 Jan 2024 18:02:05 -0500 Subject: [PATCH 281/297] Stabilize `round_ties_even` --- library/std/src/f32.rs | 4 +--- library/std/src/f64.rs | 4 +--- library/std/src/lib.rs | 1 - src/tools/miri/src/lib.rs | 1 - src/tools/miri/tests/pass/float.rs | 1 - 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index c3506175715f..1b38ba721147 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -102,8 +102,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(round_ties_even)] - /// /// let f = 3.3_f32; /// let g = -3.3_f32; /// let h = 3.5_f32; @@ -116,7 +114,7 @@ impl f32 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "round_ties_even", issue = "96710")] + #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn round_ties_even(self) -> f32 { unsafe { intrinsics::rintf32(self) } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index e4b7bfeeb84a..f8fc84440ae5 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -102,8 +102,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(round_ties_even)] - /// /// let f = 3.3_f64; /// let g = -3.3_f64; /// let h = 3.5_f64; @@ -116,7 +114,7 @@ impl f64 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "round_ties_even", issue = "96710")] + #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn round_ties_even(self) -> f64 { unsafe { intrinsics::rintf64(self) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7a8d9d0ceeca..11d655042b71 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -338,7 +338,6 @@ #![feature(prelude_2024)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] -#![feature(round_ties_even)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index cacd02bbfaee..80a47c852692 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,7 +8,6 @@ #![feature(variant_count)] #![feature(yeet_expr)] #![feature(nonzero_ops)] -#![feature(round_ties_even)] #![feature(let_chains)] #![feature(lint_reasons)] #![feature(int_roundings)] diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 5f2d4489f4ac..1bb44d56bf6b 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1,5 +1,4 @@ #![feature(stmt_expr_attributes)] -#![feature(round_ties_even)] #![feature(float_gamma)] #![allow(arithmetic_overflow)] From b1688b48d2841a1421cb7ed0afd32ce0c3eeb20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 8 Jan 2024 23:00:06 +0000 Subject: [PATCH 282/297] Avoid ICE: Check diagnostic is error before downgrading Fix #119633. --- .../rustc_hir_analysis/src/astconv/lint.rs | 8 +-- .../object-safety/avoid-ice-on-warning-2.rs | 9 ++++ .../avoid-ice-on-warning-2.stderr | 50 +++++++++++++++++++ .../ui/object-safety/avoid-ice-on-warning.rs | 6 +++ .../object-safety/avoid-ice-on-warning.stderr | 29 +++++++++++ 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-2.rs create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-2.stderr create mode 100644 tests/ui/object-safety/avoid-ice-on-warning.rs create mode 100644 tests/ui/object-safety/avoid-ice-on-warning.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 3761d5295170..bf668f311cc6 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -122,7 +122,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ], Applicability::MachineApplicable, ); - } else { + } else if diag.is_error() { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -148,8 +148,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); - // We'll emit the object safety error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); + if diag.is_error() { + // We'll emit the object safety error already, with a structured suggestion. + diag.downgrade_to_delayed_bug(); + } } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs new file mode 100644 index 000000000000..cd34362d3dd5 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -0,0 +1,9 @@ +fn id(f: Copy) -> usize { +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| ERROR the trait `Copy` cannot be made into an object + f() +} +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr new file mode 100644 index 000000000000..2755eee6f352 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr @@ -0,0 +1,50 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `Copy` it is not object safe, so it can't be `dyn` + = note: `#[warn(bare_trait_objects)]` on by default +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn id(f: impl Copy) -> usize { + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `Copy` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn id(f: impl Copy) -> usize { + | ++++ + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error: aborting due to 1 previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs new file mode 100644 index 000000000000..d2a1eeb5286b --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -0,0 +1,6 @@ +fn call_this(f: F) : Fn(&str) + call_that {} +//~^ ERROR return types are denoted using `->` +//~| ERROR cannot find trait `call_that` in this scope +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning.stderr b/tests/ui/object-safety/avoid-ice-on-warning.stderr new file mode 100644 index 000000000000..1046f177e829 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.stderr @@ -0,0 +1,29 @@ +error: return types are denoted using `->` + --> $DIR/avoid-ice-on-warning.rs:1:23 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^ help: use `->` instead + +error[E0405]: cannot find trait `call_that` in this scope + --> $DIR/avoid-ice-on-warning.rs:1:36 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning.rs:1:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type + | +LL | fn call_this(f: F) : impl Fn(&str) + call_that {} + | ++++ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0405`. From 6b7e6ea590ad0179e9c61c5e007220ae1e4b9644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 9 Jan 2024 00:22:35 +0000 Subject: [PATCH 283/297] Account for traits using self-trait by name without `dyn` Fix #119652. --- .../rustc_hir_analysis/src/astconv/lint.rs | 24 ++-- ...-trait-should-use-self-2021-without-dyn.rs | 19 ++++ ...it-should-use-self-2021-without-dyn.stderr | 105 ++++++++++++++++++ ...bject-unsafe-trait-should-use-self-2021.rs | 17 +++ ...t-unsafe-trait-should-use-self-2021.stderr | 65 +++++++++++ 5 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index bf668f311cc6..b5f42e98127e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; - let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, _), - generics, - .. - })) = tcx.hir_node_by_def_id(parent_id) - else { - return false; + let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { + (sig, generics, None) + } + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + generics, + owner_id, + .. + }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; @@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let is_object_safe = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|o| match o.trait_ref.path.res { + Res::Def(DefKind::Trait, id) if Some(id) == owner => { + // When we're dealing with a recursive trait, we don't want to downgrade + // the error, so we consider them to be object safe always. (#119652) + true + } Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id), _ => false, }) diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs new file mode 100644 index 000000000000..6382480b7e33 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs @@ -0,0 +1,19 @@ +// edition:2021 +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: A) -> A; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword +} +trait B { + fn f(a: B) -> B; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword +} +trait C { + fn f(&self, a: C) -> C; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr new file mode 100644 index 000000000000..1d8ed5480462 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr @@ -0,0 +1,105 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | fn f(a: A) -> A; + | ^ + | +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ +help: alternatively, use a trait object to accept any type that implements `A`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(a: &dyn A) -> A; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(a: A) -> Box; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:9:13 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use a new generic type parameter, constrained by `B` + | +LL | fn f(a: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl B) -> B; + | ++++ +help: alternatively, use a trait object to accept any type that implements `B`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(a: &dyn B) -> B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:9:19 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: B) -> impl B; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(a: B) -> Box; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:14:20 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use a new generic type parameter, constrained by `C` + | +LL | fn f(&self, a: T) -> C; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(&self, a: impl C) -> C; + | ++++ +help: alternatively, use a trait object to accept any type that implements `C`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(&self, a: &dyn C) -> C; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:14:26 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use `impl C` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(&self, a: C) -> impl C; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(&self, a: C) -> Box; + | +++++++ + + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs new file mode 100644 index 000000000000..a598e883f3fd --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs @@ -0,0 +1,17 @@ +// edition:2021 +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: dyn A) -> dyn A; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: dyn B) -> dyn B; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: dyn C) -> dyn C; +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr new file mode 100644 index 000000000000..d6376be9c046 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr @@ -0,0 +1,65 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: dyn A) -> dyn A; + | ^^^^^ ^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + | +LL | fn f(a: dyn A) -> dyn A; + | ^^^^^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:3:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: dyn B) -> dyn B; + | ^^^^^ ^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + | +LL | fn f(a: dyn B) -> dyn B; + | ^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: dyn B) -> dyn B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: dyn B) -> dyn B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: dyn B) -> dyn B where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0038`. From 7edbc95c27664428ba22c448ca85ee4bd4de05dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Jan 2024 23:49:40 +0000 Subject: [PATCH 284/297] Update tests after rebase Fix #119652. --- .../object-safety/avoid-ice-on-warning-3.rs | 17 ++ .../avoid-ice-on-warning-3.stderr | 148 ++++++++++++++++++ ...-trait-should-use-self-2021-without-dyn.rs | 4 + ...it-should-use-self-2021-without-dyn.stderr | 75 ++++++++- 4 files changed, 238 insertions(+), 6 deletions(-) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-3.rs create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-3.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs new file mode 100644 index 000000000000..caaf4d0fd99a --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs @@ -0,0 +1,17 @@ +trait B { fn f(a: A) -> A; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| ERROR the trait `A` cannot be made into an object +trait A { fn g(b: B) -> B; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| ERROR the trait `B` cannot be made into an object +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr new file mode 100644 index 000000000000..0fc67770b96d --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr @@ -0,0 +1,148 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `B` it is not object safe, so it can't be `dyn` + = note: `#[warn(bare_trait_objects)]` on by default +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:25 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | trait A { fn g(b: B) -> impl B; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `A` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:25 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | trait B { fn f(a: A) -> impl A; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `A` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/avoid-ice-on-warning-3.rs:9:14 + | +LL | trait A { fn g(b: B) -> B; } + | - ^ ...because associated function `g` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `g` into a method by giving it a `&self` argument + | +LL | trait A { fn g(&self, b: B) -> B; } + | ++++++ +help: alternatively, consider constraining `g` so it does not apply to trait objects + | +LL | trait A { fn g(b: B) -> B where Self: Sized; } + | +++++++++++++++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `B` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/avoid-ice-on-warning-3.rs:1:14 + | +LL | trait B { fn f(a: A) -> A; } + | - ^ ...because associated function `f` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | trait B { fn f(&self, a: A) -> A; } + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | trait B { fn f(a: A) -> A where Self: Sized; } + | +++++++++++++++++ + +error: aborting due to 2 previous errors; 6 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs index 6382480b7e33..f48c3d124dda 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs @@ -4,11 +4,15 @@ trait A: Sized { fn f(a: A) -> A; //~^ ERROR trait objects must include the `dyn` keyword //~| ERROR trait objects must include the `dyn` keyword + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object } trait B { fn f(a: B) -> B; //~^ ERROR trait objects must include the `dyn` keyword //~| ERROR trait objects must include the `dyn` keyword + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object } trait C { fn f(&self, a: C) -> C; diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr index 1d8ed5480462..73d5a24f8313 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr @@ -1,3 +1,65 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | fn f(a: A) -> A; + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | fn f(a: B) -> B; + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: B) -> B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: B) -> B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: B) -> B where Self: Sized; + | +++++++++++++++++ + error[E0782]: trait objects must include the `dyn` keyword --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 | @@ -33,7 +95,7 @@ LL | fn f(a: A) -> Box; | +++++++ + error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:9:13 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | fn f(a: B) -> B; | ^ @@ -52,7 +114,7 @@ LL | fn f(a: &dyn B) -> B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:9:19 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 | LL | fn f(a: B) -> B; | ^ @@ -67,7 +129,7 @@ LL | fn f(a: B) -> Box; | +++++++ + error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:14:20 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | fn f(&self, a: C) -> C; | ^ @@ -86,7 +148,7 @@ LL | fn f(&self, a: &dyn C) -> C; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:14:26 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 | LL | fn f(&self, a: C) -> C; | ^ @@ -100,6 +162,7 @@ help: alternatively, you can return an owned trait object LL | fn f(&self, a: C) -> Box; | +++++++ + -error: aborting due to 6 previous errors +error: aborting due to 10 previous errors -For more information about this error, try `rustc --explain E0782`. +Some errors have detailed explanations: E0038, E0782. +For more information about an error, try `rustc --explain E0038`. From c3364a23d2a0ec8557f52fcf5a705503619274c3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 15 Jan 2024 14:41:12 -0500 Subject: [PATCH 285/297] perf: Don't track specific live points for promoteds We don't query this information out of the promoted (it's basically a single "unit" regardless of the complexity within it) and this saves on re-initializing the SparseIntervalMatrix's backing IndexVec with mostly empty rows for all of the leading regions in the function. Typical promoteds will only contain a few regions that need up be uplifted, while the parent function can have thousands. For a simple function repeating println!("Hello world"); 50,000 times this reduces compile times from 90 to 15 seconds in debug mode. The previous implementations re-initialization led to an overall roughly n^2 runtime as each promoted initialized slots for ~n regions, now we scale closer to linearly (5000 hello worlds takes 1.1 seconds). --- .../rustc_borrowck/src/region_infer/values.rs | 89 +++++++++++++++---- compiler/rustc_borrowck/src/type_check/mod.rs | 28 +++--- 2 files changed, 87 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 01f7bfcadb6f..e147f62011db 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,5 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; use rustc_index::interval::IntervalSet; @@ -41,8 +42,15 @@ pub(crate) struct LivenessValues { /// The map from locations to points. elements: Rc, + /// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and + /// currently only used for validating promoteds (which don't care about more precise tracking). + live_regions: Option>, + /// For each region: the points where it is live. - points: SparseIntervalMatrix, + /// + /// This is not initialized for promoteds, because we don't care *where* within a promoted a + /// region is live, only that it is. + points: Option>, /// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at /// that point. @@ -71,24 +79,52 @@ impl LiveLoans { impl LivenessValues { /// Create an empty map of regions to locations where they're live. - pub(crate) fn new(elements: Rc) -> Self { + pub(crate) fn with_specific_points(elements: Rc) -> Self { LivenessValues { - points: SparseIntervalMatrix::new(elements.num_points()), + live_regions: None, + points: Some(SparseIntervalMatrix::new(elements.num_points())), + elements, + loans: None, + } + } + + /// Create an empty map of regions to locations where they're live. + /// + /// Unlike `with_specific_points`, does not track exact locations where something is live, only + /// which regions are live. + pub(crate) fn without_specific_points(elements: Rc) -> Self { + LivenessValues { + live_regions: Some(Default::default()), + points: None, elements, loans: None, } } /// Iterate through each region that has a value in this set. - pub(crate) fn regions(&self) -> impl Iterator { - self.points.rows() + pub(crate) fn regions(&self) -> impl Iterator + '_ { + self.points.as_ref().expect("use with_specific_points").rows() + } + + /// Iterate through each region that has a value in this set. + // We are passing query instability implications to the caller. + #[rustc_lint_query_instability] + #[allow(rustc::potential_query_instability)] + pub(crate) fn live_regions_unordered(&self) -> impl Iterator + '_ { + self.live_regions.as_ref().unwrap().iter().copied() } /// Records `region` as being live at the given `location`. pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) { - debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); let point = self.elements.point_from_location(location); - self.points.insert(region, point); + debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); + if let Some(points) = &mut self.points { + points.insert(region, point); + } else { + if self.elements.point_in_range(point) { + self.live_regions.as_mut().unwrap().insert(region); + } + } // When available, record the loans flowing into this region as live at the given point. if let Some(loans) = self.loans.as_mut() { @@ -101,7 +137,13 @@ impl LivenessValues { /// Records `region` as being live at all the given `points`. pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet) { debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points); - self.points.union_row(region, points); + if let Some(this) = &mut self.points { + this.union_row(region, points); + } else { + if points.iter().any(|point| self.elements.point_in_range(point)) { + self.live_regions.as_mut().unwrap().insert(region); + } + } // When available, record the loans flowing into this region as live at the given points. if let Some(loans) = self.loans.as_mut() { @@ -117,23 +159,33 @@ impl LivenessValues { /// Records `region` as being live at all the control-flow points. pub(crate) fn add_all_points(&mut self, region: RegionVid) { - self.points.insert_all_into_row(region); + if let Some(points) = &mut self.points { + points.insert_all_into_row(region); + } else { + self.live_regions.as_mut().unwrap().insert(region); + } } /// Returns whether `region` is marked live at the given `location`. pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { let point = self.elements.point_from_location(location); - self.points.row(region).is_some_and(|r| r.contains(point)) - } - - /// Returns whether `region` is marked live at any location. - pub(crate) fn is_live_anywhere(&self, region: RegionVid) -> bool { - self.live_points(region).next().is_some() + if let Some(points) = &self.points { + points.row(region).is_some_and(|r| r.contains(point)) + } else { + unreachable!( + "Should be using LivenessValues::with_specific_points to ask whether live at a location" + ) + } } /// Returns an iterator of all the points where `region` is live. fn live_points(&self, region: RegionVid) -> impl Iterator + '_ { - self.points + let Some(points) = &self.points else { + unreachable!( + "Should be using LivenessValues::with_specific_points to ask whether live at a location" + ) + }; + points .row(region) .into_iter() .flat_map(|set| set.iter()) @@ -288,7 +340,10 @@ impl RegionValues { /// elements for the region `from` from `values` and add them to /// the region `to` in `self`. pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) { - if let Some(set) = values.points.row(from) { + let Some(value_points) = &values.points else { + panic!("LivenessValues must track specific points for use in merge_liveness"); + }; + if let Some(set) = value_points.row(from) { self.points.union_row(to, set); } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 48444a6b6f70..cf28e62177fb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -141,7 +141,7 @@ pub(crate) fn type_check<'mir, 'tcx>( let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), placeholder_index_to_region: IndexVec::default(), - liveness_constraints: LivenessValues::new(elements.clone()), + liveness_constraints: LivenessValues::with_specific_points(elements.clone()), outlives_constraints: OutlivesConstraintSet::default(), member_constraints: MemberConstraintSet::default(), type_tests: Vec::default(), @@ -555,7 +555,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let all_facts = &mut None; let mut constraints = Default::default(); let mut liveness_constraints = - LivenessValues::new(Rc::new(DenseLocationMap::new(promoted_body))); + LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body))); // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { @@ -594,17 +594,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - for region in liveness_constraints.regions() { - // If the region is live at at least one location in the promoted MIR, - // then add a liveness constraint to the main MIR for this region - // at the location provided as an argument to this method - if liveness_constraints.is_live_anywhere(region) { - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_location(region, location); - } + // If the region is live at at least one location in the promoted MIR, + // then add a liveness constraint to the main MIR for this region + // at the location provided as an argument to this method + // + // add_location doesn't care about ordering so not a problem for the live regions to be + // unordered. + #[allow(rustc::potential_query_instability)] + for region in liveness_constraints.live_regions_unordered() { + self.cx + .borrowck_context + .constraints + .liveness_constraints + .add_location(region, location); } } From 078a979229b2e68570bf736c0a48be95d1ad41a7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 20 Jan 2024 02:33:49 +0000 Subject: [PATCH 286/297] Don't use ReErased to detect type test promotion failed --- compiler/rustc_borrowck/src/region_infer/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index cbf01feae06a..89b203f80a43 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -18,7 +18,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; @@ -1145,6 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } let ty = ty.fold_with(&mut OpaqueFolder { tcx }); + let mut failed = false; let ty = tcx.fold_regions(ty, |r, _depth| { let r_vid = self.to_region_vid(r); @@ -1160,15 +1161,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r)) .find(|&u_r| self.eval_equal(u_r, r_vid)) .map(|u_r| ty::Region::new_var(tcx, u_r)) - // In the case of a failure, use `ReErased`. We will eventually - // return `None` in this case. - .unwrap_or(tcx.lifetimes.re_erased) + // In case we could not find a named region to map to, + // we will return `None` below. + .unwrap_or_else(|| { + failed = true; + r + }) }); debug!("try_promote_type_test_subject: folded ty = {:?}", ty); // This will be true if we failed to promote some region. - if ty.has_erased_regions() { + if failed { return None; } From 60208a0517dcc4b1358a51b1411f0cf4c8079905 Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Sun, 3 Jul 2022 00:31:02 +0300 Subject: [PATCH 287/297] Tweak the threshold for chunked swapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to 98892 for the tests I brought in here, as it demonstrated that 3×usize is currently suboptimal. --- library/core/src/mem/mod.rs | 2 +- tests/codegen/swap-small-types.rs | 82 ++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 407954001e4c..47dab575253f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -736,7 +736,7 @@ pub const fn swap(x: &mut T, y: &mut T) { // tends to copy the whole thing to stack rather than doing it one part // at a time, so instead treat them as one-element slices and piggy-back // the slice optimizations that will split up the swaps. - if size_of::() / align_of::() > 4 { + if const { size_of::() / align_of::() > 2 } { // SAFETY: exclusive references always point to one non-overlapping // element and are non-null and properly aligned. return unsafe { ptr::swap_nonoverlapping(x, y, 1) }; diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index 27bc00bc3abb..2c6751744798 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -26,12 +26,15 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { // CHECK-LABEL: @swap_rgb48 #[no_mangle] pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) { - // FIXME: See #115212 for why this has an alloca again + // CHECK-NOT: alloca - // CHECK: alloca [3 x i16], align 2 - // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) - // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) - // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + // Whether `i8` is the best for this is unclear, but + // might as well record what's actually happening right now. + + // CHECK: load i8 + // CHECK: load i8 + // CHECK: store i8 + // CHECK: store i8 swap(x, y) } @@ -41,10 +44,39 @@ type RGBA64 = [u16; 4]; #[no_mangle] pub fn swap_rgba64(x: &mut RGBA64, y: &mut RGBA64) { // CHECK-NOT: alloca - // CHECK-DAG: %[[XVAL:.+]] = load <4 x i16>, ptr %x, align 2 - // CHECK-DAG: %[[YVAL:.+]] = load <4 x i16>, ptr %y, align 2 - // CHECK-DAG: store <4 x i16> %[[YVAL]], ptr %x, align 2 - // CHECK-DAG: store <4 x i16> %[[XVAL]], ptr %y, align 2 + // CHECK-DAG: %[[XVAL:.+]] = load i64, ptr %x, align 2 + // CHECK-DAG: %[[YVAL:.+]] = load i64, ptr %y, align 2 + // CHECK-DAG: store i64 %[[YVAL]], ptr %x, align 2 + // CHECK-DAG: store i64 %[[XVAL]], ptr %y, align 2 + swap(x, y) +} + +// CHECK-LABEL: @swap_vecs +#[no_mangle] +pub fn swap_vecs(x: &mut Vec, y: &mut Vec) { + // CHECK-NOT: alloca + // There are plenty more loads and stores than just these, + // but at least one sure better be 64-bit (for size or capacity). + // CHECK: load i64 + // CHECK: load i64 + // CHECK: store i64 + // CHECK: store i64 + // CHECK: ret void + swap(x, y) +} + +// CHECK-LABEL: @swap_slices +#[no_mangle] +pub fn swap_slices<'a>(x: &mut &'a [u32], y: &mut &'a [u32]) { + // CHECK-NOT: alloca + // CHECK: load ptr + // CHECK: load i64 + // CHECK: load ptr + // CHECK: load i64 + // CHECK: store ptr + // CHECK: store i64 + // CHECK: store ptr + // CHECK: store i64 swap(x, y) } @@ -55,9 +87,9 @@ type RGB24 = [u8; 3]; // CHECK-LABEL: @swap_rgb24_slices #[no_mangle] pub fn swap_rgb24_slices(x: &mut [RGB24], y: &mut [RGB24]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i8> -// CHECK: store <{{[0-9]+}} x i8> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i8> + // CHECK: store <{{[0-9]+}} x i8> if x.len() == y.len() { x.swap_with_slice(y); } @@ -69,9 +101,9 @@ type RGBA32 = [u8; 4]; // CHECK-LABEL: @swap_rgba32_slices #[no_mangle] pub fn swap_rgba32_slices(x: &mut [RGBA32], y: &mut [RGBA32]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i32> -// CHECK: store <{{[0-9]+}} x i32> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i32> + // CHECK: store <{{[0-9]+}} x i32> if x.len() == y.len() { x.swap_with_slice(y); } @@ -84,10 +116,24 @@ const _: () = assert!(!std::mem::size_of::().is_power_of_two()); // CHECK-LABEL: @swap_string_slices #[no_mangle] pub fn swap_string_slices(x: &mut [String], y: &mut [String]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i64> -// CHECK: store <{{[0-9]+}} x i64> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> if x.len() == y.len() { x.swap_with_slice(y); } } + +#[repr(C, packed)] +pub struct Packed { + pub first: bool, + pub second: usize, +} + +// CHECK-LABEL: @swap_packed_structs +#[no_mangle] +pub fn swap_packed_structs(x: &mut Packed, y: &mut Packed) { + // CHECK-NOT: alloca + // CHECK: ret void + swap(x, y) +} From 6237bebd349c7ba9286e2daa76eef07bd6b7c5be Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 16:46:54 +0100 Subject: [PATCH 288/297] Fix impl stripped in rustdoc HTML whereas it should not be in case the impl is implemented on a type alias --- src/librustdoc/passes/stripper.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index df955421ba48..1bea93c78421 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -56,13 +56,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { | clean::TraitItem(..) | clean::FunctionItem(..) | clean::VariantItem(..) - | clean::MethodItem(..) | clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | clean::ConstantItem(..) | clean::UnionItem(..) - | clean::AssocConstItem(..) - | clean::AssocTypeItem(..) | clean::TraitAliasItem(..) | clean::MacroItem(..) | clean::ForeignTypeItem => { @@ -80,6 +77,16 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } } + clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { + let item_id = i.item_id; + if item_id.is_local() + && !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id()) + { + debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name); + return None; + } + } + clean::StructFieldItem(..) => { if i.visibility(self.tcx) != Some(Visibility::Public) { return Some(strip_item(i)); @@ -192,16 +199,16 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { && imp.items.iter().all(|i| { let item_id = i.item_id; item_id.is_local() - && !is_item_reachable( - self.tcx, - self.is_json_output, - &self.cache.effective_visibilities, - item_id, - ) + && !self + .cache + .effective_visibilities + .is_reachable(self.tcx, item_id.expect_def_id()) }) { + debug!("ImplStripper: no public item; removing {imp:?}"); return None; } else if imp.items.is_empty() && i.doc_value().is_empty() { + debug!("ImplStripper: no item and no doc; removing {imp:?}"); return None; } } @@ -212,13 +219,13 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { && !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) { - debug!("ImplStripper: impl item for stripped type; removing"); + debug!("ImplStripper: impl item for stripped type; removing {imp:?}"); return None; } if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) && !self.should_keep_impl(&i, did) { - debug!("ImplStripper: impl item for stripped trait; removing"); + debug!("ImplStripper: impl item for stripped trait; removing {imp:?}"); return None; } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { @@ -226,7 +233,7 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { if let Some(did) = typaram.def_id(self.cache) && !self.should_keep_impl(&i, did) { - debug!("ImplStripper: stripped item in trait's generics; removing impl"); + debug!("ImplStripper: stripped item in trait's generics; removing {imp:?}"); return None; } } From 0933f48ac0a8631b3f7c9c508f38843ef10e839d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 16:47:14 +0100 Subject: [PATCH 289/297] Add regression test for #119015 and update tests --- tests/rustdoc/async-fn.rs | 18 ++++++++----- .../rustdoc/impl-on-ty-alias-issue-119015.rs | 27 +++++++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 tests/rustdoc/impl-on-ty-alias-issue-119015.rs diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs index 70bcbcb6ff44..b3c35c8c3f30 100644 --- a/tests/rustdoc/async-fn.rs +++ b/tests/rustdoc/async-fn.rs @@ -48,6 +48,8 @@ impl Foo { pub trait Pattern<'a> {} +impl Pattern<'_> for () {} + pub trait Trait {} // @has async_fn/fn.const_generics.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics(_: impl Trait)' @@ -57,18 +59,18 @@ pub async fn const_generics(_: impl Trait) {} // regression test for #63037 // @has async_fn/fn.elided.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str' -pub async fn elided(foo: &str) -> &str {} +pub async fn elided(foo: &str) -> &str { "" } // This should really be shown as written, but for implementation reasons it's difficult. // See `impl Clean for TyKind::Ref`. // @has async_fn/fn.user_elided.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str' -pub async fn user_elided(foo: &'_ str) -> &str {} +pub async fn user_elided(foo: &'_ str) -> &str { "" } // @has async_fn/fn.static_trait.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box' -pub async fn static_trait(foo: &str) -> Box {} +pub async fn static_trait(foo: &str) -> Box { Box::new(()) } // @has async_fn/fn.lifetime_for_trait.html // @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box" -pub async fn lifetime_for_trait(foo: &str) -> Box {} +pub async fn lifetime_for_trait(foo: &str) -> Box { Box::new(()) } // @has async_fn/fn.elided_in_input_trait.html // @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)" pub async fn elided_in_input_trait(t: impl Pattern<'_>) {} @@ -78,10 +80,12 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T } impl Foo { // @has async_fn/struct.Foo.html // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar ) -> impl Iterator' - pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator {} + pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator { + [0].iter() + } // taken from `tokio` as an example of a method that was particularly bad before // @has - '//*[@class="method"]' "pub async fn readable(&self) -> Result, ()>" - pub async fn readable(&self) -> Result, ()> {} + pub async fn readable(&self) -> Result, ()> { Err(()) } // @has - '//*[@class="method"]' "pub async fn mut_self(&mut self)" pub async fn mut_self(&mut self) {} } @@ -89,7 +93,7 @@ impl Foo { // test named lifetimes, just in case // @has async_fn/fn.named.html // @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str" -pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {} +pub async fn named<'a, 'b>(foo: &'a str) -> &'b str { "" } // @has async_fn/fn.named_trait.html // @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>" pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {} diff --git a/tests/rustdoc/impl-on-ty-alias-issue-119015.rs b/tests/rustdoc/impl-on-ty-alias-issue-119015.rs new file mode 100644 index 000000000000..68996deae6fd --- /dev/null +++ b/tests/rustdoc/impl-on-ty-alias-issue-119015.rs @@ -0,0 +1,27 @@ +#![crate_name = "foo"] + +// @has 'foo/index.html' +// There should be only `type A`. +// @count - '//*[@class="item-table"]//*[@class="item-name"]' 1 +// @has - '//*[@class="item-name"]/a[@href="type.A.html"]' 'A' + +mod foo { + pub struct S; +} + +use foo::S; + +pub type A = S; + +// @has 'foo/type.A.html' +// @has - '//*[@id="method.default"]/h4' 'fn default() -> Self' +impl Default for A { + fn default() -> Self { + S + } +} + +// @has - '//*[@id="method.a"]/h4' 'pub fn a(&self)' +impl A { + pub fn a(&self) {} +} From 862011e1cad78b956a2047e2a89e83ad9743c8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 16 Feb 2023 19:29:11 +0100 Subject: [PATCH 290/297] Avoid code generation for ThinVec's destructor in the query system --- Cargo.lock | 4 ++-- compiler/rustc_query_system/src/dep_graph/graph.rs | 2 +- compiler/rustc_query_system/src/query/mod.rs | 7 +++++-- compiler/rustc_query_system/src/query/plumbing.rs | 5 ++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92dd45cf5201..051b2a25716e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5353,9 +5353,9 @@ dependencies = [ [[package]] name = "thin-vec" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" +checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 1f09de0ed70c..0f57688063e0 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -891,7 +891,7 @@ impl DepGraphData { insertion for {dep_node:?}" ); - if !side_effects.is_empty() { + if side_effects.maybe_any() { qcx.dep_context().dep_graph().with_query_deserialization(|| { self.emit_side_effects(qcx, dep_node_index, side_effects) }); diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index eecbf86c173b..02b3c740b631 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -93,10 +93,13 @@ pub struct QuerySideEffects { } impl QuerySideEffects { + /// Returns true if there might be side effects. #[inline] - pub fn is_empty(&self) -> bool { + pub fn maybe_any(&self) -> bool { let QuerySideEffects { diagnostics } = self; - diagnostics.is_empty() + // Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped + // if `maybe_any` is known to be false. + diagnostics.has_capacity() } pub fn append(&mut self, other: QuerySideEffects) { let QuerySideEffects { diagnostics } = self; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3bb2cc5634fe..9158ba00901c 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -538,10 +538,9 @@ where prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - let diagnostics = diagnostics.into_inner(); - let side_effects = QuerySideEffects { diagnostics }; + let side_effects = QuerySideEffects { diagnostics: diagnostics.into_inner() }; - if std::intrinsics::unlikely(!side_effects.is_empty()) { + if std::intrinsics::unlikely(side_effects.maybe_any()) { if query.anon() { qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { From 796cdc590c0f6badb9629feb2a2b55873408cc0f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 Dec 2023 00:21:27 +0100 Subject: [PATCH 291/297] Remove Ty: Copy bound --- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_pattern_analysis/src/lib.rs | 8 ++++---- compiler/rustc_pattern_analysis/src/lints.rs | 4 ++-- compiler/rustc_pattern_analysis/src/pat.rs | 12 +++++------ compiler/rustc_pattern_analysis/src/rustc.rs | 20 +++++++++---------- .../rustc_pattern_analysis/src/usefulness.rs | 17 ++++++++-------- 6 files changed, 32 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e8ba83a5527c..693dc49c6e8f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1130,7 +1130,7 @@ fn collect_non_exhaustive_tys<'tcx>( non_exhaustive_tys.insert(pat.ty().inner()); } if let Constructor::IntRange(range) = pat.ctor() { - if cx.is_range_beyond_boundaries(range, pat.ty()) { + if cx.is_range_beyond_boundaries(range, *pat.ty()) { // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. non_exhaustive_tys.insert(pat.ty().inner()); } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 21fa8e68d82e..4fd01b5e638c 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -82,7 +82,7 @@ impl<'a, T: ?Sized> Captures<'a> for T {} /// Most of the crate is parameterized on a type that implements this trait. pub trait TypeCx: Sized + fmt::Debug { /// The type of a pattern. - type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy + type Ty: Clone + fmt::Debug; /// Errors that can abort analysis. type Error: fmt::Debug; /// The index of an enum variant. @@ -97,16 +97,16 @@ pub trait TypeCx: Sized + fmt::Debug { fn is_exhaustive_patterns_feature_on(&self) -> bool; /// The number of fields for this constructor. - fn ctor_arity(&self, ctor: &Constructor, ty: Self::Ty) -> usize; + fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize; /// The types of the fields for this constructor. The result must have a length of /// `ctor_arity()`. - fn ctor_sub_tys(&self, ctor: &Constructor, ty: Self::Ty) -> &[Self::Ty]; + fn ctor_sub_tys(&self, ctor: &Constructor, ty: &Self::Ty) -> &[Self::Ty]; /// The set of all the constructors for `ty`. /// /// This must follow the invariants of `ConstructorSet` - fn ctors_for_ty(&self, ty: Self::Ty) -> Result, Self::Error>; + fn ctors_for_ty(&self, ty: &Self::Ty) -> Result, Self::Error>; /// Best-effort `Debug` implementation. fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result; diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index d9dbd8250efe..f9f065fbe8b1 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -46,7 +46,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { } fn head_ty(&self) -> Option> { - self.patterns.first().map(|pat| pat.ty()) + self.patterns.first().map(|pat| *pat.ty()) } /// Do constructor splitting on the constructors of the column. @@ -101,7 +101,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( let Some(ty) = column.head_ty() else { return Ok(Vec::new()); }; - let pcx = &PlaceCtxt::new_dummy(cx, ty); + let pcx = &PlaceCtxt::new_dummy(cx, &ty); let set = column.analyze_ctors(pcx)?; if set.present.is_empty() { diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 75fe59edf88f..8cd0ecb073c2 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -54,8 +54,8 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { pub fn ctor(&self) -> &Constructor { &self.ctor } - pub fn ty(&self) -> Cx::Ty { - self.ty + pub fn ty(&self) -> &Cx::Ty { + &self.ty } /// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that /// does not correspond to a user-supplied pattern. @@ -242,15 +242,15 @@ impl WitnessPat { /// `Some(_)`. pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor) -> Self { let field_tys = pcx.ctor_sub_tys(&ctor); - let fields = field_tys.iter().map(|ty| Self::wildcard(*ty)).collect(); - Self::new(ctor, fields, pcx.ty) + let fields = field_tys.iter().cloned().map(|ty| Self::wildcard(ty)).collect(); + Self::new(ctor, fields, pcx.ty.clone()) } pub fn ctor(&self) -> &Constructor { &self.ctor } - pub fn ty(&self) -> Cx::Ty { - self.ty + pub fn ty(&self) -> &Cx::Ty { + &self.ty } pub fn iter_fields(&self) -> impl Iterator> { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 87e70d68c1b4..27b258024271 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -766,7 +766,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p))); let kind = match pat.ctor() { Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) }, - IntRange(range) => return self.hoist_pat_range(range, pat.ty()), + IntRange(range) => return self.hoist_pat_range(range, *pat.ty()), Struct | Variant(_) | UnionField => match pat.ty().kind() { ty::Tuple(..) => PatKind::Leaf { subpatterns: subpatterns @@ -785,7 +785,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); let variant = &adt_def.variant(variant_index); let subpatterns = cx - .list_variant_nonhidden_fields(pat.ty(), variant) + .list_variant_nonhidden_fields(*pat.ty(), variant) .zip(subpatterns) .map(|((field, _ty), pattern)| FieldPat { field, pattern }) .collect(); @@ -796,7 +796,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { PatKind::Leaf { subpatterns } } } - _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), pat.ty()), + _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()), }, // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should // be careful to reconstruct the correct constant pattern here. However a string @@ -961,21 +961,21 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { self.tcx.features().exhaustive_patterns } - fn ctor_arity(&self, ctor: &crate::constructor::Constructor, ty: Self::Ty) -> usize { - self.ctor_arity(ctor, ty) + fn ctor_arity(&self, ctor: &crate::constructor::Constructor, ty: &Self::Ty) -> usize { + self.ctor_arity(ctor, *ty) } fn ctor_sub_tys( &self, ctor: &crate::constructor::Constructor, - ty: Self::Ty, + ty: &Self::Ty, ) -> &[Self::Ty] { - self.ctor_sub_tys(ctor, ty) + self.ctor_sub_tys(ctor, *ty) } fn ctors_for_ty( &self, - ty: Self::Ty, + ty: &Self::Ty, ) -> Result, Self::Error> { - self.ctors_for_ty(ty) + self.ctors_for_ty(*ty) } fn debug_pat( @@ -994,7 +994,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { overlaps_on: IntRange, overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>], ) { - let overlap_as_pat = self.hoist_pat_range(&overlaps_on, pat.ty()); + let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with .iter() .map(|pat| pat.data().unwrap().span) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index dac354a1c523..d7852a2b2cbf 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -736,13 +736,14 @@ pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { #[derivative(Debug = "ignore")] pub(crate) mcx: MatchCtxt<'a, Cx>, /// Type of the place under investigation. - pub(crate) ty: Cx::Ty, + #[derivative(Clone(clone_with = "Clone::clone"))] // See rust-derivative#90 + pub(crate) ty: &'a Cx::Ty, } impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { /// A `PlaceCtxt` when code other than `is_useful` needs one. #[cfg_attr(not(feature = "rustc"), allow(dead_code))] - pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: Cx::Ty) -> Self { + pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self { PlaceCtxt { mcx, ty } } @@ -1023,8 +1024,8 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { matrix } - fn head_ty(&self) -> Option { - self.place_ty.first().copied() + fn head_ty(&self) -> Option<&Cx::Ty> { + self.place_ty.first() } fn column_count(&self) -> usize { self.place_ty.len() @@ -1058,7 +1059,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { let ctor_sub_tys = pcx.ctor_sub_tys(ctor); let arity = ctor_sub_tys.len(); let specialized_place_ty = - ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).copied().collect(); + ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).cloned().collect(); let ctor_sub_validity = self.place_validity[0].specialize(ctor); let specialized_place_validity = std::iter::repeat(ctor_sub_validity) .take(arity) @@ -1214,7 +1215,7 @@ impl WitnessStack { let len = self.0.len(); let arity = ctor.arity(pcx); let fields = self.0.drain((len - arity)..).rev().collect(); - let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty); + let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone()); self.0.push(pat); } } @@ -1410,7 +1411,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( return Ok(WitnessMatrix::empty()); } - let Some(ty) = matrix.head_ty() else { + let Some(ty) = matrix.head_ty().cloned() else { // The base case: there are no columns in the matrix. We are morally pattern-matching on (). // A row is useful iff it has no (unguarded) rows above it. let mut useful = true; // Whether the next row is useful. @@ -1431,7 +1432,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { mcx, ty }; + let pcx = &PlaceCtxt { mcx, ty: &ty }; let ctors_for_ty = pcx.ctors_for_ty()?; // Whether the place/column we are inspecting is known to contain valid data. From 0e96840e7eeaabd3cced2319855893ec7e2a503d Mon Sep 17 00:00:00 2001 From: sunrosa <79175772+sunrosa@users.noreply.github.com> Date: Sat, 20 Jan 2024 18:27:55 +0000 Subject: [PATCH 292/297] Spelling fix "It's" expands to "it is". "Its" is the possessive form. --- library/core/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/error.rs b/library/core/src/error.rs index f1a7ad935480..ded17e69bd9c 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -415,7 +415,7 @@ where // Request and its methods /////////////////////////////////////////////////////////////////////////////// -/// `Request` supports generic, type-driven access to data. It's use is currently restricted to the +/// `Request` supports generic, type-driven access to data. Its use is currently restricted to the /// standard library in cases where trait authors wish to allow trait implementors to share generic /// information across trait boundaries. The motivating and prototypical use case is /// `core::error::Error` which would otherwise require a method per concrete type (eg. From 606eeb84ad780a1cfe35e4d1265d7be4a412389e Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 10 Dec 2023 23:29:11 +0100 Subject: [PATCH 293/297] Use bool instead of PartiolOrd in is_sorted_by --- .../rustc_monomorphize/src/partitioning.rs | 4 +-- library/core/src/iter/traits/iterator.rs | 26 +++++++++---------- library/core/src/slice/iter.rs | 3 +-- library/core/src/slice/mod.rs | 25 +++++++++++++----- library/core/tests/iter/traits/iterator.rs | 3 +-- library/core/tests/slice.rs | 2 +- 6 files changed, 37 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index c2b307910e42..547f9f93109f 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -182,7 +182,7 @@ where } // Ensure CGUs are sorted by name, so that we get deterministic results. - if !codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))) { + if !codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()) { let mut names = String::new(); for cgu in codegen_units.iter() { names += &format!("- {}\n", cgu.name()); @@ -311,7 +311,7 @@ fn merge_codegen_units<'tcx>( assert!(cx.tcx.sess.codegen_units().as_usize() >= 1); // A sorted order here ensures merging is deterministic. - assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str())))); + assert!(codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str())); // This map keeps track of what got merged into what. let mut cgu_contents: FxHashMap> = diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 8e2c887a161e..e203533e08ed 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4026,42 +4026,42 @@ pub trait Iterator { Self: Sized, Self::Item: PartialOrd, { - self.is_sorted_by(PartialOrd::partial_cmp) + self.is_sorted_by(|a, b| a <= b) } /// Checks if the elements of this iterator are sorted using the given comparator function. /// /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare` - /// function to determine the ordering of two elements. Apart from that, it's equivalent to - /// [`is_sorted`]; see its documentation for more information. + /// function to determine whether two elements are to be considered in sorted order. /// /// # Examples /// /// ``` /// #![feature(is_sorted)] /// - /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!(std::iter::empty::().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// ``` + /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a <= b)); + /// assert!(![1, 2, 2, 9].iter().is_sorted_by(|a, b| a < b)); /// - /// [`is_sorted`]: Iterator::is_sorted + /// assert!([0].iter().is_sorted_by(|a, b| true)); + /// assert!([0].iter().is_sorted_by(|a, b| false)); + /// + /// assert!(std::iter::empty::().is_sorted_by(|a, b| false)); + /// assert!(std::iter::empty::().is_sorted_by(|a, b| true)); + /// ``` #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] #[rustc_do_not_const_check] fn is_sorted_by(mut self, compare: F) -> bool where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Option, + F: FnMut(&Self::Item, &Self::Item) -> bool, { #[inline] fn check<'a, T>( last: &'a mut T, - mut compare: impl FnMut(&T, &T) -> Option + 'a, + mut compare: impl FnMut(&T, &T) -> bool + 'a, ) -> impl FnMut(T) -> bool + 'a { move |curr| { - if let Some(Ordering::Greater) | None = compare(&last, &curr) { + if !compare(&last, &curr) { return false; } *last = curr; diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index fc54ea237709..be67bfc7aa44 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -4,7 +4,6 @@ mod macros; use crate::cmp; -use crate::cmp::Ordering; use crate::fmt; use crate::intrinsics::assume; use crate::iter::{ @@ -133,7 +132,7 @@ iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, { fn is_sorted_by(self, mut compare: F) -> bool where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Option, + F: FnMut(&Self::Item, &Self::Item) -> bool, { self.as_slice().is_sorted_by(|a, b| compare(&a, &b)) } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b14d9712794b..e485e5f05251 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4103,23 +4103,36 @@ impl [T] { where T: PartialOrd, { - self.is_sorted_by(|a, b| a.partial_cmp(b)) + self.is_sorted_by(|a, b| a <= b) } /// Checks if the elements of this slice are sorted using the given comparator function. /// /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare` - /// function to determine the ordering of two elements. Apart from that, it's equivalent to - /// [`is_sorted`]; see its documentation for more information. + /// function to determine whether two elements are to be considered in sorted order. /// - /// [`is_sorted`]: slice::is_sorted + /// # Examples + /// + /// ``` + /// #![feature(is_sorted)] + /// + /// assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b)); + /// assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b)); + /// + /// assert!([0].is_sorted_by(|a, b| true)); + /// assert!([0].is_sorted_by(|a, b| false)); + /// + /// let empty: [i32; 0] = []; + /// assert!(empty.is_sorted_by(|a, b| false)); + /// assert!(empty.is_sorted_by(|a, b| true)); + /// ``` #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] #[must_use] pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool where - F: FnMut(&'a T, &'a T) -> Option, + F: FnMut(&'a T, &'a T) -> bool, { - self.array_windows().all(|[a, b]| compare(a, b).map_or(false, Ordering::is_le)) + self.array_windows().all(|[a, b]| compare(a, b)) } /// Checks if the elements of this slice are sorted using the given key extraction function. diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 995bbf0e2615..e2b31658d0fb 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -1,4 +1,3 @@ -use core::cmp::Ordering; use core::num::NonZeroUsize; /// A wrapper struct that implements `Eq` and `Ord` based on the wrapped @@ -402,7 +401,7 @@ fn test_is_sorted() { // Tests for is_sorted_by assert!(![6, 2, 8, 5, 1, -60, 1337].iter().is_sorted()); - assert!([6, 2, 8, 5, 1, -60, 1337].iter().is_sorted_by(|_, _| Some(Ordering::Less))); + assert!([6, 2, 8, 5, 1, -60, 1337].iter().is_sorted_by(|_, _| true)); // Tests for is_sorted_by_key assert!([-2, -1, 0, 3].iter().is_sorted()); diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 33a303398567..6a6eea3c0725 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2307,7 +2307,7 @@ fn test_is_sorted() { // Tests for is_sorted_by assert!(![6, 2, 8, 5, 1, -60, 1337].is_sorted()); - assert!([6, 2, 8, 5, 1, -60, 1337].is_sorted_by(|_, _| Some(Ordering::Less))); + assert!([6, 2, 8, 5, 1, -60, 1337].is_sorted_by(|_, _| true)); // Tests for is_sorted_by_key assert!([-2, -1, 0, 3].is_sorted()); From 384b2ab37529ba0ad07ea8271baf0f212bab2e5a Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sun, 21 Jan 2024 05:39:01 +0000 Subject: [PATCH 294/297] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ad3a534b7ed0..aa05d224c21f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3deb9bbf84f6431ebcbb7cbdbe3d89bc2636bc1b +867d39cdf625e4db4b381faff993346582e598b4 From bdfc64ac984e892f6061deebaee5a9301b8d271f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 21 Jan 2024 12:18:48 +1100 Subject: [PATCH 295/297] coverage: Add a test that uses `#[bench]` --- tests/coverage/bench.cov-map | 16 ++++++++++++++++ tests/coverage/bench.coverage | 9 +++++++++ tests/coverage/bench.rs | 8 ++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/coverage/bench.cov-map create mode 100644 tests/coverage/bench.coverage create mode 100644 tests/coverage/bench.rs diff --git a/tests/coverage/bench.cov-map b/tests/coverage/bench.cov-map new file mode 100644 index 000000000000..7cdb1b641bf3 --- /dev/null +++ b/tests/coverage/bench.cov-map @@ -0,0 +1,16 @@ +Function name: bench::my_bench +Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 00, 27] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 39) + +Function name: bench::my_bench::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 09] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 9) + diff --git a/tests/coverage/bench.coverage b/tests/coverage/bench.coverage new file mode 100644 index 000000000000..4642d92cc191 --- /dev/null +++ b/tests/coverage/bench.coverage @@ -0,0 +1,9 @@ + LL| |#![feature(test)] + LL| |// edition: 2021 + LL| |// compile-flags: --test + LL| | + LL| |extern crate test; + LL| | + LL| 1|#[bench] + LL| 1|fn my_bench(_b: &mut test::Bencher) {} + diff --git a/tests/coverage/bench.rs b/tests/coverage/bench.rs new file mode 100644 index 000000000000..2dcd7355b2f7 --- /dev/null +++ b/tests/coverage/bench.rs @@ -0,0 +1,8 @@ +#![feature(test)] +// edition: 2021 +// compile-flags: --test + +extern crate test; + +#[bench] +fn my_bench(_b: &mut test::Bencher) {} From 6d7e80c5bc3cc3b176834322afc50dc8dd100599 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 21 Jan 2024 11:26:28 +1100 Subject: [PATCH 296/297] Add `#[coverage(off)]` to closures introduced by `#[test]`/`#[bench]` --- compiler/rustc_builtin_macros/src/lib.rs | 1 + compiler/rustc_builtin_macros/src/test.rs | 21 +++++++++++++++++---- library/core/src/macros/mod.rs | 4 ++-- tests/coverage/bench.cov-map | 8 -------- tests/coverage/bench.coverage | 2 +- tests/coverage/test_harness.cov-map | 8 -------- tests/coverage/test_harness.coverage | 2 +- tests/pretty/tests-are-sorted.pp | 9 ++++++--- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index f60b73fbe9b1..3e9b06a5b054 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 4d44e340ae14..0631f796894b 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -9,6 +9,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, Level}; use rustc_expand::base::*; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; +use std::assert_matches::assert_matches; use std::iter; use thin_vec::{thin_vec, ThinVec}; @@ -182,6 +183,16 @@ pub fn expand_test_or_bench( // creates $name: $expr let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr); + // Adds `#[coverage(off)]` to a closure, so it won't be instrumented in + // `-Cinstrument-coverage` builds. + // This requires `#[allow_internal_unstable(coverage_attribute)]` on the + // corresponding macro declaration in `core::macros`. + let coverage_off = |mut expr: P| { + assert_matches!(expr.kind, ast::ExprKind::Closure(_)); + expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp)); + expr + }; + let test_fn = if is_bench { // A simple ident for a lambda let b = Ident::from_str_and_span("b", attr_sp); @@ -190,8 +201,9 @@ pub fn expand_test_or_bench( sp, cx.expr_path(test_path("StaticBenchFn")), thin_vec![ + // #[coverage(off)] // |b| self::test::assert_test_result( - cx.lambda1( + coverage_off(cx.lambda1( sp, cx.expr_call( sp, @@ -206,7 +218,7 @@ pub fn expand_test_or_bench( ], ), b, - ), // ) + )), // ) ], ) } else { @@ -214,8 +226,9 @@ pub fn expand_test_or_bench( sp, cx.expr_path(test_path("StaticTestFn")), thin_vec![ + // #[coverage(off)] // || { - cx.lambda0( + coverage_off(cx.lambda0( sp, // test::assert_test_result( cx.expr_call( @@ -230,7 +243,7 @@ pub fn expand_test_or_bench( ), // ) ], ), // } - ), // ) + )), // ) ], ) }; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index a2437feeeb9c..9bbaf62a5caa 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1596,7 +1596,7 @@ pub(crate) mod builtin { /// /// [the reference]: ../../../reference/attributes/testing.html#the-test-attribute #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(test, rustc_attrs)] + #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] #[rustc_builtin_macro] pub macro test($item:item) { /* compiler built-in */ @@ -1609,7 +1609,7 @@ pub(crate) mod builtin { soft, reason = "`bench` is a part of custom test frameworks which are unstable" )] - #[allow_internal_unstable(test, rustc_attrs)] + #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] #[rustc_builtin_macro] pub macro bench($item:item) { /* compiler built-in */ diff --git a/tests/coverage/bench.cov-map b/tests/coverage/bench.cov-map index 7cdb1b641bf3..aa702a486818 100644 --- a/tests/coverage/bench.cov-map +++ b/tests/coverage/bench.cov-map @@ -6,11 +6,3 @@ Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 0, 39) -Function name: bench::my_bench::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 09] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 9) - diff --git a/tests/coverage/bench.coverage b/tests/coverage/bench.coverage index 4642d92cc191..64945dc64150 100644 --- a/tests/coverage/bench.coverage +++ b/tests/coverage/bench.coverage @@ -4,6 +4,6 @@ LL| | LL| |extern crate test; LL| | - LL| 1|#[bench] + LL| |#[bench] LL| 1|fn my_bench(_b: &mut test::Bencher) {} diff --git a/tests/coverage/test_harness.cov-map b/tests/coverage/test_harness.cov-map index 6940d2e28243..f75328b11c9a 100644 --- a/tests/coverage/test_harness.cov-map +++ b/tests/coverage/test_harness.cov-map @@ -6,14 +6,6 @@ Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 0, 16) -Function name: test_harness::my_test::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 08] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 8) - Function name: test_harness::unused (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f] Number of files: 1 diff --git a/tests/coverage/test_harness.coverage b/tests/coverage/test_harness.coverage index ff6009f6fce4..c3f660506fbd 100644 --- a/tests/coverage/test_harness.coverage +++ b/tests/coverage/test_harness.coverage @@ -6,6 +6,6 @@ LL| |#[allow(dead_code)] LL| 0|fn unused() {} LL| | - LL| 1|#[test] + LL| |#[test] LL| 1|fn my_test() {} diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index fd9386be8f3c..fbdad0c323f3 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -28,7 +28,8 @@ pub const m_test: test::TestDescAndFn = should_panic: test::ShouldPanic::No, test_type: test::TestType::Unknown, }, - testfn: test::StaticTestFn(|| test::assert_test_result(m_test())), + testfn: test::StaticTestFn(#[coverage(off)] || + test::assert_test_result(m_test())), }; fn m_test() {} @@ -51,7 +52,8 @@ pub const z_test: test::TestDescAndFn = should_panic: test::ShouldPanic::No, test_type: test::TestType::Unknown, }, - testfn: test::StaticTestFn(|| test::assert_test_result(z_test())), + testfn: test::StaticTestFn(#[coverage(off)] || + test::assert_test_result(z_test())), }; #[ignore = "not yet implemented"] fn z_test() {} @@ -75,7 +77,8 @@ pub const a_test: test::TestDescAndFn = should_panic: test::ShouldPanic::No, test_type: test::TestType::Unknown, }, - testfn: test::StaticTestFn(|| test::assert_test_result(a_test())), + testfn: test::StaticTestFn(#[coverage(off)] || + test::assert_test_result(a_test())), }; fn a_test() {} #[rustc_main] From 7092c660077d185df375eaf07d649be2b49018d0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 21 Jan 2024 13:11:00 +0000 Subject: [PATCH 297/297] update lockfile --- src/tools/miri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 6cd22a915189..8cd996d85645 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -486,9 +486,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "measureme" -version = "10.1.2" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe" +checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" dependencies = [ "log", "memmap2",