From 6c87448b57890eabd11103fcb2ab8f5e687a02cc Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 21 Jun 2023 20:49:18 +0200 Subject: 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 64938745a4a..71ec9fed2fe 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 ef8e4d098ed..02867789b79 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 2568aaf34f3..f3992b500ad 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 b1fa4f92117..e38234eae49 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 31d02a4da6e..2563f27d169 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 f3311f76a7f..324bf5c05af 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 f5f2dd04778..3d3f8ac10c6 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"#); +} -- cgit 1.4.1-3-g733a5 From 9ced08956902e7aeb6fd52c05fbac935de11c699 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sat, 29 Jul 2023 19:42:22 -0700 Subject: [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 bc8a6b9eac0..332ad8af33b 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] } -- cgit 1.4.1-3-g733a5 From 55020c6f2f4aeac24e24d9bf4a623415c83c4608 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 19:59:26 -0500 Subject: 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 45080eda2ce..970b1cb4f1d 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]) })) } } -- cgit 1.4.1-3-g733a5 From 6e8ec852f77f1ee21eaa6bdfffd63d5ae69d9002 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 20:22:53 -0500 Subject: 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 970b1cb4f1d..7c07a86e2dd 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]>()) }) } } -- cgit 1.4.1-3-g733a5 From 97bc528877b698df2f61dd743b1a155ca3f5eead Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sun, 5 Nov 2023 17:35:37 -0600 Subject: 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 332ad8af33b..1c6e227cec4 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] } -- cgit 1.4.1-3-g733a5 From 27f419bc7dfb777f984595ffbc800331f591ce66 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 22 Sep 2023 16:42:08 -0700 Subject: 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 921a0fb6a9f..44ba6c58c67 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 fd01f1b2610..8b3f742bf91 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 2a0b31404f0..96de7673c6f 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 00000000000..b941fdb212a --- /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") +} -- cgit 1.4.1-3-g733a5 From fb349a2b7a753640e3eb577554641f8c75a6df49 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 22 Sep 2023 20:34:54 -0700 Subject: 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 11a53aaf122..2d8dbbe1f50 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. /// -- cgit 1.4.1-3-g733a5 From 8c7a5b0338f3f168c8b5c8447f132e8983c26105 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 23 Sep 2023 11:50:02 -0700 Subject: 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 8b3f742bf91..b9f794431fb 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 2d8dbbe1f50..8d971385605 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; -- cgit 1.4.1-3-g733a5 From a43dc2b67cee8e56cbe73d36ec0a99c6b0f2dd59 Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Mon, 27 Nov 2023 12:49:09 +0530 Subject: 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 b419a738fbe..e809273c9ed 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, -- cgit 1.4.1-3-g733a5 From 6d17169104575315c7801ec7bc55dd3cb932fde8 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Tue, 28 Nov 2023 08:34:55 -0800 Subject: 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 b9f794431fb..451a2e14fe9 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 b941fdb212a..203037ffb43 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 8d971385605..9915ce385d9 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 /// -- cgit 1.4.1-3-g733a5 From 01337bf1fda37e8fde134454394e27e2ae719a24 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 20:38:30 -0500 Subject: 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 ebd4a8c05fe..4f6eef4ef0d 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 7c07a86e2dd..9512d45740f 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 df7b34ce73b..15e58a4e53f 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 666452ead3f..8bcb7ad1386 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][..]; -- cgit 1.4.1-3-g733a5 From 6318cbbe49f916c33bc3f4e5febe6cf0fcb7095a Mon Sep 17 00:00:00 2001 From: Benoît du Garreau Date: Thu, 9 Nov 2023 16:21:03 +0100 Subject: `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 39e94902cfe..b83c4d89c1e 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 8bc59608290..ea9239f0c47 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)] -- cgit 1.4.1-3-g733a5 From 7d369f98301047ca66d761549b53bde33b45ab7d Mon Sep 17 00:00:00 2001 From: Benoît du Garreau Date: Mon, 27 Nov 2023 10:30:12 +0100 Subject: 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 b83c4d89c1e..fc27b6a67bf 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 ea9239f0c47..dcb2fa0f771 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, -- cgit 1.4.1-3-g733a5 From 8bc123e321b82359c80ce50dae62e13db39c96cc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Feb 2022 15:09:37 +0100 Subject: 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 abc27bcdf07..6a48b9367b8 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 5eba1d0609f..fcf77783024 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 b898eb5d381..22fe5d8b0cf 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, -- cgit 1.4.1-3-g733a5 From d1dd589a1df3d0e2b392a1bd4034efa43326a4c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Feb 2022 15:35:10 +0100 Subject: 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 6a48b9367b8..71ad9fc243c 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 fcf77783024..4dd176b3a69 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] -- cgit 1.4.1-3-g733a5 From 13b2156c68aa8e6565923dfad336461a393b75fa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Feb 2022 15:57:01 +0100 Subject: Update rustdoc headings tests --- tests/rustdoc-gui/docblock-details.goml | 2 +- tests/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 8e6d2ba824f..4b8f5b54fac 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 38a4954fc13..1388af7df4b 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 599c429a6e1..8f477028619 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 791d3547c9f..151a42a9c9e 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 -- cgit 1.4.1-3-g733a5 From a4e5e074ac0dfb478c362af2dc37a9e333d86547 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Nov 2023 15:40:31 +0100 Subject: 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 22fe5d8b0cf..52af572f770 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; -- cgit 1.4.1-3-g733a5 From 42fcba7a6731ec2a0fc6e75383fbd35dd75db41d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Nov 2023 16:40:48 +0100 Subject: 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 19185818f40..80d11c9c849 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 00000000000..f568caa3b07 --- /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 00000000000..c5bee1a7975 --- /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' -- cgit 1.4.1-3-g733a5 From d7c5358a57ec81449f52479f83e2de32f01d696e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 5 Dec 2023 16:10:23 +0100 Subject: 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 131b1d608e6..b9a60a3fbdd 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(), -- cgit 1.4.1-3-g733a5 From bf4a20cfca442f211932e181a27baa070e3062cd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 5 Dec 2023 16:45:21 +0100 Subject: 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 e076c1b92e6..7c9be214d13 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 b9a60a3fbdd..a50e59de0fb 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()); -- cgit 1.4.1-3-g733a5 From 17edbe7cad199e04345db5e810970576e8dc6f40 Mon Sep 17 00:00:00 2001 From: David Thomas Date: Sun, 10 Dec 2023 11:36:56 +0000 Subject: 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 7fcf2ee358c..34ac0953050 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 } -- cgit 1.4.1-3-g733a5 From 605504c5bf5b02026dee02bfe682ff9adf3e22cd Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Sat, 19 Jun 2021 16:41:38 +0200 Subject: 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 8bf15c736c3..65debde100a 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 7530fc08487..12ef678735d 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)); } -- cgit 1.4.1-3-g733a5 From 1c5b2ce67cb8d698350b93143b8de342805145cc Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Tue, 19 Dec 2023 22:08:48 +0100 Subject: 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 5f1f41e6865..ad8c70c6a3c 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); //! ``` -- cgit 1.4.1-3-g733a5 From 7fee0881db85600a4a31442555a305d215064283 Mon Sep 17 00:00:00 2001 From: Yu Zeng Date: Fri, 29 Dec 2023 18:32:37 +0800 Subject: complete merge_nested_if with bugs. --- crates/ide-assists/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 00000000000..af99d6fdef0 --- /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 1e4d1c94f5b..1eb4903ab20 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 da5822bba9c..79958a2292f 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( -- cgit 1.4.1-3-g733a5 From edb9ad21bd8f0a692d100f6d3282e2b442fabc64 Mon Sep 17 00:00:00 2001 From: l1nxy Date: Mon, 1 Jan 2024 21:53:57 +0800 Subject: 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 af99d6fdef0..39db42faaea 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(); } }", -- cgit 1.4.1-3-g733a5 From b6a14ce5b8d1081ea330a0b85733fc6b646dfa33 Mon Sep 17 00:00:00 2001 From: l1nxy Date: Mon, 1 Jan 2024 22:11:45 +0800 Subject: fix doc test. --- crates/ide-assists/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 39db42faaea..206bc3e08be 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 79958a2292f..d8b3b32a1ab 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 } +} +"#####, ) } -- cgit 1.4.1-3-g733a5 From a3be52cbc0ff88f2e06e117b8e0843531832a37d Mon Sep 17 00:00:00 2001 From: l1nxy Date: Mon, 1 Jan 2024 22:31:04 +0800 Subject: 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 206bc3e08be..5742f60a1e3 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()?; -- cgit 1.4.1-3-g733a5 From 161d3055d192e36b87bfb0abd2c66f1356ed8681 Mon Sep 17 00:00:00 2001 From: l1nxy Date: Wed, 3 Jan 2024 09:48:49 +0800 Subject: 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 5742f60a1e3..2f3136f027b 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 } } }", + ) + } } -- cgit 1.4.1-3-g733a5 From b5c9982c0a0888bfc21e3a2c5c11575ecf2d1fb8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 3 Jan 2024 14:56:10 -0700 Subject: 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 +++- .../rustdoc/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 f08466baf8b..c82323ddc6a 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 70a2265c806..44afaf2e903 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 c1bf9ceeac1..ed955dcd770 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 7578d49daa5..7782e148fd9 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 a5394c7d92a..16c1705eb00 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 767d09d8558..9c4ed841f79 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 1311b4721e2..aec74f493d4 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 7004d18dc66..96ebd888eb5 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 8cfc4827a7f..d0ce9c34f51 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 19994475de2..79492b4fa76 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 13bedd5dbb0..0663ed5fc81 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 04664805a88..30c81e79601 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 8000ce73bd4..12d3e3d7f94 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 832140e061b..7c2edd01a60 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 dc1eb304c3d..968ae035043 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 4811f363bc9..39acee36d88 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 a886eb0de24..00be0042fb0 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 f6c7f9a3d08..b7d86a1c843 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 d3c2070d915..e9be1ff854e 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 941cb3ce1ca..c07aba628c9 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 { -- cgit 1.4.1-3-g733a5 From 35830fe218f245ef4a82199b8ee371fa89a52721 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 3 Jan 2024 15:30:09 -0700 Subject: rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 5) --- tests/rustdoc-ui/ice-blanket-impl-52873.rs | 174 +++++++++++++++++++++ .../rustdoc-ui/ice-blanket-impl-selection-55001.rs | 34 ++++ .../auto-trait-bounds-by-associated-type-50159.rs | 23 +++ .../auto-trait-bounds-inference-variables-54705.rs | 30 ++++ tests/rustdoc/auto-trait-bounds-where-51236.rs | 17 ++ tests/rustdoc/auto-trait-negative-impl-55321.rs | 21 +++ tests/rustdoc/auxiliary/issue-46727.rs | 7 - tests/rustdoc/blank-line-in-doc-block-47197.rs | 11 ++ tests/rustdoc/demo-allocator-54478.rs | 45 ++++++ tests/rustdoc/deref-mut-35169-2.rs | 43 +++++ tests/rustdoc/deref-mut-35169.rs | 38 +++++ tests/rustdoc/doc-attr-comment-mix-42760.rs | 18 +++ .../doctest-escape-boring-41783.codeblock.html | 5 + .../rustdoc/doctest/doctest-escape-boring-41783.rs | 22 +++ tests/rustdoc/enum-variant-reexport-35488.rs | 16 ++ tests/rustdoc/impl-blanket-53689.rs | 17 ++ tests/rustdoc/impl-trait-43869.rs | 75 +++++++++ .../rustdoc/inline_cross/auxiliary/issue-46727.rs | 7 + tests/rustdoc/inline_cross/const-eval-46727.rs | 10 ++ .../module-scope-name-resolution-55364.rs | 89 +++++++++++ tests/rustdoc/issue-35169-2.rs | 43 ----- tests/rustdoc/issue-35169.rs | 38 ----- tests/rustdoc/issue-35488.rs | 16 -- tests/rustdoc/issue-41783.codeblock.html | 5 - tests/rustdoc/issue-41783.rs | 22 --- tests/rustdoc/issue-42760.rs | 18 --- tests/rustdoc/issue-43869.rs | 75 --------- tests/rustdoc/issue-46377.rs | 6 - tests/rustdoc/issue-46380-2.rs | 12 -- tests/rustdoc/issue-46727.rs | 10 -- .../rustdoc/issue-47197-blank-line-in-doc-block.rs | 11 -- tests/rustdoc/issue-50159.rs | 23 --- tests/rustdoc/issue-51236.rs | 17 -- tests/rustdoc/issue-52873.rs | 174 --------------------- tests/rustdoc/issue-53689.rs | 17 -- tests/rustdoc/issue-53812.rs | 23 --- tests/rustdoc/issue-54478-demo-allocator.rs | 45 ------ tests/rustdoc/issue-54705.rs | 30 ---- tests/rustdoc/issue-55001.rs | 34 ---- tests/rustdoc/issue-55321.rs | 21 --- tests/rustdoc/issue-55364.rs | 89 ----------- .../public-impl-mention-private-generic-46380-2.rs | 12 ++ tests/rustdoc/sort-53812.rs | 23 +++ tests/rustdoc/summary-header-46377.rs | 6 + 44 files changed, 736 insertions(+), 736 deletions(-) create mode 100644 tests/rustdoc-ui/ice-blanket-impl-52873.rs create mode 100644 tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs create mode 100644 tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs create mode 100644 tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs create mode 100644 tests/rustdoc/auto-trait-bounds-where-51236.rs create mode 100644 tests/rustdoc/auto-trait-negative-impl-55321.rs delete mode 100644 tests/rustdoc/auxiliary/issue-46727.rs create mode 100644 tests/rustdoc/blank-line-in-doc-block-47197.rs create mode 100644 tests/rustdoc/demo-allocator-54478.rs create mode 100644 tests/rustdoc/deref-mut-35169-2.rs create mode 100644 tests/rustdoc/deref-mut-35169.rs create mode 100644 tests/rustdoc/doc-attr-comment-mix-42760.rs create mode 100644 tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html create mode 100644 tests/rustdoc/doctest/doctest-escape-boring-41783.rs create mode 100644 tests/rustdoc/enum-variant-reexport-35488.rs create mode 100644 tests/rustdoc/impl-blanket-53689.rs create mode 100644 tests/rustdoc/impl-trait-43869.rs create mode 100644 tests/rustdoc/inline_cross/auxiliary/issue-46727.rs create mode 100644 tests/rustdoc/inline_cross/const-eval-46727.rs create mode 100644 tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs delete mode 100644 tests/rustdoc/issue-35169-2.rs delete mode 100644 tests/rustdoc/issue-35169.rs delete mode 100644 tests/rustdoc/issue-35488.rs delete mode 100644 tests/rustdoc/issue-41783.codeblock.html delete mode 100644 tests/rustdoc/issue-41783.rs delete mode 100644 tests/rustdoc/issue-42760.rs delete mode 100644 tests/rustdoc/issue-43869.rs delete mode 100644 tests/rustdoc/issue-46377.rs delete mode 100644 tests/rustdoc/issue-46380-2.rs delete mode 100644 tests/rustdoc/issue-46727.rs delete mode 100644 tests/rustdoc/issue-47197-blank-line-in-doc-block.rs delete mode 100644 tests/rustdoc/issue-50159.rs delete mode 100644 tests/rustdoc/issue-51236.rs delete mode 100644 tests/rustdoc/issue-52873.rs delete mode 100644 tests/rustdoc/issue-53689.rs delete mode 100644 tests/rustdoc/issue-53812.rs delete mode 100644 tests/rustdoc/issue-54478-demo-allocator.rs delete mode 100644 tests/rustdoc/issue-54705.rs delete mode 100644 tests/rustdoc/issue-55001.rs delete mode 100644 tests/rustdoc/issue-55321.rs delete mode 100644 tests/rustdoc/issue-55364.rs create mode 100644 tests/rustdoc/public-impl-mention-private-generic-46380-2.rs create mode 100644 tests/rustdoc/sort-53812.rs create mode 100644 tests/rustdoc/summary-header-46377.rs diff --git a/tests/rustdoc-ui/ice-blanket-impl-52873.rs b/tests/rustdoc-ui/ice-blanket-impl-52873.rs new file mode 100644 index 00000000000..12d3e3d7f94 --- /dev/null +++ b/tests/rustdoc-ui/ice-blanket-impl-52873.rs @@ -0,0 +1,174 @@ +// 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". + +use std::marker::PhantomData; +use std::cmp::Ordering; +use std::ops::{Add, Mul}; + +pub type True = B1; +pub type False = B0; +pub type U0 = UTerm; +pub type U1 = UInt; + +pub trait NonZero {} + +pub trait Bit { +} + +pub trait Unsigned { +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +pub struct B0; + +impl B0 { + #[inline] + pub fn new() -> B0 { + B0 + } +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +pub struct B1; + +impl B1 { + #[inline] + pub fn new() -> B1 { + B1 + } +} + +impl Bit for B0 { +} + +impl Bit for B1 { +} + +impl NonZero for B1 {} + +pub trait PrivatePow { + type Output; +} +pub type PrivatePowOut = >::Output; + +pub type Add1 = >::Output; +pub type Prod = >::Output; +pub type Square = ::Output; +pub type Sum = >::Output; + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +pub struct UTerm; + +impl UTerm { + #[inline] + pub fn new() -> UTerm { + UTerm + } +} + +impl Unsigned for UTerm { +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] +pub struct UInt { + _marker: PhantomData<(U, B)>, +} + +impl UInt { + #[inline] + pub fn new() -> UInt { + UInt { + _marker: PhantomData, + } + } +} + +impl Unsigned for UInt { +} + +impl NonZero for UInt {} + +impl Add for UTerm { + type Output = UTerm; + fn add(self, _: B0) -> Self::Output { + UTerm + } +} + +impl Add for UInt { + type Output = UInt; + fn add(self, _: B0) -> Self::Output { + UInt::new() + } +} + +impl Add for UTerm { + type Output = U; + fn add(self, _: U) -> Self::Output { + unimplemented!() + } +} + +impl Mul for UInt { + type Output = UTerm; + fn mul(self, _: B0) -> Self::Output { + UTerm + } +} + +impl Mul for UInt { + type Output = UInt; + fn mul(self, _: B1) -> Self::Output { + UInt::new() + } +} + +impl Mul for UTerm { + type Output = UTerm; + fn mul(self, _: U) -> Self::Output { + UTerm + } +} + +impl Mul> for UInt +where + Ul: Mul>, +{ + type Output = UInt>, B0>; + fn mul(self, _: UInt) -> Self::Output { + unimplemented!() + } +} + +pub trait Pow { + type Output; +} + +impl Pow for X +where + X: PrivatePow, +{ + type Output = PrivatePowOut; +} + +impl PrivatePow for X { + type Output = Y; +} + +impl PrivatePow for X +where + X: Mul, +{ + type Output = Prod; +} + +impl PrivatePow, B0>> for X +where + X: Mul, + Square: PrivatePow>, +{ + type Output = PrivatePowOut, Y, UInt>; +} diff --git a/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs new file mode 100644 index 00000000000..b7d86a1c843 --- /dev/null +++ b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs @@ -0,0 +1,34 @@ +// 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 +// against an obligation. + +pub struct DefaultAllocator; +pub struct Standard; +pub struct Inner; + +pub trait Rand {} + +pub trait Distribution {} +pub trait Allocator {} + +impl Rand for T where Standard: Distribution {} + +impl Distribution> for Standard +where +DefaultAllocator: Allocator, +Standard: Distribution {} + +impl Distribution for Standard {} + + +pub struct Point +where DefaultAllocator: Allocator +{ + field: N +} + +fn main() {} diff --git a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs new file mode 100644 index 00000000000..0663ed5fc81 --- /dev/null +++ b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs @@ -0,0 +1,23 @@ +// https://github.com/rust-lang/rust/issues/50159 +#![crate_name="foo"] + +pub trait Signal { + type Item; +} + +pub trait Signal2 { + type Item2; +} + +impl Signal2 for B where B: Signal { + type Item2 = C; +} + +// @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 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 +pub struct Switch { + pub inner: ::Item2, +} diff --git a/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs b/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs new file mode 100644 index 00000000000..00be0042fb0 --- /dev/null +++ b/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs @@ -0,0 +1,30 @@ +// https://github.com/rust-lang/rust/issues/54705 +#![crate_name="foo"] + +pub trait ScopeHandle<'scope> {} + +// @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" +// +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync" +pub struct ScopeFutureContents<'scope, S> + where S: ScopeHandle<'scope>, +{ + dummy: &'scope S, + this: Box>, +} + +struct ScopeFuture<'scope, S> + where S: ScopeHandle<'scope>, +{ + contents: ScopeFutureContents<'scope, S>, +} + +unsafe impl<'scope, S> Send for ScopeFuture<'scope, S> + where S: ScopeHandle<'scope>, +{} +unsafe impl<'scope, S> Sync for ScopeFuture<'scope, S> + where S: ScopeHandle<'scope>, +{} diff --git a/tests/rustdoc/auto-trait-bounds-where-51236.rs b/tests/rustdoc/auto-trait-bounds-where-51236.rs new file mode 100644 index 00000000000..30c81e79601 --- /dev/null +++ b/tests/rustdoc/auto-trait-bounds-where-51236.rs @@ -0,0 +1,17 @@ +// https://github.com/rust-lang/rust/issues/51236 +#![crate_name="foo"] + +use std::marker::PhantomData; + +pub mod traits { + pub trait Owned<'a> { + type Reader; + } +} + +// @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> { + marker: PhantomData<>::Reader>, +} diff --git a/tests/rustdoc/auto-trait-negative-impl-55321.rs b/tests/rustdoc/auto-trait-negative-impl-55321.rs new file mode 100644 index 00000000000..e9be1ff854e --- /dev/null +++ b/tests/rustdoc/auto-trait-negative-impl-55321.rs @@ -0,0 +1,21 @@ +// https://github.com/rust-lang/rust/issues/55321 +#![crate_name="foo"] + +#![feature(negative_impls)] + +// @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"]' \ +// "impl !Sync for A" +pub struct A(); + +impl !Send for A {} +impl !Sync for A {} + +// @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"]' \ +// "impl !Sync for B" +pub struct B(A, Box); diff --git a/tests/rustdoc/auxiliary/issue-46727.rs b/tests/rustdoc/auxiliary/issue-46727.rs deleted file mode 100644 index 30dccfa77b5..00000000000 --- a/tests/rustdoc/auxiliary/issue-46727.rs +++ /dev/null @@ -1,7 +0,0 @@ -// compile-flags: -Cmetadata=aux - -pub trait Foo {} - -pub struct Bar { x: T } - -impl Foo for Bar<[T; 1 + 1 + 1]> {} diff --git a/tests/rustdoc/blank-line-in-doc-block-47197.rs b/tests/rustdoc/blank-line-in-doc-block-47197.rs new file mode 100644 index 00000000000..79492b4fa76 --- /dev/null +++ b/tests/rustdoc/blank-line-in-doc-block-47197.rs @@ -0,0 +1,11 @@ +// https://github.com/rust-lang/rust/issues/47197 +#![crate_name="foo"] + +// @has foo/fn.whose_woods_these_are_i_think_i_know.html + +/** +* snow + +* ice +*/ +pub fn whose_woods_these_are_i_think_i_know() {} diff --git a/tests/rustdoc/demo-allocator-54478.rs b/tests/rustdoc/demo-allocator-54478.rs new file mode 100644 index 00000000000..39acee36d88 --- /dev/null +++ b/tests/rustdoc/demo-allocator-54478.rs @@ -0,0 +1,45 @@ +// 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`. +// +// ## Background +// +// Changes in lang-item visibility injected failures that were only +// exposed when compiling with `-C prefer-dynamic`. But `rustdoc` used +// `-C prefer-dynamic` (and had done so for years, for reasons we did +// not document at that time). +// +// Rather than try to revise the visbility semanics, we instead +// decided to change `rustdoc` to behave more like the compiler's +// default setting, by leaving off `-C prefer-dynamic`. + +// compile-flags:--test + +//! This is a doc comment +//! +//! ```rust +//! use std::alloc::*; +//! +//! #[global_allocator] +//! static ALLOC: A = A; +//! +//! static mut HIT: bool = false; +//! +//! struct A; +//! +//! unsafe impl GlobalAlloc for A { +//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +//! HIT = true; +//! System.alloc(layout) +//! } +//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { +//! System.dealloc(ptr, layout); +//! } +//! } +//! +//! fn main() { +//! assert!(unsafe { HIT }); +//! } +//! ``` diff --git a/tests/rustdoc/deref-mut-35169-2.rs b/tests/rustdoc/deref-mut-35169-2.rs new file mode 100644 index 00000000000..c82323ddc6a --- /dev/null +++ b/tests/rustdoc/deref-mut-35169-2.rs @@ -0,0 +1,43 @@ +// https://github.com/rust-lang/rust/issues/35169 +#![crate_name="foo"] + +use std::ops::Deref; +use std::ops::DerefMut; + +pub struct Foo; +pub struct Bar; + +impl Foo { + pub fn by_ref(&self) {} + pub fn by_explicit_ref(self: &Foo) {} + pub fn by_mut_ref(&mut self) {} + pub fn by_explicit_mut_ref(self: &mut Foo) {} + pub fn by_explicit_box(self: Box) {} + pub fn by_explicit_self_box(self: Box) {} + pub fn static_foo() {} +} + +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Foo { loop {} } +} + +impl DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Foo { loop {} } +} + +// @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)' +// @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)' +// @has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)' +// @has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)' +// @has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)' +// @has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)' +// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box)' +// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()' +// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/tests/rustdoc/deref-mut-35169.rs b/tests/rustdoc/deref-mut-35169.rs new file mode 100644 index 00000000000..44afaf2e903 --- /dev/null +++ b/tests/rustdoc/deref-mut-35169.rs @@ -0,0 +1,38 @@ +// https://github.com/rust-lang/rust/issues/35169 +#![crate_name="foo"] + +use std::ops::Deref; + +pub struct Foo; +pub struct Bar; + +impl Foo { + pub fn by_ref(&self) {} + pub fn by_explicit_ref(self: &Foo) {} + pub fn by_mut_ref(&mut self) {} + pub fn by_explicit_mut_ref(self: &mut Foo) {} + pub fn by_explicit_box(self: Box) {} + pub fn by_explicit_self_box(self: Box) {} + pub fn static_foo() {} +} + +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Foo { loop {} } +} + +// @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)' +// @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)' +// @!has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)' +// @!has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)' +// @!has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)' +// @!has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)' +// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box)' +// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box)' +// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()' +// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/tests/rustdoc/doc-attr-comment-mix-42760.rs b/tests/rustdoc/doc-attr-comment-mix-42760.rs new file mode 100644 index 00000000000..16c1705eb00 --- /dev/null +++ b/tests/rustdoc/doc-attr-comment-mix-42760.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/42760 +#![crate_name="foo"] + +#![allow(rustdoc::invalid_rust_codeblocks)] + +// @has foo/struct.NonGen.html +// @has - '//h2' 'Example' + +/// Item docs. +/// +#[doc="Hello there!"] +/// +/// # Example +/// +/// ```rust +/// // some code here +/// ``` +pub struct NonGen; diff --git a/tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html b/tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html new file mode 100644 index 00000000000..3bca4536cd5 --- /dev/null +++ b/tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html @@ -0,0 +1,5 @@ +# single +## double +### triple +#[outer] +#![inner] diff --git a/tests/rustdoc/doctest/doctest-escape-boring-41783.rs b/tests/rustdoc/doctest/doctest-escape-boring-41783.rs new file mode 100644 index 00000000000..7782e148fd9 --- /dev/null +++ b/tests/rustdoc/doctest/doctest-escape-boring-41783.rs @@ -0,0 +1,22 @@ +// https://github.com/rust-lang/rust/issues/41783 +#![crate_name="foo"] + +// @has foo/struct.Foo.html +// @!hasraw - 'space' +// @!hasraw - 'comment' +// @hasraw - '#[outer]' +// @!hasraw - '#[outer]' +// @hasraw - '#![inner]' +// @!hasraw - '#![inner]' +// @snapshot 'codeblock' - '//*[@class="toggle top-doc"]/*[@class="docblock"]//pre/code' + +/// ```no_run +/// # # space +/// # comment +/// ## single +/// ### double +/// #### triple +/// ##[outer] +/// ##![inner] +/// ``` +pub struct Foo; diff --git a/tests/rustdoc/enum-variant-reexport-35488.rs b/tests/rustdoc/enum-variant-reexport-35488.rs new file mode 100644 index 00000000000..ed955dcd770 --- /dev/null +++ b/tests/rustdoc/enum-variant-reexport-35488.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/35488 +#![crate_name="foo"] + +mod foo { + pub enum Foo { + Bar, + } + pub use self::Foo::*; +} + +// @has 'foo/index.html' '//code' 'pub use self::Foo::*;' +// @has 'foo/enum.Foo.html' +pub use self::foo::*; + +// @has 'foo/index.html' '//code' 'pub use std::option::Option::None;' +pub use std::option::Option::None; diff --git a/tests/rustdoc/impl-blanket-53689.rs b/tests/rustdoc/impl-blanket-53689.rs new file mode 100644 index 00000000000..7c2edd01a60 --- /dev/null +++ b/tests/rustdoc/impl-blanket-53689.rs @@ -0,0 +1,17 @@ +// https://github.com/rust-lang/rust/issues/53689 +// aux-build:issue-53689.rs + +#![crate_name = "foo"] + +extern crate issue_53689; + +// @has foo/trait.MyTrait.html +// @!hasraw - 'MyStruct' +// @count - '//*[h3="impl MyTrait for T"]' 1 +pub trait MyTrait {} + +impl MyTrait for T {} + +mod a { + pub use issue_53689::MyStruct; +} diff --git a/tests/rustdoc/impl-trait-43869.rs b/tests/rustdoc/impl-trait-43869.rs new file mode 100644 index 00000000000..9c4ed841f79 --- /dev/null +++ b/tests/rustdoc/impl-trait-43869.rs @@ -0,0 +1,75 @@ +// https://github.com/rust-lang/rust/issues/43869 +#![crate_name="foo"] + +pub fn g() -> impl Iterator { + Some(1u8).into_iter() +} + +#[allow(unused_parens)] +pub fn h() -> (impl Iterator) { + Some(1u8).into_iter() +} + +pub fn i() -> impl Iterator + 'static { + Some(1u8).into_iter() +} + +pub fn j() -> impl Iterator + Clone { + Some(1u8).into_iter() +} + +pub fn k() -> [impl Clone; 2] { + [123u32, 456u32] +} + +pub fn l() -> (impl Clone, impl Default) { + (789u32, -123i32) +} + +pub fn m() -> &'static impl Clone { + &1u8 +} + +pub fn n() -> *const impl Clone { + &1u8 +} + +pub fn o() -> &'static [impl Clone] { + b":)" +} + +// issue #44731 +pub fn test_44731_0() -> Box> { + Box::new(g()) +} + +pub fn test_44731_1() -> Result, ()> { + Ok(Box::new(j())) +} + +// NOTE these involve Fn sugar, where impl Trait is disallowed for now, see issue #45994 +// +//pub fn test_44731_2() -> Box { +// Box::new(|_: u32| {}) +//} +// +//pub fn test_44731_3() -> Box impl Clone> { +// Box::new(|| 0u32) +//} + +pub fn test_44731_4() -> Box> { + Box::new(g()) +} + +// @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/inline_cross/auxiliary/issue-46727.rs b/tests/rustdoc/inline_cross/auxiliary/issue-46727.rs new file mode 100644 index 00000000000..30dccfa77b5 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/issue-46727.rs @@ -0,0 +1,7 @@ +// compile-flags: -Cmetadata=aux + +pub trait Foo {} + +pub struct Bar { x: T } + +impl Foo for Bar<[T; 1 + 1 + 1]> {} diff --git a/tests/rustdoc/inline_cross/const-eval-46727.rs b/tests/rustdoc/inline_cross/const-eval-46727.rs new file mode 100644 index 00000000000..d0ce9c34f51 --- /dev/null +++ b/tests/rustdoc/inline_cross/const-eval-46727.rs @@ -0,0 +1,10 @@ +// https://github.com/rust-lang/rust/issues/46727 +#![crate_name="foo"] + +// aux-build:issue-46727.rs + +extern crate issue_46727; + +// @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/intra-doc/module-scope-name-resolution-55364.rs b/tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs new file mode 100644 index 00000000000..c07aba628c9 --- /dev/null +++ b/tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs @@ -0,0 +1,89 @@ +// https://github.com/rust-lang/rust/issues/55364 +#![crate_name="foo"] + +// First a module with inner documentation + +// @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' +pub mod subone { + //! See either [foo] or [bar]. + + // This should refer to subone's `bar` + // @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 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() {} +} + +// A module with outer documentation + +// @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' +// Instead it should be referencing the top level functions +// @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' +// Though there should be such links later +// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.foo.html"]' 'foo' +// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.bar.html"]' 'bar' +/// See either [foo] or [bar]. +pub mod subtwo { + + // Despite the module's docs referring to the top level foo/bar, + // this should refer to subtwo's `bar` + // @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 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() {} +} + +// These are the function referred to by the module above with outer docs + +/// See [bar] +pub fn foo() {} +/// See [foo] +pub fn bar() {} + +// This module refers to the outer foo/bar by means of `super::` + +// @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' +pub mod subthree { + //! See either [foo][super::foo] or [bar][super::bar] +} + +// Next we go *deeper* - In order to ensure it's not just "this or parent" +// we test `crate::` and a `super::super::...` chain +// @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 { + pub mod subfive { + pub mod subsix { + pub mod subseven { + pub mod subeight { + /// See [other foo][crate::subone::foo] + pub fn foo() {} + /// See [other bar][super::super::super::super::super::subtwo::bar] + pub fn bar() {} + } + } + } + } +} diff --git a/tests/rustdoc/issue-35169-2.rs b/tests/rustdoc/issue-35169-2.rs deleted file mode 100644 index c82323ddc6a..00000000000 --- a/tests/rustdoc/issue-35169-2.rs +++ /dev/null @@ -1,43 +0,0 @@ -// https://github.com/rust-lang/rust/issues/35169 -#![crate_name="foo"] - -use std::ops::Deref; -use std::ops::DerefMut; - -pub struct Foo; -pub struct Bar; - -impl Foo { - pub fn by_ref(&self) {} - pub fn by_explicit_ref(self: &Foo) {} - pub fn by_mut_ref(&mut self) {} - pub fn by_explicit_mut_ref(self: &mut Foo) {} - pub fn by_explicit_box(self: Box) {} - pub fn by_explicit_self_box(self: Box) {} - pub fn static_foo() {} -} - -impl Deref for Bar { - type Target = Foo; - fn deref(&self) -> &Foo { loop {} } -} - -impl DerefMut for Bar { - fn deref_mut(&mut self) -> &mut Foo { loop {} } -} - -// @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)' -// @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)' -// @has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)' -// @has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)' -// @has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)' -// @has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)' -// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box)' -// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box)' -// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box)' -// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box)' -// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()' -// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/tests/rustdoc/issue-35169.rs b/tests/rustdoc/issue-35169.rs deleted file mode 100644 index 44afaf2e903..00000000000 --- a/tests/rustdoc/issue-35169.rs +++ /dev/null @@ -1,38 +0,0 @@ -// https://github.com/rust-lang/rust/issues/35169 -#![crate_name="foo"] - -use std::ops::Deref; - -pub struct Foo; -pub struct Bar; - -impl Foo { - pub fn by_ref(&self) {} - pub fn by_explicit_ref(self: &Foo) {} - pub fn by_mut_ref(&mut self) {} - pub fn by_explicit_mut_ref(self: &mut Foo) {} - pub fn by_explicit_box(self: Box) {} - pub fn by_explicit_self_box(self: Box) {} - pub fn static_foo() {} -} - -impl Deref for Bar { - type Target = Foo; - fn deref(&self) -> &Foo { loop {} } -} - -// @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)' -// @has - '//*[@id="method.by_explicit_ref"]' 'fn by_explicit_ref(self: &Foo)' -// @!has - '//*[@id="method.by_mut_ref"]//h4[@class="code-header"]' 'fn by_mut_ref(&mut self)' -// @!has - '//*[@id="method.by_mut_ref"]' 'fn by_mut_ref(&mut self)' -// @!has - '//*[@id="method.by_explicit_mut_ref"]//h4[@class="code-header"]' 'fn by_explicit_mut_ref(self: &mut Foo)' -// @!has - '//*[@id="method.by_explicit_mut_ref"]' 'fn by_explicit_mut_ref(self: &mut Foo)' -// @!has - '//*[@id="method.by_explicit_box"]//h4[@class="code-header"]' 'fn by_explicit_box(self: Box)' -// @!has - '//*[@id="method.by_explicit_box"]' 'fn by_explicit_box(self: Box)' -// @!has - '//*[@id="method.by_explicit_self_box"]//h4[@class="code-header"]' 'fn by_explicit_self_box(self: Box)' -// @!has - '//*[@id="method.by_explicit_self_box"]' 'fn by_explicit_self_box(self: Box)' -// @!has - '//*[@id="method.static_foo"]//h4[@class="code-header"]' 'fn static_foo()' -// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()' diff --git a/tests/rustdoc/issue-35488.rs b/tests/rustdoc/issue-35488.rs deleted file mode 100644 index ed955dcd770..00000000000 --- a/tests/rustdoc/issue-35488.rs +++ /dev/null @@ -1,16 +0,0 @@ -// https://github.com/rust-lang/rust/issues/35488 -#![crate_name="foo"] - -mod foo { - pub enum Foo { - Bar, - } - pub use self::Foo::*; -} - -// @has 'foo/index.html' '//code' 'pub use self::Foo::*;' -// @has 'foo/enum.Foo.html' -pub use self::foo::*; - -// @has 'foo/index.html' '//code' 'pub use std::option::Option::None;' -pub use std::option::Option::None; diff --git a/tests/rustdoc/issue-41783.codeblock.html b/tests/rustdoc/issue-41783.codeblock.html deleted file mode 100644 index 3bca4536cd5..00000000000 --- a/tests/rustdoc/issue-41783.codeblock.html +++ /dev/null @@ -1,5 +0,0 @@ -# single -## double -### triple -#[outer] -#![inner] diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/issue-41783.rs deleted file mode 100644 index 7782e148fd9..00000000000 --- a/tests/rustdoc/issue-41783.rs +++ /dev/null @@ -1,22 +0,0 @@ -// https://github.com/rust-lang/rust/issues/41783 -#![crate_name="foo"] - -// @has foo/struct.Foo.html -// @!hasraw - 'space' -// @!hasraw - 'comment' -// @hasraw - '#[outer]' -// @!hasraw - '#[outer]' -// @hasraw - '#![inner]' -// @!hasraw - '#![inner]' -// @snapshot 'codeblock' - '//*[@class="toggle top-doc"]/*[@class="docblock"]//pre/code' - -/// ```no_run -/// # # space -/// # comment -/// ## single -/// ### double -/// #### triple -/// ##[outer] -/// ##![inner] -/// ``` -pub struct Foo; diff --git a/tests/rustdoc/issue-42760.rs b/tests/rustdoc/issue-42760.rs deleted file mode 100644 index 16c1705eb00..00000000000 --- a/tests/rustdoc/issue-42760.rs +++ /dev/null @@ -1,18 +0,0 @@ -// https://github.com/rust-lang/rust/issues/42760 -#![crate_name="foo"] - -#![allow(rustdoc::invalid_rust_codeblocks)] - -// @has foo/struct.NonGen.html -// @has - '//h2' 'Example' - -/// Item docs. -/// -#[doc="Hello there!"] -/// -/// # Example -/// -/// ```rust -/// // some code here -/// ``` -pub struct NonGen; diff --git a/tests/rustdoc/issue-43869.rs b/tests/rustdoc/issue-43869.rs deleted file mode 100644 index 9c4ed841f79..00000000000 --- a/tests/rustdoc/issue-43869.rs +++ /dev/null @@ -1,75 +0,0 @@ -// https://github.com/rust-lang/rust/issues/43869 -#![crate_name="foo"] - -pub fn g() -> impl Iterator { - Some(1u8).into_iter() -} - -#[allow(unused_parens)] -pub fn h() -> (impl Iterator) { - Some(1u8).into_iter() -} - -pub fn i() -> impl Iterator + 'static { - Some(1u8).into_iter() -} - -pub fn j() -> impl Iterator + Clone { - Some(1u8).into_iter() -} - -pub fn k() -> [impl Clone; 2] { - [123u32, 456u32] -} - -pub fn l() -> (impl Clone, impl Default) { - (789u32, -123i32) -} - -pub fn m() -> &'static impl Clone { - &1u8 -} - -pub fn n() -> *const impl Clone { - &1u8 -} - -pub fn o() -> &'static [impl Clone] { - b":)" -} - -// issue #44731 -pub fn test_44731_0() -> Box> { - Box::new(g()) -} - -pub fn test_44731_1() -> Result, ()> { - Ok(Box::new(j())) -} - -// NOTE these involve Fn sugar, where impl Trait is disallowed for now, see issue #45994 -// -//pub fn test_44731_2() -> Box { -// Box::new(|_: u32| {}) -//} -// -//pub fn test_44731_3() -> Box impl Clone> { -// Box::new(|| 0u32) -//} - -pub fn test_44731_4() -> Box> { - Box::new(g()) -} - -// @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 deleted file mode 100644 index aec74f493d4..00000000000 --- a/tests/rustdoc/issue-46377.rs +++ /dev/null @@ -1,6 +0,0 @@ -// 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 deleted file mode 100644 index 96ebd888eb5..00000000000 --- a/tests/rustdoc/issue-46380-2.rs +++ /dev/null @@ -1,12 +0,0 @@ -// https://github.com/rust-lang/rust/issues/46380 -#![crate_name="foo"] - -pub trait PublicTrait {} - -// @has foo/struct.PublicStruct.html -pub struct PublicStruct; - -// @!has - '//*[@class="impl"]' 'impl PublicTrait for PublicStruct' -impl PublicTrait for PublicStruct {} - -struct PrivateStruct; diff --git a/tests/rustdoc/issue-46727.rs b/tests/rustdoc/issue-46727.rs deleted file mode 100644 index d0ce9c34f51..00000000000 --- a/tests/rustdoc/issue-46727.rs +++ /dev/null @@ -1,10 +0,0 @@ -// https://github.com/rust-lang/rust/issues/46727 -#![crate_name="foo"] - -// aux-build:issue-46727.rs - -extern crate issue_46727; - -// @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 deleted file mode 100644 index 79492b4fa76..00000000000 --- a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs +++ /dev/null @@ -1,11 +0,0 @@ -// https://github.com/rust-lang/rust/issues/47197 -#![crate_name="foo"] - -// @has foo/fn.whose_woods_these_are_i_think_i_know.html - -/** -* snow - -* ice -*/ -pub fn whose_woods_these_are_i_think_i_know() {} diff --git a/tests/rustdoc/issue-50159.rs b/tests/rustdoc/issue-50159.rs deleted file mode 100644 index 0663ed5fc81..00000000000 --- a/tests/rustdoc/issue-50159.rs +++ /dev/null @@ -1,23 +0,0 @@ -// https://github.com/rust-lang/rust/issues/50159 -#![crate_name="foo"] - -pub trait Signal { - type Item; -} - -pub trait Signal2 { - type Item2; -} - -impl Signal2 for B where B: Signal { - type Item2 = C; -} - -// @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 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 -pub struct Switch { - pub inner: ::Item2, -} diff --git a/tests/rustdoc/issue-51236.rs b/tests/rustdoc/issue-51236.rs deleted file mode 100644 index 30c81e79601..00000000000 --- a/tests/rustdoc/issue-51236.rs +++ /dev/null @@ -1,17 +0,0 @@ -// https://github.com/rust-lang/rust/issues/51236 -#![crate_name="foo"] - -use std::marker::PhantomData; - -pub mod traits { - pub trait Owned<'a> { - type Reader; - } -} - -// @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> { - marker: PhantomData<>::Reader>, -} diff --git a/tests/rustdoc/issue-52873.rs b/tests/rustdoc/issue-52873.rs deleted file mode 100644 index 12d3e3d7f94..00000000000 --- a/tests/rustdoc/issue-52873.rs +++ /dev/null @@ -1,174 +0,0 @@ -// 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". - -use std::marker::PhantomData; -use std::cmp::Ordering; -use std::ops::{Add, Mul}; - -pub type True = B1; -pub type False = B0; -pub type U0 = UTerm; -pub type U1 = UInt; - -pub trait NonZero {} - -pub trait Bit { -} - -pub trait Unsigned { -} - -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] -pub struct B0; - -impl B0 { - #[inline] - pub fn new() -> B0 { - B0 - } -} - -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] -pub struct B1; - -impl B1 { - #[inline] - pub fn new() -> B1 { - B1 - } -} - -impl Bit for B0 { -} - -impl Bit for B1 { -} - -impl NonZero for B1 {} - -pub trait PrivatePow { - type Output; -} -pub type PrivatePowOut = >::Output; - -pub type Add1 = >::Output; -pub type Prod = >::Output; -pub type Square = ::Output; -pub type Sum = >::Output; - -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] -pub struct UTerm; - -impl UTerm { - #[inline] - pub fn new() -> UTerm { - UTerm - } -} - -impl Unsigned for UTerm { -} - -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] -pub struct UInt { - _marker: PhantomData<(U, B)>, -} - -impl UInt { - #[inline] - pub fn new() -> UInt { - UInt { - _marker: PhantomData, - } - } -} - -impl Unsigned for UInt { -} - -impl NonZero for UInt {} - -impl Add for UTerm { - type Output = UTerm; - fn add(self, _: B0) -> Self::Output { - UTerm - } -} - -impl Add for UInt { - type Output = UInt; - fn add(self, _: B0) -> Self::Output { - UInt::new() - } -} - -impl Add for UTerm { - type Output = U; - fn add(self, _: U) -> Self::Output { - unimplemented!() - } -} - -impl Mul for UInt { - type Output = UTerm; - fn mul(self, _: B0) -> Self::Output { - UTerm - } -} - -impl Mul for UInt { - type Output = UInt; - fn mul(self, _: B1) -> Self::Output { - UInt::new() - } -} - -impl Mul for UTerm { - type Output = UTerm; - fn mul(self, _: U) -> Self::Output { - UTerm - } -} - -impl Mul> for UInt -where - Ul: Mul>, -{ - type Output = UInt>, B0>; - fn mul(self, _: UInt) -> Self::Output { - unimplemented!() - } -} - -pub trait Pow { - type Output; -} - -impl Pow for X -where - X: PrivatePow, -{ - type Output = PrivatePowOut; -} - -impl PrivatePow for X { - type Output = Y; -} - -impl PrivatePow for X -where - X: Mul, -{ - type Output = Prod; -} - -impl PrivatePow, B0>> for X -where - X: Mul, - Square: PrivatePow>, -{ - type Output = PrivatePowOut, Y, UInt>; -} diff --git a/tests/rustdoc/issue-53689.rs b/tests/rustdoc/issue-53689.rs deleted file mode 100644 index 7c2edd01a60..00000000000 --- a/tests/rustdoc/issue-53689.rs +++ /dev/null @@ -1,17 +0,0 @@ -// https://github.com/rust-lang/rust/issues/53689 -// aux-build:issue-53689.rs - -#![crate_name = "foo"] - -extern crate issue_53689; - -// @has foo/trait.MyTrait.html -// @!hasraw - 'MyStruct' -// @count - '//*[h3="impl MyTrait for T"]' 1 -pub trait MyTrait {} - -impl MyTrait for T {} - -mod a { - pub use issue_53689::MyStruct; -} diff --git a/tests/rustdoc/issue-53812.rs b/tests/rustdoc/issue-53812.rs deleted file mode 100644 index 968ae035043..00000000000 --- a/tests/rustdoc/issue-53812.rs +++ /dev/null @@ -1,23 +0,0 @@ -// https://github.com/rust-lang/rust/issues/53812 -#![crate_name="foo"] - -pub trait MyIterator {} - -pub struct MyStruct(T); - -macro_rules! array_impls { - ($($N:expr)+) => { - $( - impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> { - } - )+ - } -} - -// @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]>' -// @has - '//*[@id="implementors-list"]/*[@class="impl"][4]' 'MyStruct<[T; 3]>' -// @has - '//*[@id="implementors-list"]/*[@class="impl"][5]' 'MyStruct<[T; 10]>' -array_impls! { 10 3 2 1 0 } diff --git a/tests/rustdoc/issue-54478-demo-allocator.rs b/tests/rustdoc/issue-54478-demo-allocator.rs deleted file mode 100644 index 39acee36d88..00000000000 --- a/tests/rustdoc/issue-54478-demo-allocator.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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`. -// -// ## Background -// -// Changes in lang-item visibility injected failures that were only -// exposed when compiling with `-C prefer-dynamic`. But `rustdoc` used -// `-C prefer-dynamic` (and had done so for years, for reasons we did -// not document at that time). -// -// Rather than try to revise the visbility semanics, we instead -// decided to change `rustdoc` to behave more like the compiler's -// default setting, by leaving off `-C prefer-dynamic`. - -// compile-flags:--test - -//! This is a doc comment -//! -//! ```rust -//! use std::alloc::*; -//! -//! #[global_allocator] -//! static ALLOC: A = A; -//! -//! static mut HIT: bool = false; -//! -//! struct A; -//! -//! unsafe impl GlobalAlloc for A { -//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 { -//! HIT = true; -//! System.alloc(layout) -//! } -//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { -//! System.dealloc(ptr, layout); -//! } -//! } -//! -//! fn main() { -//! assert!(unsafe { HIT }); -//! } -//! ``` diff --git a/tests/rustdoc/issue-54705.rs b/tests/rustdoc/issue-54705.rs deleted file mode 100644 index 00be0042fb0..00000000000 --- a/tests/rustdoc/issue-54705.rs +++ /dev/null @@ -1,30 +0,0 @@ -// https://github.com/rust-lang/rust/issues/54705 -#![crate_name="foo"] - -pub trait ScopeHandle<'scope> {} - -// @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" -// -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ -// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync" -pub struct ScopeFutureContents<'scope, S> - where S: ScopeHandle<'scope>, -{ - dummy: &'scope S, - this: Box>, -} - -struct ScopeFuture<'scope, S> - where S: ScopeHandle<'scope>, -{ - contents: ScopeFutureContents<'scope, S>, -} - -unsafe impl<'scope, S> Send for ScopeFuture<'scope, S> - where S: ScopeHandle<'scope>, -{} -unsafe impl<'scope, S> Sync for ScopeFuture<'scope, S> - where S: ScopeHandle<'scope>, -{} diff --git a/tests/rustdoc/issue-55001.rs b/tests/rustdoc/issue-55001.rs deleted file mode 100644 index b7d86a1c843..00000000000 --- a/tests/rustdoc/issue-55001.rs +++ /dev/null @@ -1,34 +0,0 @@ -// 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 -// against an obligation. - -pub struct DefaultAllocator; -pub struct Standard; -pub struct Inner; - -pub trait Rand {} - -pub trait Distribution {} -pub trait Allocator {} - -impl Rand for T where Standard: Distribution {} - -impl Distribution> for Standard -where -DefaultAllocator: Allocator, -Standard: Distribution {} - -impl Distribution for Standard {} - - -pub struct Point -where DefaultAllocator: Allocator -{ - field: N -} - -fn main() {} diff --git a/tests/rustdoc/issue-55321.rs b/tests/rustdoc/issue-55321.rs deleted file mode 100644 index e9be1ff854e..00000000000 --- a/tests/rustdoc/issue-55321.rs +++ /dev/null @@ -1,21 +0,0 @@ -// https://github.com/rust-lang/rust/issues/55321 -#![crate_name="foo"] - -#![feature(negative_impls)] - -// @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"]' \ -// "impl !Sync for A" -pub struct A(); - -impl !Send for A {} -impl !Sync for A {} - -// @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"]' \ -// "impl !Sync for B" -pub struct B(A, Box); diff --git a/tests/rustdoc/issue-55364.rs b/tests/rustdoc/issue-55364.rs deleted file mode 100644 index c07aba628c9..00000000000 --- a/tests/rustdoc/issue-55364.rs +++ /dev/null @@ -1,89 +0,0 @@ -// https://github.com/rust-lang/rust/issues/55364 -#![crate_name="foo"] - -// First a module with inner documentation - -// @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' -pub mod subone { - //! See either [foo] or [bar]. - - // This should refer to subone's `bar` - // @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 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() {} -} - -// A module with outer documentation - -// @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' -// Instead it should be referencing the top level functions -// @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' -// Though there should be such links later -// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.foo.html"]' 'foo' -// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.bar.html"]' 'bar' -/// See either [foo] or [bar]. -pub mod subtwo { - - // Despite the module's docs referring to the top level foo/bar, - // this should refer to subtwo's `bar` - // @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 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() {} -} - -// These are the function referred to by the module above with outer docs - -/// See [bar] -pub fn foo() {} -/// See [foo] -pub fn bar() {} - -// This module refers to the outer foo/bar by means of `super::` - -// @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' -pub mod subthree { - //! See either [foo][super::foo] or [bar][super::bar] -} - -// Next we go *deeper* - In order to ensure it's not just "this or parent" -// we test `crate::` and a `super::super::...` chain -// @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 { - pub mod subfive { - pub mod subsix { - pub mod subseven { - pub mod subeight { - /// See [other foo][crate::subone::foo] - pub fn foo() {} - /// See [other bar][super::super::super::super::super::subtwo::bar] - pub fn bar() {} - } - } - } - } -} diff --git a/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs b/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs new file mode 100644 index 00000000000..96ebd888eb5 --- /dev/null +++ b/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs @@ -0,0 +1,12 @@ +// https://github.com/rust-lang/rust/issues/46380 +#![crate_name="foo"] + +pub trait PublicTrait {} + +// @has foo/struct.PublicStruct.html +pub struct PublicStruct; + +// @!has - '//*[@class="impl"]' 'impl PublicTrait for PublicStruct' +impl PublicTrait for PublicStruct {} + +struct PrivateStruct; diff --git a/tests/rustdoc/sort-53812.rs b/tests/rustdoc/sort-53812.rs new file mode 100644 index 00000000000..968ae035043 --- /dev/null +++ b/tests/rustdoc/sort-53812.rs @@ -0,0 +1,23 @@ +// https://github.com/rust-lang/rust/issues/53812 +#![crate_name="foo"] + +pub trait MyIterator {} + +pub struct MyStruct(T); + +macro_rules! array_impls { + ($($N:expr)+) => { + $( + impl<'a, T> MyIterator for &'a MyStruct<[T; $N]> { + } + )+ + } +} + +// @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]>' +// @has - '//*[@id="implementors-list"]/*[@class="impl"][4]' 'MyStruct<[T; 3]>' +// @has - '//*[@id="implementors-list"]/*[@class="impl"][5]' 'MyStruct<[T; 10]>' +array_impls! { 10 3 2 1 0 } diff --git a/tests/rustdoc/summary-header-46377.rs b/tests/rustdoc/summary-header-46377.rs new file mode 100644 index 00000000000..aec74f493d4 --- /dev/null +++ b/tests/rustdoc/summary-header-46377.rs @@ -0,0 +1,6 @@ +// 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; -- cgit 1.4.1-3-g733a5 From a704e21c3f2ee1c9215bd088d2880c8e396eacca Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 3 Jan 2024 15:30:46 -0700 Subject: 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 12d3e3d7f94..2520957bd00 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 b7d86a1c843..babcb3dda14 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"] -- cgit 1.4.1-3-g733a5 From b83f487d1013f2277646cca478d5aa91d8b96f30 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 4 Jan 2024 11:02:20 +0100 Subject: 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 f50d796e139..2046fa943a8 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 980eab2696b..b9e4e534924 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 b6686fa5b65..54dae4eba96 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 7cd6df2df86..f1575a5b0bd 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; -- cgit 1.4.1-3-g733a5 From ab2286935dc37c4463f21837e70a4a51a13ef9b0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 1 Jan 2024 14:37:33 +0100 Subject: 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 54dae4eba96..ba17ea6f7b4 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 -- cgit 1.4.1-3-g733a5 From d480525ce8548e6220b1fc49a1078e165b485c11 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 1 Jan 2024 14:58:26 +0100 Subject: 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 b9e4e534924..2caa24b7032 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 000a526e9f9..87f7555b02c 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 6f40a4c88ed..7432f0f7a7c 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; -- cgit 1.4.1-3-g733a5 From 8390d2aca3d9845995968e47b65ae40fe06fc637 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 4 Jan 2024 10:44:18 +0100 Subject: 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 2caa24b7032..a559ba01755 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]] -- cgit 1.4.1-3-g733a5 From 79fa976864a2774e3b5377642d2c72147d240d2f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 4 Jan 2024 15:12:57 +0100 Subject: 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 ba17ea6f7b4..9c4375559c1 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] -- cgit 1.4.1-3-g733a5 From 4b7e0a0b56aa2446e670dfd6558380a1039a86aa Mon Sep 17 00:00:00 2001 From: Arlo Siemsen Date: Thu, 4 Jan 2024 11:40:56 -0600 Subject: 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 4e20babc55a..3770d0687b2 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); } -- cgit 1.4.1-3-g733a5 From 08c44a6c246690304fd8d0b667af81a7a1b96e42 Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 6 Jan 2024 08:41:11 +0300 Subject: 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 a7e4899fb7e..bc32220b416 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 + } + }) }) } -- cgit 1.4.1-3-g733a5 From 6403dbf0115b5cbde2e113965ecdeac38a5607ae Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 6 Jan 2024 12:51:44 +0300 Subject: fix ast::Path::segments callers that implicitly relied on behavior of previous implementation --- crates/ide-assists/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 a4e8e7388f6..8b8c6ceee99 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 }"#, ); } -- cgit 1.4.1-3-g733a5 From 89d6b011c4e104af34cb6f687af014c97992979e Mon Sep 17 00:00:00 2001 From: davidsemakula Date: Sat, 6 Jan 2024 12:53:56 +0300 Subject: 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 652968d808f..b834f517d49 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 bc32220b416..daa463261ae 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() { -- cgit 1.4.1-3-g733a5 From 872951d2d995cda3f7817c7f505c0257c4a784d5 Mon Sep 17 00:00:00 2001 From: roife Date: Sat, 6 Jan 2024 20:07:38 +0800 Subject: 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 8c1a6e6e40b..2d1af8fb7fb 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); } -- cgit 1.4.1-3-g733a5 From ba952e65ffc09d49bb92dfe3beb4bd584c3e82e4 Mon Sep 17 00:00:00 2001 From: roife Date: Sat, 6 Jan 2024 20:09:51 +0800 Subject: Transform paths before make::fn_ --- .../src/handlers/generate_delegate_methods.rs | 45 ++++++++++++++-------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index db1e0ceaec1..9856c58a0b2 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 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, [])); - 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([]), - }; + + // 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 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 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) } -- cgit 1.4.1-3-g733a5 From 05c4eef95e52f95aa938c5ec89773d0f21f9a872 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 3 May 2023 17:27:10 +0000 Subject: 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 2551c8aca88..e8b8baa15a9 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)) } } -- cgit 1.4.1-3-g733a5 From e26c9a42c6d9e0dab3eba4daf66785afeda2589b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 16 May 2023 10:19:08 +0000 Subject: 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 e8b8baa15a9..696067b1f0e 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); } } -- cgit 1.4.1-3-g733a5 From 4ee01faaf074f3a985bb7325f2209f9ee224cb5e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 19:08:36 +0000 Subject: 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 696067b1f0e..e8b86d1327d 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 fc0c8afd4cf..dfab4959516 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 cf4089598e7..b6d69732316 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 93dfef96cf1..2dc3aa9afca 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 93dfef96cf1..2dc3aa9afca 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; } -- cgit 1.4.1-3-g733a5 From 7e39100586d717f5a350eb8704bcd8938d09419c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 24 Dec 2023 13:00:48 +0000 Subject: 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 ++--- ..._oob_for_slices.main.GVN.32bit.panic-abort.diff | 12 +++------ ...oob_for_slices.main.GVN.32bit.panic-unwind.diff | 12 +++------ ..._oob_for_slices.main.GVN.64bit.panic-abort.diff | 12 +++------ ...oob_for_slices.main.GVN.64bit.panic-unwind.diff | 12 +++------ .../const_prop/indirect_mutation.bar.GVN.diff | 6 ++--- .../const_prop/indirect_mutation.foo.GVN.diff | 6 ++--- ...utable_variable_aggregate_mut_ref.main.GVN.diff | 6 ++--- .../mutable_variable_no_prop.main.GVN.diff | 6 ++--- ...ointer_expose_address.main.GVN.panic-abort.diff | 6 ++--- ...inter_expose_address.main.GVN.panic-unwind.diff | 6 ++--- tests/mir-opt/const_prop/ref_deref.main.GVN.diff | 6 ++--- .../const_prop/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 ++--- .../mir-opt/gvn.dereferences.GVN.panic-abort.diff | 18 +++++-------- .../mir-opt/gvn.dereferences.GVN.panic-unwind.diff | 18 +++++-------- tests/mir-opt/gvn.slices.GVN.panic-abort.diff | 12 +++------ tests/mir-opt/gvn.slices.GVN.panic-unwind.diff | 12 +++------ ....subexpression_elimination.GVN.panic-abort.diff | 30 ++++++++-------------- ...subexpression_elimination.GVN.panic-unwind.diff | 30 ++++++++-------------- ...lter.variant_a-{closure#0}.PreCodegen.after.mir | 16 ++++++++++++ ..._get_mut_usize.PreCodegen.after.panic-abort.mir | 2 ++ ...get_mut_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 e8b86d1327d..dc3af038d80 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 f089c6741fe..10d99a13463 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 9cbbaf302be..2f23dbe9ee4 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 dfa2d808128..6499e3676aa 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 02b66987169..02f5ebab847 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 386a55ee6fa..c95e696946a 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 b9e98f8cd4c..198bc8bd07e 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 2285962fad1..a044cfc62e2 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 a42f9291324..e1a93e31446 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 f2d6de6621b..91999145efb 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 a42f9291324..e1a93e31446 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 f2d6de6621b..91999145efb 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 7dd80d64360..b389080c497 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 c4b647d9d2d..c21869dece6 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 bc60546cd19..4ed7c985147 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 d02c392f6bd..e113f43a56e 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 425bc3ff6c1..4e79b3ad599 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 e9360ab8d62..fdc459b457c 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 8f9aa20524d..56cbd00025e 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 8d38888b7d6..d75c0c3b286 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 8b2411e50ab..803be994d9a 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 9b20d243f87..2a20e3eca59 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 8b2411e50ab..803be994d9a 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 9b20d243f87..2a20e3eca59 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 2dc3aa9afca..0ff31b1a981 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 2dc3aa9afca..0ff31b1a981 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 a587b1e6b1d..46bf13985da 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 6fdda5e9988..3e731ead859 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 ec449980312..f3f9073909e 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 56a78ca8694..383152cce5e 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 0a747d3aef0..3ecd4650d81 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 119a4d9bbe9..bf448280b1e 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 cc009e45e7e..7370da5629c 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 a12411a0413..e4d9060d4cf 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 a12411a0413..e4d9060d4cf 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; } } -- cgit 1.4.1-3-g733a5 From c4b10545250387876297777c2769b4195835b689 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Dec 2023 13:09:51 +0000 Subject: Move PointIndex to mir_dataflow. --- compiler/rustc_borrowck/src/nll.rs | 5 +- compiler/rustc_borrowck/src/region_infer/mod.rs | 6 +- compiler/rustc_borrowck/src/region_infer/values.rs | 104 ++------------------- .../src/type_check/liveness/local_use_map.rs | 8 +- .../rustc_borrowck/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 5b764495922..cc8208e9dc3 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 948221e9407..cbf01feae06 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 dc3ee849d00..01f7bfcadb6 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 7433c94a0bc..da5456692ab 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 e137bc1be0a..51ae7d14e43 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 c718d57bec3..eec128b5f1d 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 9c0f53ddb86..ea5593c09a9 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 f0b21fd4184..b805f8ca23e 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 00000000000..538e27ca1af --- /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 {} +} -- cgit 1.4.1-3-g733a5 From da235ce92db7270ad66ed7cd3e7bc8260c0c9b60 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Dec 2023 13:32:02 +0000 Subject: 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 538e27ca1af..161560516da 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 49b0edc0db8..49bb114609c 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(()) -- cgit 1.4.1-3-g733a5 From 3082028be3707e2e4c88af2cf4d9d8ccc352a230 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Dec 2023 13:33:56 +0000 Subject: 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 161560516da..c111ab2b881 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]; -- cgit 1.4.1-3-g733a5 From 1d6723a77a642850e60559c7d9c64b4b5233c9be Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Jan 2024 20:09:26 +0000 Subject: 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 c111ab2b881..ff17ce1fe07 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); }); } -- cgit 1.4.1-3-g733a5 From 3afeb241981a37d90b2f48f87322532e5552efff Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Mon, 8 Jan 2024 11:29:25 +0200 Subject: 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 | 573 ++++---- 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 | 125 +- crates/hir-ty/src/mir/lower/as_place.rs | 2 +- crates/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 +- crates/ide-assists/src/handlers/auto_import.rs | 15 +- crates/ide-assists/src/handlers/bool_to_enum.rs | 4 +- .../src/handlers/convert_let_else_to_match.rs | 1 + .../handlers/convert_nested_function_to_closure.rs | 4 +- .../convert_tuple_return_type_to_struct.rs | 2 +- .../handlers/extract_struct_from_enum_variant.rs | 72 +- .../ide-assists/src/handlers/extract_variable.rs | 2 +- .../src/handlers/generate_delegate_methods.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 344 ++--- .../ide-assists/src/handlers/generate_function.rs | 2 +- .../src/handlers/generate_mut_trait_impl.rs | 4 +- .../src/handlers/generate_trait_from_impl.rs | 10 +- crates/ide-assists/src/handlers/qualify_path.rs | 9 +- .../ide-assists/src/handlers/remove_parentheses.rs | 2 +- .../handlers/replace_derive_with_manual_impl.rs | 1 - crates/ide-completion/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 +- .../handlers/trait_impl_redundant_assoc_item.rs | 211 ++- .../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 | 292 +--- 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 | 513 ++++--- crates/ide/src/runnables.rs | 1518 ++------------------ crates/ide/src/static_index.rs | 13 +- crates/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 +- crates/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 +- crates/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 | 267 ++-- 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, 3088 insertions(+), 3605 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 c7d110eafb6..6670e92f51b 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 7054020086e..4ee8064b5e3 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 a45ec844aba..c728570d986 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 6ecf1c20d6c..02b19ade44b 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 b163112db91..a95b78614e8 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 591ee77c70a..5890e818c46 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 aea7229bd64..989bbc7bfb2 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 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. /// - /// 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, + /// 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)) } - }); + 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] + }; - 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()), - } + 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 { - 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, - ); + 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, + }; - let (infos, _) = - map.entry(item).or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::No)); - infos.reserve_exact(1); - infos.push(import_info); + 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, + ); + } - // 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); + 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 } - 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); - continue; - } - }; - let assoc_item = if is_type_in_ns { - ItemInNs::Types(module_def_id) - } else { - ItemInNs::Values(module_def_id) - }; + 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 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); + 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.map == other.map + self.item_to_info_map == other.item_to_info_map } } -impl Eq for ImportMap {} - 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)); - } - let mut stream = op.union(); + match query.search_mode { + SearchMode::Exact => { + let automaton = fst::automaton::Str::new(&query.lowercased); - 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 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); - // 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; + for map in &import_maps { + op = op.add(map.fst.search(&automaton)); } - 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)) - } - }) - }); - res.extend(iter); + search_maps(&import_maps, op.union(), query) + } + SearchMode::Prefix => { + let automaton = fst::automaton::Str::new(&query.lowercased).starts_with(); - if res.len() >= query.limit { - return res; + for map in &import_maps { + op = op.add(map.fst.search(&automaton)); } + search_maps(&import_maps, op.union(), query) + } + } +} + +fn search_maps( + import_maps: &[Arc], + mut stream: fst::map::Union<'_>, + query: &Query, +) -> FxHashSet { + let mut res = FxHashSet::default(); + while let Some((_, indexed_values)) = stream.next() { + 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]; + + 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.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 22ba3aab4e9..250d7b677b5 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 3763bfcbcfa..a18ac4b28c4 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 f7a26e436de..ed04582cb0a 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 b5197d4c25d..6a122e0859c 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 1873e7bfe6a..c7807bcf9aa 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 9792d945eb8..5528ad3ab4a 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 d81926f7c97..23d95154221 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 8053300ad22..a78e3e7dc25 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 af74df1032c..118b9c0149f 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 84954ca7e90..db631c8517c 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 b8a1af96fba..663ea853231 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 acdb540289d..1bf8babe836 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 e4dd4b86cf9..eb6296f7a04 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 bfc4f1383ec..68619bb8b18 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 9937113685c..ef0be7ab2da 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 cf174feed24..793b52b49fa 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 041d61c1b15..33619edfee9 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 f1795e71d94..7bef6f0d0f7 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 74c5efd6c3f..e79c87a02f4 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 fbfb6ff8cdd..16075d90734 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(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(f) => { + 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 2de99e41659..ff26a3d0be1 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 b0f929279a5..6552bf49337 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 639fabc198c..c02c5ef8767 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 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 bytes = b.iter().copied().chain(iter::once(0)).collect::>(); + + 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 8c078eb4ad7..cb5588a5c13 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 1120bb1c112..98c2e7c63bc 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 a91f90bc249..366c2f662b5 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 003ae60e8e5..d270328605a 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 d60d20f5b7e..60ddc4aa86f 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 5847c8a9fb5..9b99b141fc5 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 09b56e13824..0266915c39b 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 fdc604a006f..f51fe80931c 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 54b4d81012f..73f8db762ae 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 4da0dfba675..841ddfb9c43 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 1f785b5d0a8..7b71d9b8696 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 b7b00e7ed06..dc1952c3ff3 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 5f7056b9c1c..79c34c14da7 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 399f87c8f50..c30f3e1c3b2 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 79b46d66121..41366658a74 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 37db27a8fc0..65e2a018477 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 874b81d3b63..0b3bd0bed6e 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 db1e0ceaec1..dc02aaf9af6 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 0d34502add9..339c3ac71ec 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(); - - // 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); + let trait_gen_params = remove_instantiated_params( + &old_impl.self_ty()?, + old_impl_params.clone(), + &old_impl_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 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() }; - - // 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)); - } + 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(); - - 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); - }, - ) - } + 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(); + + 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 5bb200e84a4..50528e1caaa 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 cb8ef395650..d90d366ffe4 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 0f67380d12b..315b6487b51 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 fde46db3058..08648718490 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 0281b29cd42..99c55e9ff7c 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 b54e4204e3f..788cc846c2a 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 d74d3b264ae..446f0be8348 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 ff324e7a56d..6a98e109f6d 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 c58374f2e83..1af16ef857d 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 ded5d4e3db5..8f55f30a2dd 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 a4f0a6df781..652968d808f 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 4a5d234f73d..432f1d745d2 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 8c1a6e6e40b..edfeddc1bc9 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 7f28965885a..f694f7160de 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 dbef3602682..a40dd2692cf 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 c7188f1f794..73be6a4071e 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 f5f0f0576f2..c2e95ca860c 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, - only_types: bool, - libs: bool, mode: SearchMode, + assoc_mode: AssocSearchMode, case_sensitive: bool, - limit: usize, + only_types: bool, + libs: bool, } 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 c202264bb56..6ecfd55ea02 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 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 db = ctx.sema.db; 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 60a45a05a4a..41fb6729085 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 e90d385bab8..4d7d425bab3 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)))) + _ => None, + }; + + 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::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::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::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) + Definition::Local(it) => { + render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| 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 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 e82d730e4a3..f466b8e938f 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 c9e9a223786..b6063978e92 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 00000000000..50ab15c504f --- /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 6ff16b9e2f7..c98e9fba120 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 8e8bb5e0139..486329daded 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 6cb7d7724d5..bc0574ca86e 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 1febfabfcb7..3bf41defe34 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, - }, - ], + ), + [ + Indel { + insert: "foo2", + delete: 4..7, }, - None, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 2, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + 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, - }, - ], + ), + [ + Indel { + insert: "quux", + delete: 11..14, }, - None, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + 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, - }, - ], + ), + [ + Indel { + insert: "bar", + delete: 16..19, }, - None, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 1, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + 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, - }, - ], + ), + [ + Indel { + insert: "foo2", + delete: 8..11, }, - None, + ], + ), + ] + file_system_edits: [ + MoveFile { + src: FileId( + 2, ), - }, - file_system_edits: [ - MoveFile { - src: FileId( + 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, - }, - ], + ), + [ + Indel { + insert: "foo2", + delete: 4..7, }, - None, + ], + ), + ] + 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, - }, - ], + ), + [ + Indel { + insert: "r#fn", + delete: 4..7, }, - None, + 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, - }, - ], + ), + [ + Indel { + insert: "foo", + delete: 4..8, }, - None, + 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 d334e66d3dd..352ce89820d 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, - }, - 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: 121..185, + focus_range: 136..145, + name: "foo2_test", + kind: Function, + }, + 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 3724dc28221..5b7094e6bcc 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 0558f658fd1..d686652bb3e 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 71f4d07245d..6bf13ffd06f 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 e8b3a38c9e0..4063cf9f757 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 afb6c555b4a..864c6d1cad7 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 3802978f494..53f998e5457 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 55be6bc23bb..90545bb5130 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 d89c4598afc..bc1fcd08e20 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 fe046dd1463..d52e448d747 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 4057493fa3a..00cc7c30ee3 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 1908c73b3b4..e69302dbacc 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 95c8798d43c..c86b2c0ba40 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 88fb3708449..fe009f82a71 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 f1317ce2b40..13544558c50 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 69b88b5a17b..a4abba29bb9 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 71e269f74bc..43909fff02c 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 1e691befff6..cc90d2dd1d5 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 4c2878f49f0..aa56f10d609 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 36980b146ef..18a56e2823a 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) - } - - pub fn op_token(&self) -> Option { - self.op_details().map(|t| t.1) - } +impl RangeItem for ast::RangeExpr { + type Bound = ast::Expr; - 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 2abbfc81f67..b1dd1fe8c82 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 a7e4899fb7e..8618018c0b6 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 8e04ab8bedc..9ddf5a0a980 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 2b1bbac08e5..eabbda2c398 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 a5f1811bf24..bb77aa0eaae 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: - -* `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). +`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. -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. - -[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 +`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/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 c3f249e0ce2..ecc90abff13 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 9fc19a7d074..fa8413c19ae 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 27ed8ac502b..8307f6833e6 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 987d936943a..51a0aece820 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 63ae386c8ad..55163241c2a 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 3073353674c..599cfb4ff77 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 187a1a96c10..bf65ad43ba5 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 c74284a00d9..87cfd1b2ee1 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 00000000000..93ac03696a0 --- /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. -- cgit 1.4.1-3-g733a5 From 7dd9f20ce30a22f1e10e02627bf98bee7c61f176 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 10:37:09 +0100 Subject: Builtin derives are hygienic --- .../macro_expansion_tests/builtin_derive_macro.rs | 83 ++++++++------- .../src/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 abd84c6a46d..553c0b79533 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 d4798f4507d..4690ca5d363 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 8f240ef0732..46bbb7f92c0 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 f99a8917623..65a55f8b5b8 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 9bdd75f9d22..a3b84afd2ae 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 d16e0eb0137..622b4f56d4f 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 024053effe4..17c701ad035 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 1f3136404c6..140bb080427 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 -- cgit 1.4.1-3-g733a5 From 1c40ac79c8570a05b143823159bbc83904bf9730 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 7 Jan 2024 20:31:56 +0100 Subject: VFS no longer stores all source files in memory --- crates/load-cargo/src/lib.rs | 5 +- crates/rust-analyzer/src/global_state.rs | 83 ++++++++-------- crates/rust-analyzer/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 556ed73a04c..ee0b9e6d504 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 f57a27305f0..da132f93968 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 7e6219991b6..c0d35498c66 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 13544558c50..22c7e9b0503 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 a4417e4d4a1..fa5ea5b57db 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 cdf41c955d2..356c332f90d 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 45a1dab9772..6a93a0ebb4c 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 91dc6c2e4b4..8e3fa7fa4da 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 ef5b10ee9db..34a85818eb8 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, 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, Copy, Clone, Debug)] +#[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`. - /// - /// # 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`. + /// Returns the status of the file 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] } } -- cgit 1.4.1-3-g733a5 From 72200641c1702fe143ba11218c3ecc6604c3d9db Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:09:19 +0100 Subject: fix: Fix incorrect parsing error on method call on range --- crates/parser/src/grammar/expressions.rs | 10 ++++- .../inline/ok/0208_closure_range_method_call.rast | 49 ++++++++++++++++++++++ .../inline/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 e346ece2f94..c8626111145 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 00000000000..542711339d1 --- /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 00000000000..a81d3c37133 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs @@ -0,0 +1,4 @@ +fn foo() { + || .. .method(); + || .. .field; +} -- cgit 1.4.1-3-g733a5 From b97ab00bd404bc5e6fb3eb92a123062a02ab7f23 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:24:46 +0100 Subject: 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 6670e92f51b..98ae47640f2 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 4ee8064b5e3..296ccb2dfaa 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 0c63484634b..e74b340126c 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 b9e7566fdf9..f47ec49df1d 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 d9b3f46f200..ed0aec3cab3 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 0bf04301df1..ae8abc6cc7b 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 13fcbc49193..d3f386fe08a 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 40a93fec2ce..9f78614bba6 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 d5d565a015a..ede392fc62a 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 d600698040d..1b41596a5f2 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 eabbda2c398..6c6916c585f 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, -- cgit 1.4.1-3-g733a5 From e25e0dd0adb7bc4b402872af8414e7d99e0adec0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:30:26 +0100 Subject: 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 98ae47640f2..547940c91d6 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 296ccb2dfaa..1734c55a3f2 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 5933d30040f..fea7d81c6a6 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 7fc33abc7c9..c0d1738b504 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 250d7b677b5..9d042ea9354 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 ae8abc6cc7b..a14cc60860c 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 d3f386fe08a..d2aafe8a02b 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; -- cgit 1.4.1-3-g733a5 From f972da70d4b6ce79e43e07f68002227fd4db86f2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 15:39:35 +0100 Subject: 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 547940c91d6..b1a1c8fb9fd 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 1734c55a3f2..a81c4659636 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 fea7d81c6a6..523ff6fc404 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 a95b78614e8..8772c34f02f 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 9d042ea9354..aa84ccaee6e 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 c7807bcf9aa..803c18677da 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 68619bb8b18..b7bfaf2931b 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 39788a95029..8a7715ce872 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 793b52b49fa..e72864a12ee 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 ad24d6d28cd..76414160716 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 a14cc60860c..00000000000 --- 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 d2aafe8a02b..00000000000 --- 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::*; -} -- cgit 1.4.1-3-g733a5 From df5c6479823fda0c346e00f6cc89fcaa2f03168e Mon Sep 17 00:00:00 2001 From: dfireBird Date: Sat, 6 Jan 2024 15:48:10 +0530 Subject: 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 26f76afb1f0..dfee397619c 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 108b040de6b..92aa1da89c4 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 de41a5bd70c..affd9b72964 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 581d557e831..f924c9aedb6 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 b306bede653..ccd312b03fb 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() }); -- cgit 1.4.1-3-g733a5 From d94f572fe249e1adc95a2dc876cc9f1d028c47bb Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Mon, 8 Jan 2024 18:10:48 +0100 Subject: 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 97e376787c8..fd6f220f4fa 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 -- cgit 1.4.1-3-g733a5 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: 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 d969ab10ef5..0b42ff1771e 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. -- cgit 1.4.1-3-g733a5 From 0ae73738adfbe0a6eaceed6b198cd3a124bce77c Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Tue, 9 Jan 2024 08:56:53 +0200 Subject: 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 f1575a5b0bd..67b9f57a163 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; -- cgit 1.4.1-3-g733a5 From b0b2b1c5f1c4d4d989d0e21ebfe575db2cbf4e18 Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Tue, 9 Jan 2024 10:00:57 +0200 Subject: 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 ef0be7ab2da..57214193cfb 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)*), -- cgit 1.4.1-3-g733a5 From 4413aeb9e8a710bcbc11e90cb87f3ba7420c851f Mon Sep 17 00:00:00 2001 From: Laurențiu Nicola Date: Tue, 9 Jan 2024 10:27:36 +0200 Subject: 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 78411e2d58d..f76ff7db38c 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; } -- cgit 1.4.1-3-g733a5 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: 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 8b9d5d4a746..291cef926f8 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": [ { -- cgit 1.4.1-3-g733a5 From e1c67485bf02bdaa1234df174a48aba402a2d707 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 10:30:16 +0100 Subject: 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 ++++++++-------- crates/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 ee0b9e6d504..e6ddfd580c3 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 00cc7c30ee3..c04eddc56fb 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 da132f93968..c4a29e0cbb0 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 c0d35498c66..ce69d612255 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 356c332f90d..ca7893faf5d 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 f76ff7db38c..78411e2d58d 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 03065043714..19b34ffe6b9 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 e2d74782ae5..89a544c81d8 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) -- cgit 1.4.1-3-g733a5 From a8c94eaf131cdadad07296fd1d69edeb51aa0970 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 16:28:18 +0100 Subject: 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 3494164c067..0f64f9195d8 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( -- cgit 1.4.1-3-g733a5 From 21a953fe37635d5f37a49af5505f6391ed62e53d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 8 Jan 2024 11:40:27 +0100 Subject: 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 a87becd63e2..208051113a7 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 3494164c067..a22d8628f16 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 87f7555b02c..af9a03826ff 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))] -- cgit 1.4.1-3-g733a5 From 7a7bb3ef85ca2f827c39db9fd1594db5162cea13 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Mon, 8 Jan 2024 14:43:31 +0100 Subject: 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 f6835472e2c..8bf1e2dca6f 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; -- cgit 1.4.1-3-g733a5 From 342ea154906163a678c257469823d7c7383014d6 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 10:08:47 +0100 Subject: Add tests --- tests/ui/pattern/never_patterns.rs | 23 ------------ tests/ui/pattern/never_patterns.stderr | 34 +---------------- tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs | 28 ++++++++++++++ .../rfcs/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 915f3e75e7b..eb2421204ae 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 11e50debfd3..f3787f9816a 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 00000000000..61a4231e5da --- /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 00000000000..56cefcb51f3 --- /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`. -- cgit 1.4.1-3-g733a5 From b31735a401941910f5ae2fbf06eba8594a1b2d4b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 22 Nov 2023 01:15:36 +0100 Subject: 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 a82f7bdfbf3..536ecd0fa24 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)); - - let inners = inners.collect::>(); + .flat_map(|(map, _)| map); - 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`. -- cgit 1.4.1-3-g733a5 From 560beb1ad423a9f3e447bdeefded8994cd8af75c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 10:11:18 +0100 Subject: 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-gates/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 +++++----- tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs | 11 ++-- .../rfcs/rfc-0000-never_patterns/bindings.stderr | 47 ++++++----------- tests/ui/rfcs/rfc-0000-never_patterns/parse.rs | 1 + tests/ui/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 3f8df16e03f..c8ec10cad17 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 c1cb20f6bb0..5f53733276a 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 1fdb193e571..821b1e946f3 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 536ecd0fa24..90b27856161 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 a14f3d494fb..5a9bf22de51 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 f3910622313..d23405ada2d 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 dd10829d495..3181dac69e5 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 eb2421204ae..8f44f8a6559 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 f3787f9816a..20eeb01cf71 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 + | + = 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) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns +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 61a4231e5da..756ead9e184 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 56cefcb51f3..4e83b843ae8 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 5 previous errors +error: aborting due to 4 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 f254b9c201c..566bb071646 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 e81a13a3967..17d1b7e0d43 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 -- cgit 1.4.1-3-g733a5 From 807d618676052befa3e621dc42e7be0b4c5f1576 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 9 Jan 2024 17:05:55 +0100 Subject: 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 90b27856161..2a8bf1fe2d3 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) { -- cgit 1.4.1-3-g733a5 From 223cda41071416c20d3d1db458ce7c6c789e2b08 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 9 Jan 2024 17:04:20 +0100 Subject: 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 2a8bf1fe2d3..5c246893d87 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. -- cgit 1.4.1-3-g733a5 From 06aaf20f1000fca742fdb84f016d46c45b6f36d6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 20:43:17 +0100 Subject: 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 a0a55df5f99..28931676eed 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 f5324f052e5..26a836f25e9 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 75adf21abdc..935a8ebad16 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 8e2fafe81b5..6343b43a016 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 97c4a741ff2..e371e427615 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 33619edfee9..3b1697a07b0 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 db6cd128e83..6399f83c475 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 128971994f6..79531936fde 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 c98e9fba120..60a9367adce 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>) { -- cgit 1.4.1-3-g733a5 From 967391504523adadc01c70f675a0d66923df1c32 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 20:52:10 +0100 Subject: 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 d5831022f28..8c1e3aca98e 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 7204868464b..403a6c88ab0 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 6399f83c475..259d141404d 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 -- cgit 1.4.1-3-g733a5 From 4e16e0f2c126c7250c16d7c2256da169a602b215 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 21:06:21 +0100 Subject: 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 26f76afb1f0..a0dfcb6a286 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 8c1e3aca98e..70c0d5193d4 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 1ae6bd4c919..66e0d2cc346 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 60ddc4aa86f..5a21f41dca8 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()) -- cgit 1.4.1-3-g733a5 From c4b3075be0d2829de5172c38969b0f5d0ea06292 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 21:20:03 +0100 Subject: 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 f4fbace19e3..e81d4ced554 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 410bcbf0356..ad790fa094d 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 3b1697a07b0..06df30582aa 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()); } -- cgit 1.4.1-3-g733a5 From f8b130a6aa437a1e9626db89db1252c325c868d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 9 Jan 2024 21:30:01 +0100 Subject: 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 26a836f25e9..6cb9b8448d1 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 { -- cgit 1.4.1-3-g733a5 From beeaaf184ee1b896450ac98bad3aa9a62e3413bc Mon Sep 17 00:00:00 2001 From: Zach Date: Tue, 9 Jan 2024 17:09:50 -0600 Subject: 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 c7ad09e7ebd..c4ced1e1211 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), -- cgit 1.4.1-3-g733a5 From d5c39d0638221f07e7172b61e6c1e70cd2fee6bc Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 9 Jan 2024 20:30:53 -0800 Subject: 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 75c7de4f405..4d917ec6f91 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 5dbfe4aa2ac..5b32bc5117c 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'] } -- cgit 1.4.1-3-g733a5 From bc54775c9d7026b1ca616ca43fd34ff6f53d668a Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 10 Jan 2024 15:00:35 +0800 Subject: Preserve comments for extracted block expr in 'extract_function' assist --- crates/ide-assists/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 347a3e9ba07..3d91cb6a0f8 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)); -- cgit 1.4.1-3-g733a5 From d327f3036c2db0cffb91807c301d48f8e37165e2 Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 10 Jan 2024 15:00:58 +0800 Subject: Add test 'comments_in_block_expr' in in 'extract_function' --- .../ide-assists/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 3d91cb6a0f8..1eb28626f75 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); -- cgit 1.4.1-3-g733a5 From 9c2d331e1696aba883a0d220c0dc445dc82ace0d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 10 Jan 2024 08:47:26 +0100 Subject: Bump salsa --- Cargo.lock | 23 +++++++++++++++++------ Cargo.toml | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1a1c8fb9fd..15d06222eb4 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 a81c4659636..35bef151196 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"] } -- cgit 1.4.1-3-g733a5 From 500d6f64791d4f9576c8588ef2cdeab4a3139a02 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 3 Nov 2023 21:56:06 -0400 Subject: 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 cfa54072eb9..c149b659a4f 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 9512d45740f..a425beb1c9a 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 15e58a4e53f..df7b34ce73b 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)] -- cgit 1.4.1-3-g733a5 From 4b7b602da9e11840aacd063d9485a0a8166d6960 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 5 Jan 2024 15:18:02 +0100 Subject: Remove sysroot-abi feature flag from proc-macro-test --- crates/proc-macro-srv/Cargo.toml | 2 +- crates/proc-macro-srv/proc-macro-test/Cargo.toml | 3 --- crates/proc-macro-srv/proc-macro-test/build.rs | 28 ++++++++++++---------- .../proc-macro-srv/proc-macro-test/imp/Cargo.toml | 3 --- .../proc-macro-srv/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 9c4375559c1..ba17ea6f7b4 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 90545bb5130..7977afb1cbd 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 7299147686d..6cf2b5643e5 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 dc94fcd61a4..fa189752b76 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 b8aad4acefc..d9018b1b87d 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)] -- cgit 1.4.1-3-g733a5 From 257870e09f0f56ce5e2588948b00e2bf04ce304c Mon Sep 17 00:00:00 2001 From: dfireBird Date: Wed, 10 Jan 2024 16:30:22 +0530 Subject: 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 f924c9aedb6..8c0e6694761 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 ccd312b03fb..6ad84eba33b 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()); } -- cgit 1.4.1-3-g733a5 From 1aff8157bcf9d9cf3d5358c60c28b0b896e18d19 Mon Sep 17 00:00:00 2001 From: Zach Date: Wed, 10 Jan 2024 05:58:25 -0600 Subject: 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 f1c95993c84..551021c55a9 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 c4ced1e1211..c7ad09e7ebd 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), -- cgit 1.4.1-3-g733a5 From 4d3a0dc3291c527fc186c4e24babc6ad5b16ab35 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 10 Jan 2024 14:51:51 +0100 Subject: 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 28931676eed..c2ab9506489 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 f4a6b61f7af..c992c3c9204 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 6f4aef22d2f..d0a1fb1d576 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 841ddfb9c43..9ae5bb26932 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 79531936fde..eae23e95482 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) } } -- cgit 1.4.1-3-g733a5 From fcaeb4542173b364835aef7dd2526303191b2d2c Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 10 Jan 2024 17:12:01 +0200 Subject: 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 75c7de4f405..dc44041141b 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 fdac789423c..c57e964168f 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 319e8175809..a238eacda44 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 08cc8173eb0..79d3482472a 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" } -- cgit 1.4.1-3-g733a5 From 1dc3ab02cdba905aa1cce73d938c8e825107a8e8 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 10 Jan 2024 17:13:03 +0200 Subject: 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 74e7afee7bc..6d6a1200f50 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 cfa46447845..764306ce6ec 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 92a6445ed09..a09bb3c5fd0 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 -- cgit 1.4.1-3-g733a5 From 08fc5e8acd1bc41fbf5b8a4b5c96a42c16bab158 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:03:05 +0000 Subject: Define hidden types in confirmation --- .../rustc_trait_selection/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 dd4e69efe37..abbc2066eac 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 00000000000..16b78f18aa3 --- /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() {} -- cgit 1.4.1-3-g733a5 From 0ae00444dc075c814dd061aa1cfdc5c461c1f608 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:05:24 +0000 Subject: 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 16b78f18aa3..d2091ca96ea 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` -- cgit 1.4.1-3-g733a5 From 76aaf17794c37cb134fc968d04e1982958af12fd Mon Sep 17 00:00:00 2001 From: Patryk Wychowaniec Date: Fri, 5 Jan 2024 11:00:29 +0100 Subject: 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 +- crates/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 4737b48703d..e8086be86f4 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 4902f24e2e3..0a6ba88065d 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 52a981fd19e..a97f57f5531 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 be3438e427d..700264839b9 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 49688c5ee9c..163484e241b 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 30b8c189f52..4618dcec70b 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 d81926f7c97..b01f742c3d1 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 1f785b5d0a8..43c2f820274 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 dbef3602682..6ea604740c6 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()); } -- cgit 1.4.1-3-g733a5 From 68a13bf7fd0e456969ea591fc216bf44eea9890d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:07:48 +0100 Subject: 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 5c246893d87..e100c925478 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| { -- cgit 1.4.1-3-g733a5 From 5ccd29d6f0c8e8f678bb05adfd8482de0ecde0c2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:08:53 +0100 Subject: Add more tests --- tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs | 21 +++++++++++++++++ .../rfcs/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 756ead9e184..f2e238ecb13 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 4e83b843ae8..b69ba80af88 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 -- cgit 1.4.1-3-g733a5 From fb44c848c3899ed4ece01e63070a45a532e357fc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:34:54 +0000 Subject: 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 ++-------------- .../borrowck/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 11b5b437eff..db46b39ce25 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 aed111e2144..7197a4fb91a 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 77a0ea5027c..19512116a66 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 2 previous errors +error: aborting due to 1 previous error -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 c10246eec64..b52939ffc11 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 2b10cf67d15..516c1d065e6 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 3 previous errors +error: aborting due to 2 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 63f4898f430..7ba8579e24f 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 0e86561aa27..44c20a7be53 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 e16199caaaa..4a89238d07e 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 55e966bd7bf..88fb1fb2707 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 2 previous errors +error: aborting due to 1 previous error -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`. -- cgit 1.4.1-3-g733a5 From 0aedd6e86fd11c146b1bf8f0c38415ca7e66f240 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Jan 2024 18:34:25 +0000 Subject: Sandwich MIR optimizations between DSE. --- .../src/dead_store_elimination.rs | 12 +++- compiler/rustc_mir_transform/src/lib.rs | 9 +-- ...e.main.DataflowConstProp.32bit.panic-abort.diff | 15 ++-- ....main.DataflowConstProp.32bit.panic-unwind.diff | 15 ++-- ...e.main.DataflowConstProp.64bit.panic-abort.diff | 15 ++-- ....main.DataflowConstProp.64bit.panic-unwind.diff | 15 ++-- ...ult_boxed_slice.main.GVN.32bit.panic-abort.diff | 15 ++-- ...lt_boxed_slice.main.GVN.32bit.panic-unwind.diff | 15 ++-- ...ult_boxed_slice.main.GVN.64bit.panic-abort.diff | 15 ++-- ...lt_boxed_slice.main.GVN.64bit.panic-unwind.diff | 15 ++-- ...ked.DeadStoreElimination-final.panic-abort.diff | 15 ++++ ...ed.DeadStoreElimination-final.panic-unwind.diff | 15 ++++ ...ve_packed.DeadStoreElimination.panic-abort.diff | 15 ---- ...e_packed.DeadStoreElimination.panic-unwind.diff | 15 ---- ...ple.DeadStoreElimination-final.panic-abort.diff | 23 ++++++ ...le.DeadStoreElimination-final.panic-unwind.diff | 23 ++++++ ...ve_simple.DeadStoreElimination.panic-abort.diff | 23 ------ ...e_simple.DeadStoreElimination.panic-unwind.diff | 23 ------ .../dead-store-elimination/call_arg_copy.rs | 12 ++-- .../cycle.cycle.DeadStoreElimination-initial.diff | 29 ++++++++ .../cycle.cycle.DeadStoreElimination.diff | 29 -------- tests/mir-opt/dead-store-elimination/cycle.rs | 9 ++- ..._mention.main.DeadStoreElimination-initial.diff | 19 +++++ .../place_mention.main.DeadStoreElimination.diff | 19 ----- .../dead-store-elimination/place_mention.rs | 15 ++-- ...ointer_to_int.DeadStoreElimination-initial.diff | 35 +++++++++ ...ndness.pointer_to_int.DeadStoreElimination.diff | 35 --------- ...ndness.retags.DeadStoreElimination-initial.diff | 14 ++++ ...ance_soundness.retags.DeadStoreElimination.diff | 14 ---- .../dead-store-elimination/provenance_soundness.rs | 18 +++-- ...on.main.DestinationPropagation.panic-abort.diff | 10 ++- ...n.main.DestinationPropagation.panic-unwind.diff | 10 ++- ...loat_to_exponential_common.GVN.panic-abort.diff | 34 ++++++++- ...oat_to_exponential_common.GVN.panic-unwind.diff | 34 ++++++++- .../inline_coroutine.main.Inline.panic-abort.diff | 2 +- .../inline_coroutine.main.Inline.panic-unwind.diff | 2 +- .../inline_diverging.h.Inline.panic-abort.diff | 2 +- .../inline_diverging.h.Inline.panic-unwind.diff | 2 +- ...wrap_unchecked.PreCodegen.after.panic-abort.mir | 2 +- ...rap_unchecked.PreCodegen.after.panic-unwind.mir | 2 +- .../issue_101973.inner.GVN.panic-abort.diff | 14 +++- .../issue_101973.inner.GVN.panic-unwind.diff | 14 +++- ...reading.identity.JumpThreading.panic-abort.diff | 4 +- ...eading.identity.JumpThreading.panic-unwind.diff | 4 +- ...nvalid_constant.main.GVN.32bit.panic-abort.diff | 16 ++++- ...valid_constant.main.GVN.32bit.panic-unwind.diff | 16 ++++- ...nvalid_constant.main.GVN.64bit.panic-abort.diff | 16 ++++- ...valid_constant.main.GVN.64bit.panic-unwind.diff | 16 ++++- .../loops.filter_mapped.PreCodegen.after.mir | 2 +- .../loops.int_range.PreCodegen.after.mir | 2 +- .../pre-codegen/loops.mapped.PreCodegen.after.mir | 2 +- .../mem_replace.mem_replace.PreCodegen.after.mir | 19 ++--- ...s_into_variable.main.GVN.32bit.panic-abort.diff | 8 ++- ..._into_variable.main.GVN.32bit.panic-unwind.diff | 8 ++- ...s_into_variable.main.GVN.64bit.panic-abort.diff | 8 ++- ..._into_variable.main.GVN.64bit.panic-unwind.diff | 8 ++- ...r.forward_loop.PreCodegen.after.panic-abort.mir | 2 +- ....forward_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...inclusive_loop.PreCodegen.after.panic-abort.mir | 2 +- ...nclusive_loop.PreCodegen.after.panic-unwind.mir | 2 +- ..._get_mut_usize.PreCodegen.after.panic-abort.mir | 13 ++-- ...get_mut_usize.PreCodegen.after.panic-unwind.mir | 13 ++-- ...cked_mut_range.PreCodegen.after.panic-abort.mir | 17 +++-- ...ked_mut_range.PreCodegen.after.panic-unwind.mir | 17 +++-- ...numerated_loop.PreCodegen.after.panic-abort.mir | 19 ++--- ...umerated_loop.PreCodegen.after.panic-unwind.mir | 19 ++--- ...r.forward_loop.PreCodegen.after.panic-abort.mir | 17 +++-- ....forward_loop.PreCodegen.after.panic-unwind.mir | 17 +++-- ...ter.range_loop.PreCodegen.after.panic-abort.mir | 2 +- ...er.range_loop.PreCodegen.after.panic-unwind.mir | 2 +- ...r.reverse_loop.PreCodegen.after.panic-abort.mir | 19 ++--- ....reverse_loop.PreCodegen.after.panic-unwind.mir | 19 ++--- .../try_identity.new.PreCodegen.after.mir | 8 +-- .../try_identity.old.PreCodegen.after.mir | 4 +- ..._const_switch.identity.SeparateConstSwitch.diff | 82 ++++++++++++---------- ...nst_switch.too_complex.SeparateConstSwitch.diff | 41 +++++------ .../simplify_match.main.GVN.panic-abort.diff | 10 ++- .../simplify_match.main.GVN.panic-unwind.diff | 10 ++- 78 files changed, 696 insertions(+), 439 deletions(-) create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff delete mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff delete mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff delete mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff delete mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff create mode 100644 tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff delete mode 100644 tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff create mode 100644 tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff delete mode 100644 tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff create mode 100644 tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff delete mode 100644 tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff create mode 100644 tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff delete mode 100644 tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3d74ef7e327..9dd5aa4c8bd 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 ce9043ec287..4e8afcd7d2f 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 6925fdb1e70..ffbd97bb545 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 82ad842505c..7b6dcf1972b 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 6925fdb1e70..ffbd97bb545 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 82ad842505c..7b6dcf1972b 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 13545aa464a..df68ce496fd 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 bf326915381..e16ea22091e 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 13545aa464a..df68ce496fd 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 bf326915381..e16ea22091e 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-final.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff new file mode 100644 index 00000000000..07fb8301b9a --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff @@ -0,0 +1,15 @@ +- // MIR for `move_packed` before DeadStoreElimination-final ++ // MIR for `move_packed` after DeadStoreElimination-final + + fn move_packed(_1: Packed) -> () { + let mut _0: (); + + bb0: { + _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff new file mode 100644 index 00000000000..cac3badfa67 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff @@ -0,0 +1,15 @@ +- // MIR for `move_packed` before DeadStoreElimination-final ++ // MIR for `move_packed` after DeadStoreElimination-final + + fn move_packed(_1: Packed) -> () { + let mut _0: (); + + bb0: { + _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind continue]; + } + + bb1: { + return; + } + } + 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.panic-abort.diff deleted file mode 100644 index dc0f9073416..00000000000 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff +++ /dev/null @@ -1,15 +0,0 @@ -- // MIR for `move_packed` before DeadStoreElimination -+ // MIR for `move_packed` after DeadStoreElimination - - fn move_packed(_1: Packed) -> () { - let mut _0: (); - - bb0: { - _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind unreachable]; - } - - bb1: { - return; - } - } - 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.panic-unwind.diff deleted file mode 100644 index 86ef026ec5c..00000000000 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff +++ /dev/null @@ -1,15 +0,0 @@ -- // MIR for `move_packed` before DeadStoreElimination -+ // MIR for `move_packed` after DeadStoreElimination - - fn move_packed(_1: Packed) -> () { - let mut _0: (); - - bb0: { - _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind continue]; - } - - bb1: { - return; - } - } - 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 new file mode 100644 index 00000000000..268924b7c5d --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff @@ -0,0 +1,23 @@ +- // MIR for `move_simple` before DeadStoreElimination-final ++ // MIR for `move_simple` after DeadStoreElimination-final + + fn move_simple(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); +- let mut _3: i32; +- let mut _4: i32; + + bb0: { + StorageLive(_2); +- _2 = use_both(_1, _1) -> [return: bb1, unwind unreachable]; ++ _2 = use_both(_1, move _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_2); + _0 = const (); + return; + } + } + 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 new file mode 100644 index 00000000000..bd754f9ebd4 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff @@ -0,0 +1,23 @@ +- // MIR for `move_simple` before DeadStoreElimination-final ++ // MIR for `move_simple` after DeadStoreElimination-final + + fn move_simple(_1: i32) -> () { + debug x => _1; + let mut _0: (); + let _2: (); +- let mut _3: i32; +- let mut _4: i32; + + bb0: { + StorageLive(_2); +- _2 = use_both(_1, _1) -> [return: bb1, unwind continue]; ++ _2 = use_both(_1, move _1) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_2); + _0 = const (); + return; + } + } + 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.panic-abort.diff deleted file mode 100644 index 8f799b33f45..00000000000 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff +++ /dev/null @@ -1,23 +0,0 @@ -- // MIR for `move_simple` before DeadStoreElimination -+ // MIR for `move_simple` after DeadStoreElimination - - fn move_simple(_1: i32) -> () { - debug x => _1; - let mut _0: (); - let _2: (); -- let mut _3: i32; -- let mut _4: i32; - - bb0: { - StorageLive(_2); -- _2 = use_both(_1, _1) -> [return: bb1, unwind unreachable]; -+ _2 = use_both(_1, move _1) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_2); - _0 = const (); - return; - } - } - 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.panic-unwind.diff deleted file mode 100644 index 0551d663b50..00000000000 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff +++ /dev/null @@ -1,23 +0,0 @@ -- // MIR for `move_simple` before DeadStoreElimination -+ // MIR for `move_simple` after DeadStoreElimination - - fn move_simple(_1: i32) -> () { - debug x => _1; - let mut _0: (); - let _2: (); -- let mut _3: i32; -- let mut _4: i32; - - bb0: { - StorageLive(_2); -- _2 = use_both(_1, _1) -> [return: bb1, unwind continue]; -+ _2 = use_both(_1, move _1) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_2); - _0 = const (); - return; - } - } - 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 490a4aa502c..37b3313f7d0 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-initial.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff new file mode 100644 index 00000000000..f13588c3aa4 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff @@ -0,0 +1,29 @@ +- // MIR for `cycle` before DeadStoreElimination-initial ++ // MIR for `cycle` after DeadStoreElimination-initial + + fn cycle(_1: i32, _2: i32, _3: i32) -> () { + let mut _0: (); + let mut _4: bool; +- let mut _5: i32; + + bb0: { + _4 = cond() -> [return: bb1, unwind continue]; + } + + bb1: { + switchInt(_4) -> [1: bb2, otherwise: bb3]; + } + + bb2: { +- _5 = _3; +- _3 = _2; +- _2 = _1; +- _1 = _5; + _4 = cond() -> [return: bb1, unwind continue]; + } + + bb3: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff deleted file mode 100644 index cf73358dc52..00000000000 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff +++ /dev/null @@ -1,29 +0,0 @@ -- // MIR for `cycle` before DeadStoreElimination -+ // MIR for `cycle` after DeadStoreElimination - - fn cycle(_1: i32, _2: i32, _3: i32) -> () { - let mut _0: (); - let mut _4: bool; -- let mut _5: i32; - - bb0: { - _4 = cond() -> [return: bb1, unwind continue]; - } - - bb1: { - switchInt(_4) -> [1: bb2, otherwise: bb3]; - } - - bb2: { -- _5 = _3; -- _3 = _2; -- _2 = _1; -- _1 = _5; - _4 = cond() -> [return: bb1, unwind continue]; - } - - bb3: { - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index 13e5411275d..e8f566b4aa7 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-initial.diff b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff new file mode 100644 index 00000000000..5a550285871 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff @@ -0,0 +1,19 @@ +- // MIR for `main` before DeadStoreElimination-initial ++ // MIR for `main` after DeadStoreElimination-initial + + fn main() -> () { + let mut _0: (); + let mut _1: (&str, &str); + scope 1 { + } + + bb0: { + StorageLive(_1); + _1 = (const "Hello", const "World"); + PlaceMention(_1); + StorageDead(_1); + _0 = const (); + return; + } + } + 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.diff deleted file mode 100644 index 2130518771a..00000000000 --- a/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff +++ /dev/null @@ -1,19 +0,0 @@ -- // MIR for `main` before DeadStoreElimination -+ // MIR for `main` after DeadStoreElimination - - fn main() -> () { - let mut _0: (); - let mut _1: (&str, &str); - scope 1 { - } - - bb0: { - StorageLive(_1); - _1 = (const "Hello", const "World"); - PlaceMention(_1); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/place_mention.rs b/tests/mir-opt/dead-store-elimination/place_mention.rs index 4813cf7ee2b..ae75e622ff7 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-initial.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff new file mode 100644 index 00000000000..9b0dc6b6af6 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff @@ -0,0 +1,35 @@ +- // 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; + let mut _0: (); + let _2: usize; + let mut _3: *mut i32; + let mut _5: *mut i32; + scope 1 { + debug _x => _2; + let _4: isize; + scope 2 { + debug _y => _4; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = _1; + _2 = move _3 as usize (PointerExposeAddress); + StorageDead(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; + _4 = move _5 as isize (PointerExposeAddress); + StorageDead(_5); + _0 = const (); + StorageDead(_4); + StorageDead(_2); + return; + } + } + 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.diff deleted file mode 100644 index 31f727e5fb3..00000000000 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `pointer_to_int` before DeadStoreElimination -+ // MIR for `pointer_to_int` after DeadStoreElimination - - fn pointer_to_int(_1: *mut i32) -> () { - debug p => _1; - let mut _0: (); - let _2: usize; - let mut _3: *mut i32; - let mut _5: *mut i32; - scope 1 { - debug _x => _2; - let _4: isize; - scope 2 { - debug _y => _4; - } - } - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = _1; - _2 = move _3 as usize (PointerExposeAddress); - StorageDead(_3); - StorageLive(_4); - StorageLive(_5); - _5 = _1; - _4 = move _5 as isize (PointerExposeAddress); - StorageDead(_5); - _0 = const (); - StorageDead(_4); - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff new file mode 100644 index 00000000000..ab74d2411bb --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff @@ -0,0 +1,14 @@ +- // MIR for `retags` before DeadStoreElimination-initial ++ // MIR for `retags` after DeadStoreElimination-initial + + fn retags(_1: &mut i32) -> () { + debug _r => _1; + let mut _0: (); + + bb0: { + Retag([fn entry] _1); + _0 = const (); + return; + } + } + 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.diff deleted file mode 100644 index e1ebc39aacc..00000000000 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff +++ /dev/null @@ -1,14 +0,0 @@ -- // MIR for `retags` before DeadStoreElimination -+ // MIR for `retags` after DeadStoreElimination - - fn retags(_1: &mut i32) -> () { - debug _r => _1; - let mut _0: (); - - bb0: { - Retag([fn entry] _1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs index 24ffbe980eb..916c393b9de 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 -// compile-flags: -Zmir-emit-retag - // Test that we don't remove pointer to int casts or retags +// unit-test: DeadStoreElimination-initial +// compile-flags: -Zmir-emit-retag -// 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 993e0f1d1a6..0af3faf28f0 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 993e0f1d1a6..0af3faf28f0 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 0ba1bac0a03..080478ea884 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 27ea43ef12b..ff8933fca8b 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 68c612314f6..8e53427e7e0 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 1bf14e8c3b3..b06db41af9d 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 da45ebcb4d8..2bbb830fc77 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 d65c65e5fd0..bc4f2d24df0 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 aeb93bd334f..d6a608476df 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 aeb93bd334f..d6a608476df 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 d2db8f61916..b04728a9b0f 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 514183b3bc0..fcf99ac6918 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 f04ca72dd6d..9cc4385f60b 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 f04ca72dd6d..9cc4385f60b 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 47e0d402347..3cb44096881 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 dee57ce6c27..06d5e615b14 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 a255b15920c..eb54cc7da85 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 192ffea2591..4200ce3087f 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 8dbb688999a..8d182069adc 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 42c7eb3c6aa..e27e417ed4a 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 30bdc131090..b800a1be22b 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 713d6cc558a..f0cb4ca31fe 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 4e34233a979..0e7e1f971ec 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 275f17e52ae..9071a3339c0 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 4e34233a979..0e7e1f971ec 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 275f17e52ae..9071a3339c0 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 e5940bd8201..99805da5669 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 87e7485cb36..f40f1307175 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 1b23e421368..0836600cb6e 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 a677e8b439f..8c1794de524 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 a12411a0413..cdbd8d89f28 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 a12411a0413..cdbd8d89f28 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 0d95f81c37c..36329f8fc68 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 0d95f81c37c..36329f8fc68 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 c58b630a0c3..26b2663fa35 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 1a805f0fd8d..a055612bd5f 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 09075eed6a9..471491108e0 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 47b84746468..bbf38aba91f 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 6a99f15774f..83915d3c449 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 4f028fa0a64..0a005a460e8 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 5ed7ca5e2b8..f9c8ab4db60 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 bbb979d23b3..65f423ac326 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 0bf4a267002..c1d4d4871d0 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 7ccb8b0430d..d6883ac9fda 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 a12db0a730c..e7280f14837 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 80f40b86919..294bfa661cf 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 d7ade041e4c..33b36f660cb 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 931c5c43c4c..e5c3adff623 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; } } -- cgit 1.4.1-3-g733a5 From 974b727874b18a161c17fd0eaa4ca883d05bf19a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Jan 2024 20:01:52 +0000 Subject: 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 7ce3597206b..93def93127c 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" => { -- cgit 1.4.1-3-g733a5 From bc35ee41fa6751a85a528656953b581fb02ddd25 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Jan 2024 12:22:33 +0000 Subject: Do not run simplify_locals inside DSE. The full pass is run short after. --- compiler/rustc_mir_transform/src/dead_store_elimination.rs | 2 -- ...arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff | 4 ++-- ...rg_copy.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 9dd5aa4c8bd..c27718d7bda 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 268924b7c5d..f9bc9405d6a 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 bd754f9ebd4..efe165422d9 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 f13588c3aa4..2766b6ce6a9 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]; } -- cgit 1.4.1-3-g733a5 From b6e6d5d3af99aa771b2f34fb8fcbca03679e0320 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 11 Jan 2024 11:36:10 +0100 Subject: 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 | 91 +++++++----- 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, 212 insertions(+), 224 deletions(-) diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index c2ab9506489..92d2b9c3f57 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 c728570d986..fc0a4eb43dc 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 c82d2347de5..32c53cb9503 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 e8086be86f4..67e43f15cd3 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 0a6ba88065d..168ee4acffb 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::Values(def) => self - .values - .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, 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 20e4e44339e..82ea5ffeba1 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 6d92fce0727..8693b9a98c9 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 a97f57f5531..53644f58efc 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 700264839b9..389dabdbc86 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 301391516d6..1d850f721c1 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 163484e241b..cd8023f5d7d 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 4618dcec70b..30b8c189f52 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 06df30582aa..03ed8d36a1d 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 0266915c39b..3180a2b713a 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 9ae5bb26932..e1101dd8236 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); } -- cgit 1.4.1-3-g733a5 From 215ede84979971e0d4dbae41c7be4c3f46d2728a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 11 Jan 2024 12:41:47 +0100 Subject: 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 48fe43450a7..0f6e64016f1 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 65a55f8b5b8..c892f462d2c 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 6a122e0859c..ae7d17e49a9 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 { -- cgit 1.4.1-3-g733a5 From adce3fd99ba2ad3f3b03136473c29256513213fb Mon Sep 17 00:00:00 2001 From: Nathan Reller Date: Thu, 11 Jan 2024 15:26:16 +0000 Subject: 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 8c141aaaec3..80b3da8a752 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 eeee98f754e..f5988a4df13 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" {} -- cgit 1.4.1-3-g733a5 From 9018d2c455df78d3f2900b4ced3ed63962e4f11e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 7 Dec 2023 09:53:08 +1100 Subject: 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 +++++ .../rustc_parse/src/lexer/unescape_error_reporting.rs | 3 +++ compiler/rustc_session/messages.ftl | 2 -- compiler/rustc_session/src/errors.rs | 15 +-------------- src/tools/rust-analyzer/crates/parser/src/lexed_str.rs | 1 + .../rust-analyzer/crates/syntax/src/validation.rs | 3 +++ tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs | Bin 738 -> 1906 bytes .../ui/rfcs/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 92b9adf1db7..fbae4964588 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 abec12f52a6..0a632c4d12a 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 c11a6fab7e5..3c2fb53b294 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 0de252707bd..ef8e9d0a248 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 fbc77f28780..3238f8e23bb 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 f2e646c70f5..4f824f9f62e 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 b672e760feb..b0a397de3eb 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 b9e7566fdf9..3753a1beb7a 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 eabbda2c398..0504f67c9dc 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 e20ca50b88f..2f9ca09f3a5 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs differ diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr index ff9006f6f97..a05dea3ff07 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr differ -- cgit 1.4.1-3-g733a5 From f37a919e9668dbbdc999bb727eafc2bd46e505a6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 16:16:17 +0000 Subject: Remove redundant Code from FulfillmentErrorCode variants --- compiler/rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_infer/src/traits/mod.rs | 13 +++---- .../rustc_infer/src/traits/structural_impls.rs | 15 ++++---- .../rustc_trait_selection/src/solve/fulfill.rs | 16 ++++---- .../traits/error_reporting/type_err_ctxt_ext.rs | 18 ++++----- .../rustc_trait_selection/src/traits/fulfill.rs | 43 +++++++++++----------- compiler/rustc_traits/src/codegen.rs | 2 +- .../rustc_traits/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 b31325485db..8cad3661178 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 3b3d440df97..9fc0a973054 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 76360239c45..d7459bf4f68 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 b542132d71c..4fabe0ff818 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 b9be178916c..fdae093aac8 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 51c06c8970b..3b4050fcd27 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 2139210b873..23d08d380c2 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 47a700805fa..659ac74ee8d 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 045d7e444b6..f27fe80f028 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 2cd1c3b502a..f3fae63ecc7 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 b8c71bc96f8..21a016e29d6 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); } } -- cgit 1.4.1-3-g733a5 From fbdc116e6ea4051d25847cdd2d12919f8ca8aebc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 16:20:12 +0000 Subject: OutputTypeParameterMismatch -> SignatureMismatch --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 7 +++--- compiler/rustc_middle/src/traits/mod.rs | 4 ++-- .../traits/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 d7459bf4f68..1ad79cb78c4 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 af601a0d702..fb74d6610f2 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 659ac74ee8d..64ce1746c16 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 e20bb06d777..74f388e53a3 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, -- cgit 1.4.1-3-g733a5 From 50e1580cd0ba57e183ff766781a2408f8ba983c7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 17:50:43 +0000 Subject: 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 7edb5912dd5..b7ca070a478 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, -- cgit 1.4.1-3-g733a5 From db36304102fd86305b0319d5a3d8f440aa4b139d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 3 Jan 2024 01:34:38 +0100 Subject: rustc_pattern_analysis no longer needs to be passed an arena --- Cargo.lock | 7 ------- compiler/rustc_pattern_analysis/Cargo.toml | 6 ------ compiler/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 ++++-- compiler/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 440def72768..f23a18d3877 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 2152f9fda00..7cc585bea3a 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 15ff4ceb5b3..c1042d5b66e 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 374914055d8..ed10a515508 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 2f5dc241cb7..75fe59edf88 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 a17cd2c81b9..e82d6666b1a 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 85b6a6a3b6c..6244cf0ff7d 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 c198c116282..b03811e5efd 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", -- cgit 1.4.1-3-g733a5 From 6a6318342a953f0ad83de003c080d19bd4b911aa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Jan 2024 17:52:26 +0000 Subject: 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 b7ca070a478..1bc750a7e12 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"); - 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`"); + // For now, we only do signature deduction based off of the `Fn` traits. + if !tcx.is_fn_trait(trait_def_id) { return None; } - 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); + 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; }; -- cgit 1.4.1-3-g733a5 From b858c591dd85f51bb515f492cfa8a0252339ddb9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 11 Jan 2024 21:20:15 -0800 Subject: 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 eff1b9b59b1..1f448984e53 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 00000000000..5c57b41532f --- /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() +} -- cgit 1.4.1-3-g733a5 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: 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 ++++++++++++++++++---- ...issue-66340-deprecated-attr-non-meta-grammar.rs | 2 +- ...e-66340-deprecated-attr-non-meta-grammar.stderr | 7 +++++- .../ui/parser/attribute/attr-unquoted-ident.fixed | 15 ++++++++++++ tests/ui/parser/attribute/attr-unquoted-ident.rs | 15 ++++++++++++ .../ui/parser/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 c11a6fab7e5..d515e86a182 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 0de252707bd..34b34a1bad6 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 02dab95233a..a92609c2c2f 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 c0cde75d4ca..6653bd15ddd 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 48c763c50e3..078c766deed 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 00000000000..6cdf22f7ec0 --- /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 00000000000..75af015c9fe --- /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 00000000000..bc028f39be6 --- /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 + -- cgit 1.4.1-3-g733a5 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: 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 bd2851a26fb..5025b77d698 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`] -- cgit 1.4.1-3-g733a5 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: 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 3f3b57ba94f..1cc1f11b3c8 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 6c0909d2853..0e33e9cd790 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 57f24a4c28e..ae442a0d0b4 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 68b5a24bf97..a98a2ab0706 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`. -- cgit 1.4.1-3-g733a5 From ac58f9ae034eaba1ae2efd27d43d5e2328260461 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Sat, 13 Jan 2024 16:32:03 +0100 Subject: 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 440def72768..697e8c81bda 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 c12142e302d..3948a49ee2a 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 23949deaade..9d598c32e6f 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 8e6ca645f80..82e56c9cbe2 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 88eb4603069..c57f22a0da2 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 3da751c69a9..a65010b055b 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`. -- cgit 1.4.1-3-g733a5 From 41b69aae912aa9a1a8d5ed9518e73d136b42e7ca Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 13 Jan 2024 12:18:51 +0100 Subject: Add way to express no-values with check-cfg --- compiler/rustc_interface/src/interface.rs | 4 +++- compiler/rustc_lint/src/context/diagnostics.rs | 11 ++++++++++ .../unstable-book/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 32fba6ade88..5ca88090996 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 9e6a6f70eac..312874db3f5 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 78bc8dceb78..bf83f6ad7c5 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 9a308429484..aed4fd2a8c0 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 f2fd0fd6420..8542174d0c0 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 fc6951b5617..74d65e550bb 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 0f9178ce6a5..ad922f8c908 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 dec43f5bda3..6fe9f2baa09 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 00000000000..7e6ba6ae84a --- /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 00000000000..e7b0b05d561 --- /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 + -- cgit 1.4.1-3-g733a5 From 0b45ff5dac44aa8cb65c800eb8f1ad32d2a2ded7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 20:55:50 +0000 Subject: Don't ICE when noting GAT bounds in report_no_match_method_error --- compiler/rustc_hir_typeck/src/method/suggest.rs | 17 ++++--- ...tisified-gat-bound-during-assoc-ty-selection.rs | 33 ++++++++++++++ ...fied-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 1f01c6b7406..3bf1e1312b3 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 00000000000..252dc7d751e --- /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 00000000000..3a973d356dc --- /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`. -- cgit 1.4.1-3-g733a5 From 04a6fd241bc18391b3f1f6ece1b109acd19842f1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 17:09:33 +0000 Subject: Make InferCtxtExt::could_impl_trait less messed up --- compiler/rustc_borrowck/src/diagnostics/mod.rs | 8 +- .../src/diagnostics/mutability_errors.rs | 23 +++--- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 91 ++++++++-------------- .../borrowck/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 b31325485db..bb802c4eb46 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 3b3d440df97..60164e84d54 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 b542132d71c..6944b5eb176 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 251f0628a71..ef4a0f52f9e 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 00000000000..0b0ac9448db --- /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 00000000000..ab42205d510 --- /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 edc9eeaffb5..f2d1dd0fbc3 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 4a6a0e94bec..936ddd67bcd 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 ce5740bc0e7..76e0b517354 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 4889f774afa..57900bfb612 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 c60ac62fa34..e062a253767 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 e3dd65b6419..f96b0c7d9e1 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 462deacbe8d..17f48f5f7bf 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 -- cgit 1.4.1-3-g733a5 From 7724ba7bd5f2c947a7dc561c24b19bb8409a6ed6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 21:53:42 +0000 Subject: 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 2139210b873..09f4f3e9702 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 045d7e444b6..472342f9898 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(), -- cgit 1.4.1-3-g733a5 From 2de99ec787c80d4ba5ac4638d371a5bd8b752795 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 13 Jan 2024 10:31:09 +1100 Subject: 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 bd7c58d904e..93b2dd61b05 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)) }) } -- cgit 1.4.1-3-g733a5 From 24c1f4aa802bc6b9c3710baa4464e691b5b13bb2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 22:57:44 +0000 Subject: Make sure to instantiate placeholders correctly in old solver --- .../src/infer/canonical/query_response.rs | 16 +++++++++---- ...g-placeholders-in-query-response.current.stderr | 11 +++++++++ ...ying-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 8cca4c6231f..1f071a9ff0b 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 00000000000..040009efbde --- /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 00000000000..040009efbde --- /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 00000000000..5e28a2ba8b9 --- /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() {} -- cgit 1.4.1-3-g733a5 From 985e1e031b0d9d7c54812931c2beb57b0d304a94 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 13 Jan 2024 23:08:22 +0000 Subject: Add a simpler test --- ...placeholders-in-query-response-2.current.stderr | 11 +++++++++++ ...ng-placeholders-in-query-response-2.next.stderr | 11 +++++++++++ .../unifying-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 00000000000..4082d6d47e7 --- /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 00000000000..4082d6d47e7 --- /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 00000000000..bbf1a1f72db --- /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(); +} -- cgit 1.4.1-3-g733a5 From 4ca6342eb30dfbc3fe0992de0cfc780f3992f446 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 14 Jan 2024 00:24:39 +0000 Subject: 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 ac374a41eb6..4f973c1f010 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 ff435349249..781c7a91a5a 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 { -- cgit 1.4.1-3-g733a5 From 6d1c396399be9dc7a31cc023513e103848a96506 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 30 Dec 2023 17:59:39 +1100 Subject: 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`. --- compiler/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 263bfdaaaba..b8e269b9103 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); } -- cgit 1.4.1-3-g733a5 From c412cd4bc2241d7a67813b594cfc7e284e32c55b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 1 Jan 2024 21:52:43 +1100 Subject: coverage: Indicate whether a block's successors allow BCB chaining --- compiler/rustc_mir_transform/src/coverage/graph.rs | 90 +++++++++++++++------- compiler/rustc_mir_transform/src/lib.rs | 1 + 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index b8e269b9103..c418d86aa70 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, - }; - - terminator.successors().take(take_n_successors) +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()), + + // 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 ce9043ec287..98076077b9a 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)] -- cgit 1.4.1-3-g733a5 From 229d0983b5c1765a50afe1a67853487bb6b145f4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 1 Jan 2024 22:46:45 +1100 Subject: 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. --- compiler/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 c418d86aa70..3e27a3e990a 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(_) => {} - } + basic_blocks.push(bb); } 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; -- cgit 1.4.1-3-g733a5 From 867950f8c6f4a11e388e3e3e75cdf5344e95e4e8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 2 Jan 2024 12:48:35 +1100 Subject: 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. --- compiler/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 3e27a3e990a..9a3605b7a6a 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, -- cgit 1.4.1-3-g733a5 From 5eae9452b6762a1347a3dec4f40c8ddc7789a868 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 1 Jan 2024 22:59:47 +1100 Subject: coverage: Simplify computing successors in the BCB graph --- compiler/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 9a3605b7a6a..c6badbe78a4 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(), ); -- cgit 1.4.1-3-g733a5 From d71f535a6f39e82313b46ac3157c4ed9267a2e40 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 13 Jan 2024 13:11:56 +1100 Subject: 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 ++++++++++------------ compiler/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 +- .../rustc_hir_analysis/src/structured_errors.rs | 4 +- .../missing_cast_for_variadic_arg.rs | 4 +- .../src/structured_errors/sized_unsized_cast.rs | 4 +- .../wrong_number_of_generic_args.rs | 6 +-- compiler/rustc_hir_typeck/src/expr.rs | 4 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 ++-- compiler/rustc_hir_typeck/src/lib.rs | 4 +- .../src/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 af1c6594446..5d497d4a188 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 648c9118400..f0699a56f98 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 786aced5b4f..4934bc2450c 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 93b2dd61b05..87e2d295c7f 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 987832e6937..23efdaea0eb 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 87bf9c23456..51b064f4c61 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 63391a0faa6..141547b537d 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 469e7a6a13c..774feb94f7d 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 04d04304e70..b061d637138 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 634904e3271..6f4435db411 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 c68d74969a5..19cac4a38aa 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 6657e3fd872..ba81e7f1f81 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 af47455c16d..ac8701a33d4 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 8cd5ed3494b..3fe42d1495a 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 36dd06d944c..67c35d717a1 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 4aefadf590d..e85c940f1b5 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 fb908fe2db1..0b7ecff8148 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 c5e4dfaf19e..4ab16cf19ba 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 446f13feff0..2ee660ddc9b 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 a9d0e0d2dd3..25ca685cbfa 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 b9e603a4992..ccf90fbff22 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 0adea65ee58..196f28d878d 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 c629c9884c8..16036e5be38 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 1c3d5a3cb88..3f6c70a18d3 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) } -- cgit 1.4.1-3-g733a5 From 5788f3d350e0367cd5bbb192b8780429949844de Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Sun, 14 Jan 2024 13:55:18 +0100 Subject: Remove Zulip rustdoc nomination alert --- triagebot.toml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 1e1db2d1663..2b818c0a990 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}" -- cgit 1.4.1-3-g733a5 From c6f83b8ff6b4e0fa98713b720ff48d67efe8d932 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 14 Jan 2024 12:57:13 +0000 Subject: 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 df1318c835e..ede8416125d 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 504763f6cdb..f6f6aa07cb3 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) } -- cgit 1.4.1-3-g733a5 From 0529ccf341516b098554ccc82a77553159316c2a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 14 Jan 2024 13:22:43 +0000 Subject: Fix `allow_internal_unstable` for `(min_)specialization` --- .../src/traits/specialize/mod.rs | 20 +++++++++++++++++--- tests/ui/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 200d022c80c..d3862451a01 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 00000000000..317782b7b72 --- /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! {} -- cgit 1.4.1-3-g733a5 From a596159dca825a02270335d4b90b8fcb128b2d11 Mon Sep 17 00:00:00 2001 From: Behnam Esfahbod Date: Thu, 11 Jan 2024 15:55:50 -0800 Subject: 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 3598598cfa0..27b59cfc8c2 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. -- cgit 1.4.1-3-g733a5 From eb63d3a49d7681d6ede7dc1bcac7bb1125ff7132 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 14 Jan 2024 13:48:58 +0000 Subject: `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 ac374a41eb6..b0bf4554ba8 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 d3862451a01..b37d9714ddd 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; + } } } -- cgit 1.4.1-3-g733a5 From 6f98a6cc8015cb094dc0c6acb330eb71ef75cb64 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 18:29:01 +0000 Subject: Simplify closure_env_ty and closure_env_param --- compiler/rustc_borrowck/src/universal_regions.rs | 6 ++- compiler/rustc_middle/src/ty/util.rs | 14 +++--- compiler/rustc_mir_build/src/thir/cx/mod.rs | 56 ++++++++---------------- compiler/rustc_ty_utils/src/abi.rs | 6 ++- 4 files changed, 34 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index addb41ff5fc..ae8a135f090 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 7285cdb830e..3a50ec2251a 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 fa3dd2afa85..5d0bb3954cc 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) + 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 } } - 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), + 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, ); - let env_param = Param { - ty: liberated_closure_env_ty, + Param { + ty: closure_env_ty, pat: None, ty_span: None, self_kind: None, hir_id: None, - }; - - Some(env_param) + } } - _ => 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 2772831e731..11f7972ceee 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( -- cgit 1.4.1-3-g733a5 From c5cb87cf0cf9f798869c098288304e132b0e53a1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 19:59:10 +0000 Subject: 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 b8d08319422..7b987288f80 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, ) -- cgit 1.4.1-3-g733a5 From c811662fb0e3eab4ee88134551cf2605327705f6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 20:01:12 +0000 Subject: Use zip_eq to enforce that things being zipped have equal sizes --- Cargo.lock | 3 +++ compiler/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 5b9dd05398f..7bbf8a526bc 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 61b6bef3b87..59518f68ab1 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 b5ebc1fab76..648b569a217 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 410706110c9..7d145ea1f23 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 b0c60304424..975f9375642 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 7873257c4e3..2bb7caea3c4 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 da6f2042c11..5ece2fcaa80 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 6d681dc295e..d71f7121322 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 7b987288f80..714c5f2686e 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 78d72b30284..22094c112fc 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 db89fba2a89..8b20ad05727 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); -- cgit 1.4.1-3-g733a5 From 56df3bb70d808d535e46f1c017bafeccbbf1cb6d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:47:10 -0800 Subject: 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 2df38ab5848..1de9226f47f 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); +} -- cgit 1.4.1-3-g733a5 From 54cb822563dc7ffd4838c23d04f7c1ad6c3e90cd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:21:50 -0800 Subject: 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 1de9226f47f..6b113d57f25 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); } -- cgit 1.4.1-3-g733a5 From 9196d2a552c28144252730bcf8a8e58878f625d4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:44:02 -0800 Subject: Unindent nonzero_integer macro body --- library/core/src/num/nonzero.rs | 278 ++++++++++++++++++++-------------------- 1 file changed, 139 insertions(+), 139 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b113d57f25..f7098bcf6e9 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 - } + #[$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) } + } - /// 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 + /// 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 = "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() + /// 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 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()) } - } + } + + #[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 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 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()) } } + } - #[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 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 BitOrAssign for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: Self) { - *self = *self | 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<$Int> for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: $Int) { - *self = *self | rhs; - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + *self = *self | rhs; } + } - impl_nonzero_fmt! { - #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[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 + } }; } -- cgit 1.4.1-3-g733a5 From a6152cdd9a6c287411212209a18904ca5d68d484 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:24:16 -0800 Subject: 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 f7098bcf6e9..f6ccefa2614 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", } -- cgit 1.4.1-3-g733a5 From 3de0af1a4da54885dd312e5e6f39641f5da06410 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:28:52 -0800 Subject: 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 f6ccefa2614..0f5d421235e 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 ;)+ ) => { $( -- cgit 1.4.1-3-g733a5 From 81e1a7c6b5bb5bea9fbbd0f5db0c118dbea867fb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:41:24 -0800 Subject: 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 0f5d421235e..79cca276479 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. -- cgit 1.4.1-3-g733a5 From a78d9a6de1848358b3835d3ac8ce6b20a24c061f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:07:42 -0800 Subject: 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 79cca276479..75429d9059a 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()) } } + } }; } -- cgit 1.4.1-3-g733a5 From f846ed53e41a18fbb900e794467351fda5ffbb80 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:37:28 -0800 Subject: 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 75429d9059a..9c396710fd4 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, } -- cgit 1.4.1-3-g733a5 From 23483664a24434e0bd5dab1576dffe4d8ada712c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 13 Jan 2024 17:53:14 -0800 Subject: 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 ++-- ...issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir | 2 +- ...ssue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir | 2 +- ...68_print_invalid_constant.main.GVN.32bit.panic-abort.diff | 2 +- ...8_print_invalid_constant.main.GVN.32bit.panic-unwind.diff | 2 +- ...68_print_invalid_constant.main.GVN.64bit.panic-abort.diff | 2 +- ...8_print_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 ff435349249..975aff90d35 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 b1475ee7931..d529f9ccead 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 5d25c655700..f7be8b75db7 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 4677c0108e3..e76fe992ac7 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 47e0d402347..cf93897d591 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 dee57ce6c27..ca33619aa1f 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 a255b15920c..9c026280ea9 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 192ffea2591..7eec7ffb01f 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: { -- cgit 1.4.1-3-g733a5 From 757ed2566701feba8fc67cae3d21a7423254efba Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:50:14 -0800 Subject: 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 9c396710fd4..b1dd766de31 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")] } )+ } } -- cgit 1.4.1-3-g733a5 From 4291b3ff62e4aad3dae4c573bde5f203d3baec79 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:03:55 -0800 Subject: 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 b1dd766de31..1b8920f9477 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", -- cgit 1.4.1-3-g733a5 From b21b9cc901c3f021c7b7475c406662cd9c0d76e1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:06:40 -0800 Subject: 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 1b8920f9477..8550a7b4c7b 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) } + } }; } -- cgit 1.4.1-3-g733a5 From c6d776ef4ba4f133b5f370f144b99cd3f39388fa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:38:38 -0800 Subject: 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 8550a7b4c7b..6b28f8100e7 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. ( -- cgit 1.4.1-3-g733a5 From 63256af236f4620701d7d8771f874c4ef57e6ff2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:46:18 -0800 Subject: 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 6b28f8100e7..c9693a22e87 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 )+ ) => { $( -- cgit 1.4.1-3-g733a5 From 441913626d33919b743e167c5c9e951487291fdd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:47:53 -0800 Subject: 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 c9693a22e87..0c34012ab5c 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); )+ ) => { $( -- cgit 1.4.1-3-g733a5 From 7f7c5af097678da556cd57936a8d8b6c02858502 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:49:44 -0800 Subject: 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 0c34012ab5c..0ab89aa0d6c 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); -- cgit 1.4.1-3-g733a5 From 66cda3b75fb35655076b1fa555bf4f95fdd9b54e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:50:31 -0800 Subject: 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 0ab89aa0d6c..9c48a5b0dbd 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); )+ ) => { $( -- cgit 1.4.1-3-g733a5 From c53713274cc6c04cad7b903c597ff54e4cdc8d27 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:52:20 -0800 Subject: 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 9c48a5b0dbd..0b42b628675 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, -- cgit 1.4.1-3-g733a5 From cdee1feb49989f13e5091c591fbba90ef9278add Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 6 Dec 2023 00:41:18 -0800 Subject: 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 0b42b628675..174fa200737 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, } -- cgit 1.4.1-3-g733a5 From 4efddb141a37577c6fc6a9a39248cc86b736750b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Jan 2024 10:55:08 +1100 Subject: 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 a10bdc6012c..4d9a1be2087 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}; -- cgit 1.4.1-3-g733a5 From 086d17b7cb77850ce9bc549b29082b6938a6c0d4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Jan 2024 11:08:06 +1100 Subject: 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 4d9a1be2087..3c6ad90b2ea 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) } } -- cgit 1.4.1-3-g733a5 From 32de78cade63ae338bd6e0d47d2f9d7278d7edfc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 10 Jan 2024 12:47:22 +1100 Subject: 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 2e4baf26176..11dcf4108d4 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 3c6ad90b2ea..6c9000c45f6 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 fe1166457ba..ac15c3b407b 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 2d91a3fbd91..f4bf79f93f2 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 -- cgit 1.4.1-3-g733a5 From f7602232a5a27165fc5f8ead2c72adca97b1330a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jan 2024 11:49:03 +0100 Subject: 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 695e87aaabf..f53a6f9e134 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 2df38ab5848..715c3a0b8ac 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 11a53aaf122..bbbbd61c4b1 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 3d58afd26ea..4a64faf9b3f 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 } } } -- cgit 1.4.1-3-g733a5 From 70b03645002e50fbe0c8ed29a0b0e801ace48a10 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 15 Jan 2024 16:26:25 +0100 Subject: std: move OS String implementation into `sys` --- library/std/src/sys/mod.rs | 1 + library/std/src/sys/os_str/bytes.rs | 287 ++++++++++++++++++++++++++ library/std/src/sys/os_str/bytes/tests.rs | 17 ++ library/std/src/sys/os_str/mod.rs | 12 ++ library/std/src/sys/os_str/wtf8.rs | 245 +++++++++++++++++++++++ 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/unix/os_str.rs | 288 --------------------------- library/std/src/sys/pal/unix/os_str/tests.rs | 17 -- 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/windows/os_str.rs | 245 ----------------------- library/std/src/sys/pal/xous/mod.rs | 2 - 19 files changed, 562 insertions(+), 570 deletions(-) create mode 100644 library/std/src/sys/os_str/bytes.rs create mode 100644 library/std/src/sys/os_str/bytes/tests.rs create mode 100644 library/std/src/sys/os_str/mod.rs create mode 100644 library/std/src/sys/os_str/wtf8.rs delete mode 100644 library/std/src/sys/pal/unix/os_str.rs delete mode 100644 library/std/src/sys/pal/unix/os_str/tests.rs delete mode 100644 library/std/src/sys/pal/windows/os_str.rs diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index bbdcb32606c..d95c0d8d062 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/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs new file mode 100644 index 00000000000..3a75ce9ebb7 --- /dev/null +++ b/library/std/src/sys/os_str/bytes.rs @@ -0,0 +1,287 @@ +//! The underlying OsString/OsStr implementation on Unix and many other +//! systems: just a `Vec`/`[u8]`. + +use crate::borrow::Cow; +use crate::collections::TryReserveError; +use crate::fmt; +use crate::fmt::Write; +use crate::mem; +use crate::rc::Rc; +use crate::str; +use crate::sync::Arc; +use crate::sys_common::{AsInner, IntoInner}; + +use core::str::Utf8Chunks; + +#[cfg(test)] +mod tests; + +#[derive(Hash)] +#[repr(transparent)] +pub struct Buf { + pub inner: Vec, +} + +#[repr(transparent)] +pub struct Slice { + pub inner: [u8], +} + +impl fmt::Debug for Slice { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&Utf8Chunks::new(&self.inner).debug(), f) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If we're the empty string then our iterator won't actually yield + // anything, so perform the formatting manually + if self.inner.is_empty() { + return "".fmt(f); + } + + for chunk in Utf8Chunks::new(&self.inner) { + let valid = chunk.valid(); + // If we successfully decoded the whole chunk as a valid string then + // we can return a direct formatting of the string which will also + // respect various formatting flags if possible. + if chunk.invalid().is_empty() { + return valid.fmt(f); + } + + f.write_str(valid)?; + f.write_char(char::REPLACEMENT_CHARACTER)?; + } + Ok(()) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) + } +} + +impl Clone for Buf { + #[inline] + fn clone(&self) -> Self { + Buf { inner: self.inner.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner) + } +} + +impl IntoInner> for Buf { + fn into_inner(self) -> Vec { + self.inner + } +} + +impl AsInner<[u8]> for Buf { + #[inline] + fn as_inner(&self) -> &[u8] { + &self.inner + } +} + +impl Buf { + #[inline] + pub fn into_encoded_bytes(self) -> Vec { + self.inner + } + + #[inline] + pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self { + Self { inner: s } + } + + pub fn from_string(s: String) -> Buf { + Buf { inner: s.into_bytes() } + } + + #[inline] + pub fn with_capacity(capacity: usize) -> Buf { + Buf { inner: Vec::with_capacity(capacity) } + } + + #[inline] + pub fn clear(&mut self) { + self.inner.clear() + } + + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + + #[inline] + pub fn shrink_to_fit(&mut self) { + self.inner.shrink_to_fit() + } + + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + + #[inline] + pub fn as_slice(&self) -> &Slice { + // SAFETY: Slice just wraps [u8], + // and &*self.inner is &[u8], therefore + // transmuting &[u8] to &Slice is safe. + unsafe { mem::transmute(&*self.inner) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut Slice { + // SAFETY: Slice just wraps [u8], + // and &mut *self.inner is &mut [u8], therefore + // transmuting &mut [u8] to &mut Slice is safe. + unsafe { mem::transmute(&mut *self.inner) } + } + + pub fn into_string(self) -> Result { + String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() }) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.extend_from_slice(&s.inner) + } + + #[inline] + pub fn into_box(self) -> Box { + unsafe { mem::transmute(self.inner.into_boxed_slice()) } + } + + #[inline] + pub fn from_box(boxed: Box) -> Buf { + let inner: Box<[u8]> = unsafe { mem::transmute(boxed) }; + Buf { inner: inner.into_vec() } + } + + #[inline] + pub fn into_arc(&self) -> Arc { + self.as_slice().into_arc() + } + + #[inline] + pub fn into_rc(&self) -> Rc { + self.as_slice().into_rc() + } +} + +impl Slice { + #[inline] + pub fn as_encoded_bytes(&self) -> &[u8] { + &self.inner + } + + #[inline] + pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { + unsafe { mem::transmute(s) } + } + + #[inline] + pub fn from_str(s: &str) -> &Slice { + unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) } + } + + pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { + str::from_utf8(&self.inner) + } + + pub fn to_string_lossy(&self) -> Cow<'_, str> { + String::from_utf8_lossy(&self.inner) + } + + pub fn to_owned(&self) -> Buf { + Buf { inner: self.inner.to_vec() } + } + + pub fn clone_into(&self, buf: &mut Buf) { + self.inner.clone_into(&mut buf.inner) + } + + #[inline] + pub fn into_box(&self) -> Box { + let boxed: Box<[u8]> = self.inner.into(); + unsafe { mem::transmute(boxed) } + } + + pub fn empty_box() -> Box { + let boxed: Box<[u8]> = Default::default(); + unsafe { mem::transmute(boxed) } + } + + #[inline] + pub fn into_arc(&self) -> Arc { + let arc: Arc<[u8]> = Arc::from(&self.inner); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) } + } + + #[inline] + pub fn into_rc(&self) -> Rc { + let rc: Rc<[u8]> = Rc::from(&self.inner); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } + } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.inner.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.inner.make_ascii_uppercase() + } + + #[inline] + pub fn to_ascii_lowercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_lowercase() } + } + + #[inline] + pub fn to_ascii_uppercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_uppercase() } + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.inner.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.inner.eq_ignore_ascii_case(&other.inner) + } +} diff --git a/library/std/src/sys/os_str/bytes/tests.rs b/library/std/src/sys/os_str/bytes/tests.rs new file mode 100644 index 00000000000..e2a99045e41 --- /dev/null +++ b/library/std/src/sys/os_str/bytes/tests.rs @@ -0,0 +1,17 @@ +use super::*; + +#[test] +fn slice_debug_output() { + let input = unsafe { Slice::from_encoded_bytes_unchecked(b"\xF0hello,\tworld") }; + let expected = r#""\xF0hello,\tworld""#; + let output = format!("{input:?}"); + + assert_eq!(output, expected); +} + +#[test] +fn display() { + assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe { + Slice::from_encoded_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string() + },); +} 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 00000000000..b509729475b --- /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/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs new file mode 100644 index 00000000000..237854fac4e --- /dev/null +++ b/library/std/src/sys/os_str/wtf8.rs @@ -0,0 +1,245 @@ +/// The underlying OsString/OsStr implementation on Windows is a +/// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. +use crate::borrow::Cow; +use crate::collections::TryReserveError; +use crate::fmt; +use crate::mem; +use crate::rc::Rc; +use crate::sync::Arc; +use crate::sys_common::wtf8::{Wtf8, Wtf8Buf}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; + +#[derive(Clone, Hash)] +pub struct Buf { + pub inner: Wtf8Buf, +} + +impl IntoInner for Buf { + fn into_inner(self) -> Wtf8Buf { + self.inner + } +} + +impl FromInner for Buf { + fn from_inner(inner: Wtf8Buf) -> Self { + Buf { inner } + } +} + +impl AsInner for Buf { + #[inline] + fn as_inner(&self) -> &Wtf8 { + &self.inner + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) + } +} + +#[repr(transparent)] +pub struct Slice { + pub inner: Wtf8, +} + +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.inner, formatter) + } +} + +impl Buf { + #[inline] + pub fn into_encoded_bytes(self) -> Vec { + self.inner.into_bytes() + } + + #[inline] + pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self { + Self { inner: Wtf8Buf::from_bytes_unchecked(s) } + } + + pub fn with_capacity(capacity: usize) -> Buf { + Buf { inner: Wtf8Buf::with_capacity(capacity) } + } + + pub fn clear(&mut self) { + self.inner.clear() + } + + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + pub fn from_string(s: String) -> Buf { + Buf { inner: Wtf8Buf::from_string(s) } + } + + pub fn as_slice(&self) -> &Slice { + // SAFETY: Slice is just a wrapper for Wtf8, + // and self.inner.as_slice() returns &Wtf8. + // Therefore, transmuting &Wtf8 to &Slice is safe. + unsafe { mem::transmute(self.inner.as_slice()) } + } + + pub fn as_mut_slice(&mut self) -> &mut Slice { + // SAFETY: Slice is just a wrapper for Wtf8, + // and self.inner.as_mut_slice() returns &mut Wtf8. + // Therefore, transmuting &mut Wtf8 to &mut Slice is safe. + // Additionally, care should be taken to ensure the slice + // is always valid Wtf8. + unsafe { mem::transmute(self.inner.as_mut_slice()) } + } + + pub fn into_string(self) -> Result { + self.inner.into_string().map_err(|buf| Buf { inner: buf }) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.push_wtf8(&s.inner) + } + + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + + pub fn shrink_to_fit(&mut self) { + self.inner.shrink_to_fit() + } + + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + + #[inline] + pub fn into_box(self) -> Box { + unsafe { mem::transmute(self.inner.into_box()) } + } + + #[inline] + pub fn from_box(boxed: Box) -> Buf { + let inner: Box = unsafe { mem::transmute(boxed) }; + Buf { inner: Wtf8Buf::from_box(inner) } + } + + #[inline] + pub fn into_arc(&self) -> Arc { + self.as_slice().into_arc() + } + + #[inline] + pub fn into_rc(&self) -> Rc { + self.as_slice().into_rc() + } +} + +impl Slice { + #[inline] + pub fn as_encoded_bytes(&self) -> &[u8] { + self.inner.as_bytes() + } + + #[inline] + pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { + mem::transmute(Wtf8::from_bytes_unchecked(s)) + } + + #[inline] + pub fn from_str(s: &str) -> &Slice { + unsafe { mem::transmute(Wtf8::from_str(s)) } + } + + pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { + self.inner.as_str() + } + + pub fn to_string_lossy(&self) -> Cow<'_, str> { + self.inner.to_string_lossy() + } + + pub fn to_owned(&self) -> Buf { + Buf { inner: self.inner.to_owned() } + } + + pub fn clone_into(&self, buf: &mut Buf) { + self.inner.clone_into(&mut buf.inner) + } + + #[inline] + pub fn into_box(&self) -> Box { + unsafe { mem::transmute(self.inner.into_box()) } + } + + pub fn empty_box() -> Box { + unsafe { mem::transmute(Wtf8::empty_box()) } + } + + #[inline] + pub fn into_arc(&self) -> Arc { + let arc = self.inner.into_arc(); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) } + } + + #[inline] + pub fn into_rc(&self) -> Rc { + let rc = self.inner.into_rc(); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } + } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.inner.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.inner.make_ascii_uppercase() + } + + #[inline] + pub fn to_ascii_lowercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_lowercase() } + } + + #[inline] + pub fn to_ascii_uppercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_uppercase() } + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.inner.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.inner.eq_ignore_ascii_case(&other.inner) + } +} diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 937603cfd8a..50336296919 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 09d3f7638ca..893c5f765a7 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 5af83653cf8..5742ce9d72c 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 ed8c54b2c36..764a4e6ad35 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 4edc00e3ea0..fb1a531182a 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 b5da5f870ec..86027c2b0b0 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/unix/os_str.rs b/library/std/src/sys/pal/unix/os_str.rs deleted file mode 100644 index 7bd2f656a24..00000000000 --- a/library/std/src/sys/pal/unix/os_str.rs +++ /dev/null @@ -1,288 +0,0 @@ -//! The underlying OsString/OsStr implementation on Unix and many other -//! systems: just a `Vec`/`[u8]`. - -use crate::borrow::Cow; -use crate::collections::TryReserveError; -use crate::fmt; -use crate::fmt::Write; -use crate::mem; -use crate::rc::Rc; -use crate::str; -use crate::sync::Arc; -use crate::sys_common::{AsInner, IntoInner}; - -use core::str::Utf8Chunks; - -#[cfg(test)] -#[path = "../unix/os_str/tests.rs"] -mod tests; - -#[derive(Hash)] -#[repr(transparent)] -pub struct Buf { - pub inner: Vec, -} - -#[repr(transparent)] -pub struct Slice { - pub inner: [u8], -} - -impl fmt::Debug for Slice { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&Utf8Chunks::new(&self.inner).debug(), f) - } -} - -impl fmt::Display for Slice { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If we're the empty string then our iterator won't actually yield - // anything, so perform the formatting manually - if self.inner.is_empty() { - return "".fmt(f); - } - - for chunk in Utf8Chunks::new(&self.inner) { - let valid = chunk.valid(); - // If we successfully decoded the whole chunk as a valid string then - // we can return a direct formatting of the string which will also - // respect various formatting flags if possible. - if chunk.invalid().is_empty() { - return valid.fmt(f); - } - - f.write_str(valid)?; - f.write_char(char::REPLACEMENT_CHARACTER)?; - } - Ok(()) - } -} - -impl fmt::Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.as_slice(), formatter) - } -} - -impl fmt::Display for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.as_slice(), formatter) - } -} - -impl Clone for Buf { - #[inline] - fn clone(&self) -> Self { - Buf { inner: self.inner.clone() } - } - - #[inline] - fn clone_from(&mut self, source: &Self) { - self.inner.clone_from(&source.inner) - } -} - -impl IntoInner> for Buf { - fn into_inner(self) -> Vec { - self.inner - } -} - -impl AsInner<[u8]> for Buf { - #[inline] - fn as_inner(&self) -> &[u8] { - &self.inner - } -} - -impl Buf { - #[inline] - pub fn into_encoded_bytes(self) -> Vec { - self.inner - } - - #[inline] - pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self { - Self { inner: s } - } - - pub fn from_string(s: String) -> Buf { - Buf { inner: s.into_bytes() } - } - - #[inline] - pub fn with_capacity(capacity: usize) -> Buf { - Buf { inner: Vec::with_capacity(capacity) } - } - - #[inline] - pub fn clear(&mut self) { - self.inner.clear() - } - - #[inline] - pub fn capacity(&self) -> usize { - self.inner.capacity() - } - - #[inline] - pub fn reserve(&mut self, additional: usize) { - self.inner.reserve(additional) - } - - #[inline] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.inner.try_reserve(additional) - } - - #[inline] - pub fn reserve_exact(&mut self, additional: usize) { - self.inner.reserve_exact(additional) - } - - #[inline] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.inner.try_reserve_exact(additional) - } - - #[inline] - pub fn shrink_to_fit(&mut self) { - self.inner.shrink_to_fit() - } - - #[inline] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.inner.shrink_to(min_capacity) - } - - #[inline] - pub fn as_slice(&self) -> &Slice { - // SAFETY: Slice just wraps [u8], - // and &*self.inner is &[u8], therefore - // transmuting &[u8] to &Slice is safe. - unsafe { mem::transmute(&*self.inner) } - } - - #[inline] - pub fn as_mut_slice(&mut self) -> &mut Slice { - // SAFETY: Slice just wraps [u8], - // and &mut *self.inner is &mut [u8], therefore - // transmuting &mut [u8] to &mut Slice is safe. - unsafe { mem::transmute(&mut *self.inner) } - } - - pub fn into_string(self) -> Result { - String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() }) - } - - pub fn push_slice(&mut self, s: &Slice) { - self.inner.extend_from_slice(&s.inner) - } - - #[inline] - pub fn into_box(self) -> Box { - unsafe { mem::transmute(self.inner.into_boxed_slice()) } - } - - #[inline] - pub fn from_box(boxed: Box) -> Buf { - let inner: Box<[u8]> = unsafe { mem::transmute(boxed) }; - Buf { inner: inner.into_vec() } - } - - #[inline] - pub fn into_arc(&self) -> Arc { - self.as_slice().into_arc() - } - - #[inline] - pub fn into_rc(&self) -> Rc { - self.as_slice().into_rc() - } -} - -impl Slice { - #[inline] - pub fn as_encoded_bytes(&self) -> &[u8] { - &self.inner - } - - #[inline] - pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { - unsafe { mem::transmute(s) } - } - - #[inline] - pub fn from_str(s: &str) -> &Slice { - unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) } - } - - pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { - str::from_utf8(&self.inner) - } - - pub fn to_string_lossy(&self) -> Cow<'_, str> { - String::from_utf8_lossy(&self.inner) - } - - pub fn to_owned(&self) -> Buf { - Buf { inner: self.inner.to_vec() } - } - - pub fn clone_into(&self, buf: &mut Buf) { - self.inner.clone_into(&mut buf.inner) - } - - #[inline] - pub fn into_box(&self) -> Box { - let boxed: Box<[u8]> = self.inner.into(); - unsafe { mem::transmute(boxed) } - } - - pub fn empty_box() -> Box { - let boxed: Box<[u8]> = Default::default(); - unsafe { mem::transmute(boxed) } - } - - #[inline] - pub fn into_arc(&self) -> Arc { - let arc: Arc<[u8]> = Arc::from(&self.inner); - unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) } - } - - #[inline] - pub fn into_rc(&self) -> Rc { - let rc: Rc<[u8]> = Rc::from(&self.inner); - unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } - } - - #[inline] - pub fn make_ascii_lowercase(&mut self) { - self.inner.make_ascii_lowercase() - } - - #[inline] - pub fn make_ascii_uppercase(&mut self) { - self.inner.make_ascii_uppercase() - } - - #[inline] - pub fn to_ascii_lowercase(&self) -> Buf { - Buf { inner: self.inner.to_ascii_lowercase() } - } - - #[inline] - pub fn to_ascii_uppercase(&self) -> Buf { - Buf { inner: self.inner.to_ascii_uppercase() } - } - - #[inline] - pub fn is_ascii(&self) -> bool { - self.inner.is_ascii() - } - - #[inline] - pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { - self.inner.eq_ignore_ascii_case(&other.inner) - } -} diff --git a/library/std/src/sys/pal/unix/os_str/tests.rs b/library/std/src/sys/pal/unix/os_str/tests.rs deleted file mode 100644 index e2a99045e41..00000000000 --- a/library/std/src/sys/pal/unix/os_str/tests.rs +++ /dev/null @@ -1,17 +0,0 @@ -use super::*; - -#[test] -fn slice_debug_output() { - let input = unsafe { Slice::from_encoded_bytes_unchecked(b"\xF0hello,\tworld") }; - let expected = r#""\xF0hello,\tworld""#; - let output = format!("{input:?}"); - - assert_eq!(output, expected); -} - -#[test] -fn display() { - assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe { - Slice::from_encoded_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string() - },); -} diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index e1a38de6471..6254c67a2a3 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 5919cc506d9..c1fc053bf04 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 6c05b56e1bf..d2181565887 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 8b722f01a5d..d097a7b8bb2 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/windows/os_str.rs b/library/std/src/sys/pal/windows/os_str.rs deleted file mode 100644 index 237854fac4e..00000000000 --- a/library/std/src/sys/pal/windows/os_str.rs +++ /dev/null @@ -1,245 +0,0 @@ -/// The underlying OsString/OsStr implementation on Windows is a -/// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. -use crate::borrow::Cow; -use crate::collections::TryReserveError; -use crate::fmt; -use crate::mem; -use crate::rc::Rc; -use crate::sync::Arc; -use crate::sys_common::wtf8::{Wtf8, Wtf8Buf}; -use crate::sys_common::{AsInner, FromInner, IntoInner}; - -#[derive(Clone, Hash)] -pub struct Buf { - pub inner: Wtf8Buf, -} - -impl IntoInner for Buf { - fn into_inner(self) -> Wtf8Buf { - self.inner - } -} - -impl FromInner for Buf { - fn from_inner(inner: Wtf8Buf) -> Self { - Buf { inner } - } -} - -impl AsInner for Buf { - #[inline] - fn as_inner(&self) -> &Wtf8 { - &self.inner - } -} - -impl fmt::Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.as_slice(), formatter) - } -} - -impl fmt::Display for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.as_slice(), formatter) - } -} - -#[repr(transparent)] -pub struct Slice { - pub inner: Wtf8, -} - -impl fmt::Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.inner, formatter) - } -} - -impl fmt::Display for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.inner, formatter) - } -} - -impl Buf { - #[inline] - pub fn into_encoded_bytes(self) -> Vec { - self.inner.into_bytes() - } - - #[inline] - pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self { - Self { inner: Wtf8Buf::from_bytes_unchecked(s) } - } - - pub fn with_capacity(capacity: usize) -> Buf { - Buf { inner: Wtf8Buf::with_capacity(capacity) } - } - - pub fn clear(&mut self) { - self.inner.clear() - } - - pub fn capacity(&self) -> usize { - self.inner.capacity() - } - - pub fn from_string(s: String) -> Buf { - Buf { inner: Wtf8Buf::from_string(s) } - } - - pub fn as_slice(&self) -> &Slice { - // SAFETY: Slice is just a wrapper for Wtf8, - // and self.inner.as_slice() returns &Wtf8. - // Therefore, transmuting &Wtf8 to &Slice is safe. - unsafe { mem::transmute(self.inner.as_slice()) } - } - - pub fn as_mut_slice(&mut self) -> &mut Slice { - // SAFETY: Slice is just a wrapper for Wtf8, - // and self.inner.as_mut_slice() returns &mut Wtf8. - // Therefore, transmuting &mut Wtf8 to &mut Slice is safe. - // Additionally, care should be taken to ensure the slice - // is always valid Wtf8. - unsafe { mem::transmute(self.inner.as_mut_slice()) } - } - - pub fn into_string(self) -> Result { - self.inner.into_string().map_err(|buf| Buf { inner: buf }) - } - - pub fn push_slice(&mut self, s: &Slice) { - self.inner.push_wtf8(&s.inner) - } - - pub fn reserve(&mut self, additional: usize) { - self.inner.reserve(additional) - } - - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.inner.try_reserve(additional) - } - - pub fn reserve_exact(&mut self, additional: usize) { - self.inner.reserve_exact(additional) - } - - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.inner.try_reserve_exact(additional) - } - - pub fn shrink_to_fit(&mut self) { - self.inner.shrink_to_fit() - } - - #[inline] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.inner.shrink_to(min_capacity) - } - - #[inline] - pub fn into_box(self) -> Box { - unsafe { mem::transmute(self.inner.into_box()) } - } - - #[inline] - pub fn from_box(boxed: Box) -> Buf { - let inner: Box = unsafe { mem::transmute(boxed) }; - Buf { inner: Wtf8Buf::from_box(inner) } - } - - #[inline] - pub fn into_arc(&self) -> Arc { - self.as_slice().into_arc() - } - - #[inline] - pub fn into_rc(&self) -> Rc { - self.as_slice().into_rc() - } -} - -impl Slice { - #[inline] - pub fn as_encoded_bytes(&self) -> &[u8] { - self.inner.as_bytes() - } - - #[inline] - pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { - mem::transmute(Wtf8::from_bytes_unchecked(s)) - } - - #[inline] - pub fn from_str(s: &str) -> &Slice { - unsafe { mem::transmute(Wtf8::from_str(s)) } - } - - pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { - self.inner.as_str() - } - - pub fn to_string_lossy(&self) -> Cow<'_, str> { - self.inner.to_string_lossy() - } - - pub fn to_owned(&self) -> Buf { - Buf { inner: self.inner.to_owned() } - } - - pub fn clone_into(&self, buf: &mut Buf) { - self.inner.clone_into(&mut buf.inner) - } - - #[inline] - pub fn into_box(&self) -> Box { - unsafe { mem::transmute(self.inner.into_box()) } - } - - pub fn empty_box() -> Box { - unsafe { mem::transmute(Wtf8::empty_box()) } - } - - #[inline] - pub fn into_arc(&self) -> Arc { - let arc = self.inner.into_arc(); - unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) } - } - - #[inline] - pub fn into_rc(&self) -> Rc { - let rc = self.inner.into_rc(); - unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } - } - - #[inline] - pub fn make_ascii_lowercase(&mut self) { - self.inner.make_ascii_lowercase() - } - - #[inline] - pub fn make_ascii_uppercase(&mut self) { - self.inner.make_ascii_uppercase() - } - - #[inline] - pub fn to_ascii_lowercase(&self) -> Buf { - Buf { inner: self.inner.to_ascii_lowercase() } - } - - #[inline] - pub fn to_ascii_uppercase(&self) -> Buf { - Buf { inner: self.inner.to_ascii_uppercase() } - } - - #[inline] - pub fn is_ascii(&self) -> bool { - self.inner.is_ascii() - } - - #[inline] - pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { - self.inner.eq_ignore_ascii_case(&other.inner) - } -} diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index c2550dcfd83..230067907c8 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"] -- cgit 1.4.1-3-g733a5 From 9a8f117d7b20e5503b8499112c26076cbbf570eb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 15 Jan 2024 15:49:58 +0000 Subject: 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 af47455c16d..a08f36ddfda 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); + + self.register_wf_obligation(ty.into(), expr.span, traits::WellFormed(None)); - Ty::new_array_with_const_len(tcx, t, count) + ty } fn check_repeat_element_needs_copy_bound( -- cgit 1.4.1-3-g733a5 From 2ad780eaf03816ae26cd4285eb379e2bb0c55672 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:18:48 +0100 Subject: 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 f6c5e4a5cd6..1b7be98600f 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, .. } => { -- cgit 1.4.1-3-g733a5 From bf913ad0aee7e97b93f50824e9b2292414670954 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:42:23 +0100 Subject: Simplify use of `ValidityConstraint` We had reached a point where the shenanigans about omitting empty arms are unnecessary. --- compiler/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 6244cf0ff7d..72459582113 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 { -- cgit 1.4.1-3-g733a5 From edb27a306a29b5b3e9f63da3e74e985736905bc2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:23:21 +0100 Subject: Make all the empty pattern decisions in `usefulness` --- compiler/rustc_pattern_analysis/src/constructor.rs | 19 +++++-------------- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- compiler/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 c1042d5b66e..af553840898 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 cfe4ca3ce93..cf3dddfafeb 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 72459582113..490a84c65db 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. -- cgit 1.4.1-3-g733a5 From de77f1a86ef732d3cbffd284bb32c5908a535748 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 22:47:52 +0100 Subject: Simplify empty pattern logic a bit --- compiler/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 490a84c65db..ec9cbeb4fef 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; -- cgit 1.4.1-3-g733a5 From d95644d3ae276ba787cdf9214a97f27b82c1348e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 10 Jan 2024 23:08:31 +0100 Subject: 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 ec9cbeb4fef..d8c63e0571d 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 { -- cgit 1.4.1-3-g733a5 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: 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 f6bd083c4cc..6bc2415218d 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 3565c7978cf..8c77e8be9da 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 c0be6299e52..ddf5cb0e6ee 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 d13e85152a9..4af29d1a7f6 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit d13e85152a977cd0bcaf583cf5f49e86225697de +Subproject commit 4af29d1a7f64f88a36539662c6a84fe1fbe6cde1 -- cgit 1.4.1-3-g733a5 From 65409c46096886a6f25bf0d327e23613c821f0ea Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Mon, 15 Jan 2024 12:26:45 -0500 Subject: Ensure `callee_id`s are body owners --- src/tools/clippy/clippy_lints/src/derive.rs | 4 +-- .../clippy_lints/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 d8abe411030..a8217d0602a 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 c7980060807..814ccaa36f5 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 61d0663aa83..a07d6587bf9 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; -- cgit 1.4.1-3-g733a5 From ee370a1157be0b0260a7804c91a8e78fd03e932a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 15 Jan 2024 09:23:05 -0800 Subject: 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 fea194a80ef..6f3be1f6e93 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", "") -- cgit 1.4.1-3-g733a5 From 924ea05103da3bd25e6021535615ca7f8b9ec76d Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 12 Jan 2024 08:22:05 +0100 Subject: 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). --- compiler/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 7c869adbd83..11b579a1f85 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)?, + }) + } +} -- cgit 1.4.1-3-g733a5 From 16ba56c24238b2f44e0a97da760c83d8795abd80 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 12 Jan 2024 08:21:42 +0100 Subject: 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 +- compiler/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 ++- compiler/rustc_codegen_cranelift/src/abi/mod.rs | 13 ++-- .../rustc_codegen_cranelift/src/intrinsics/llvm.rs | 2 +- .../src/intrinsics/llvm_aarch64.rs | 2 +- .../src/intrinsics/llvm_x86.rs | 86 +++++++++++----------- .../rustc_codegen_cranelift/src/intrinsics/mod.rs | 22 +++--- .../rustc_codegen_cranelift/src/intrinsics/simd.rs | 24 +++--- compiler/rustc_codegen_ssa/src/mir/block.rs | 21 ++++-- .../rustc_const_eval/src/interpret/terminator.rs | 8 +- .../src/transform/check_consts/check.rs | 4 +- .../rustc_const_eval/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 +- compiler/rustc_middle/src/util/find_self_call.rs | 9 ++- .../src/build/custom/parse/instruction.rs | 5 +- .../rustc_mir_build/src/build/expr/as_rvalue.rs | 10 ++- compiler/rustc_mir_build/src/build/expr/into.rs | 6 +- compiler/rustc_mir_build/src/build/matches/test.rs | 10 ++- compiler/rustc_mir_build/src/build/scope.rs | 5 +- compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 7 +- .../rustc_mir_dataflow/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 +- .../rustc_mir_transform/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 +++-- compiler/rustc_mir_transform/src/instsimplify.rs | 4 +- compiler/rustc_mir_transform/src/lib.rs | 12 +-- compiler/rustc_mir_transform/src/lint.rs | 2 +- .../rustc_mir_transform/src/lower_intrinsics.rs | 24 +++--- .../rustc_mir_transform/src/lower_slice_len.rs | 2 +- compiler/rustc_mir_transform/src/promote_consts.rs | 7 +- compiler/rustc_mir_transform/src/shim.rs | 5 +- compiler/rustc_monomorphize/src/collector.rs | 4 +- compiler/rustc_smir/src/rustc_smir/convert/mir.rs | 2 +- compiler/rustc_span/src/source_map.rs | 2 +- .../clippy/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 b4a73574aa2..8909f47af2d 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 6606be2f9f4..4f66468a865 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 bb802c4eb46..0f22fc21d3c 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 0457b4e6ddc..b304fb5589f 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 232bd741825..5c9056272cc 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 9c0f53ddb86..33190e19104 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 795c8daec6a..abd70dd4458 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 a38a728c926..1345c4614e2 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 c8f9c3997a6..f6f3b85d3ef 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 81114cbf40d..994dc66835c 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 15249402a63..a27853fa0a8 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 78ea7c2dbfc..d56d17892d5 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 a1662f25e14..e35b4029b45 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 2358caffc9b..7b993279f18 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 ae9595d7e64..89c65d92325 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 0b73691204d..9c2f336e912 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 1a6b0f4031d..239929a2c0e 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 462076d750f..6ebe57e29da 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 2ccf5a9f6f7..4696f54c897 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 9f1e4ac11c2..0ca4fce5da9 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 e3dea2212df..5428333a116 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 f799be165ec..6e8af7bb6df 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 060a3b521a4..2978491d646 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 53e5d70f946..990be30b2d6 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 48b237f3ae6..6827797df37 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 c9930565186..862876f53c7 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 cae35765308..38ee26c5a87 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 5373876d1c2..08a5d70fb6f 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 379e96e263c..eaa36e0cc91 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 3d74ef7e327..0f0a2bcd870 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 990cfb05e60..a6750911394 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 49b0edc0db8..2cc76f30fcf 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 340bb1948eb..61d99f1f018 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 ebefc3b47cc..67668a216de 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 4f0f63d22a4..a28db0defc9 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 98076077b9a..6f3fd14cd97 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 c0c0a3f5ee6..5b269185e87 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 18f588dccf6..897375e0e16 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 daeb56666f4..8137525a332 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 841b86fed45..c00093ea27e 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 f6b820bfcd0..89414ce940e 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 92f001cc321..1d7bad6cba3 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 c5fb6f7a26f..2f3d9d69b85 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 8253ffefcaa..72a8b23721d 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 c62c351e716..3416a93e3c4 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 703985b9d4b..f9cc5f19125 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 668ea9fcf3b..81f4fcc2133 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 { -- cgit 1.4.1-3-g733a5 From 8f440f06c68846fc0094f5c2d1c9509ec80455ef Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sat, 7 Oct 2023 14:34:29 +0200 Subject: 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 +++++++++++++-------- .../large_assignments/box_rc_arc_allowed.stderr | 4 +- tests/ui/lint/large_assignments/copy_into_fn.rs | 24 +++++ .../ui/lint/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 234ccee5546..5597609c7d7 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 1d7bad6cba3..070580860c1 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 b45cbe5da4d..fefb3a9621b 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 00000000000..ee204bf7af1 --- /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 00000000000..f05fc33e17e --- /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 + -- cgit 1.4.1-3-g733a5 From 8b66f497ebe3458226dbcc91501b5dd1c1728b45 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 15 Jan 2024 19:17:28 +0100 Subject: 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 +++++++++++++++++------ compiler/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 ed10a515508..0bc432fa6f0 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 cfe4ca3ce93..4266e2a405e 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 e82d6666b1a..dbb2bf4a4cb 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 6244cf0ff7d..1d505f0c1cd 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, -- cgit 1.4.1-3-g733a5 From 448c4a4efb689f5d7d1479a1c3d1cac0d3a1fc82 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 15 Jan 2024 19:26:55 +0100 Subject: Remove the unused `overlapping_range_endpoints` Vec --- compiler/rustc_pattern_analysis/src/rustc.rs | 2 -- compiler/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 dbb2bf4a4cb..87e70d68c1b 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 1d505f0c1cd..c7894994213 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 }) } -- cgit 1.4.1-3-g733a5 From 604d2083d3921471e5b0d4f90baf61a746ba3603 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 15 Jan 2024 13:09:46 -0800 Subject: 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 f53a6f9e134..f5d765e690d 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 = "", -- cgit 1.4.1-3-g733a5 From 37849643c670f7f0809948986329b04ce5c90405 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 14 Jan 2024 18:08:02 -0500 Subject: 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 +- compiler/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 945f17d5df2..69d3974184d 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 0240f012da0..674a0984ae9 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 9ff04c4e910..eecbf86c173 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; -- cgit 1.4.1-3-g733a5 From f1494425bbb68e71f2bf3aa215fb71978b36acf2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 13:40:01 +1100 Subject: 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 45d3795eff8..1c36f2871dd 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 ceef6386780..b658a656259 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 98264bdc1af..649e8e52a49 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 6bdcca40ed6..e06d1676358 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 015e03d5165..8408769cdc1 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 abc9e5f7f64..388cd645631 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 c5ac17600cd..921ca6cf4e1 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 67014f792c8..58224eeaf62 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 16a2c4e33bd..4be78062f3f 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 90eeb1a6686..160b348bd63 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 f3299834bce..3bf19f28072 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 739bc5f0b51..6c94b90c656 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 391a69e0e82..d7122f4b1a0 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 2e6845190aa..77db24ef51b 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 8ad5042ff7b..e8c0e7a7a22 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 da692ca3aa2..7163681d3a0 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 0274401f004..2bf93487cec 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 3244e1e3afd..a0687925d63 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 fb893e37960..3c660551dea 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 41838b8513f..86ff7fc4f07 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 4f45ae0b3d4..7b166662b5d 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 82582b309bf..6d577b3d485 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 e693866e277..9080d95eff5 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 facf5b5b4cf..9c218a37e6c 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 2d1ff24e62d..03dbb59d26b 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 2d927a08356..f058be83900 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 bb6219e851c..47bfb116449 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 75018442d07..d8dca8a85c3 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 1f0630636dd..7d453398759 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 dbc4fad7a23..015365c2b3e 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 f1691ffc5e6..0a342cb3673 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 691c6cd1e7d..b6552c62ff9 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 6f7f23475b8..6776911563d 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 4a32745d292..7c242e2c328 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 7f5dd3bb646..3a4fc6743f5 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 be99e59a826..2ad4e55b4ed 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 a9a18a180dd..5cfb40ce528 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 5d48cbd62f2..418efa7fcb5 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 557cbf22bfa..1acc2616912 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 369ebe891f1..c883eb4baf2 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 49d39d36603..f4372ad282e 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 b2f0eee2cc0..a6421e797f6 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 -- cgit 1.4.1-3-g733a5 From 1f9353ae2ca81b0a508e38751b0d3ab213526f56 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 14:12:10 +1100 Subject: 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 | 22 +++++++++++----------- 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, 34 insertions(+), 22 deletions(-) diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index cfee55ed31a..a6a427aca00 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 473335ff641..48516217592 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 fa7f2a116c2..e18e7191e61 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 6e26c61aac9..c3969f8ce99 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -1,51 +1,51 @@ 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(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, 16, 01, 02, 17, 00, 02, 17, 00, 18, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +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 + 22, 1) to (start + 2, 23) -- Code(Zero) at (prev + 2, 23) to (start + 0, 24) +- 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, 1c, 01, 03, 0f, 00, 03, 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, 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 + 28, 1) to (start + 3, 15) -- Code(Zero) at (prev + 3, 15) to (start + 0, 16) +- 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) diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage index f1ddb1da780..71e15fc11eb 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 92850c8a188..1f4cc67af83 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 09839183566..c68c0be80b1 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 bf4c2d8d685..fd3811b6937 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 af250f3fb71..c6557b48e27 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 c9d497651c9..90c16288d66 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 781b90b3566..d60916a9798 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 } } -- cgit 1.4.1-3-g733a5 From 40166c894ad7f3de348545da0e92d88e2ead393f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 17:37:24 +1100 Subject: 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 cae96f59319..7d60033c3e8 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 = -- cgit 1.4.1-3-g733a5 From a3fe3bbb2c80d155e31230bb75078b44904051bc Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 6 Nov 2022 19:26:25 +0300 Subject: 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 ++++++ tests/ui/borrowck/fn-item-check-trait-ref.stderr | 12 +++++ tests/ui/borrowck/fn-item-check-type-params.rs | 57 ++++++++++++++++++++++ tests/ui/borrowck/fn-item-check-type-params.stderr | 43 ++++++++++++++++ tests/ui/higher-ranked/trait-bounds/issue-59311.rs | 1 + .../higher-ranked/trait-bounds/issue-59311.stderr | 11 ++++- .../implied-bounds-on-trait-hierarchy-1.rs | 38 +++++++++++++++ .../implied-bounds-on-trait-hierarchy-1.stderr | 16 ++++++ .../implied-bounds-on-trait-hierarchy-2.rs | 45 +++++++++++++++++ .../implied-bounds-on-trait-hierarchy.rs | 39 --------------- tests/ui/lifetimes/lifetime-errors/issue_74400.rs | 2 + .../lifetimes/lifetime-errors/issue_74400.stderr | 32 +++++++++++- .../ui/type-alias-impl-trait/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 -------------- 18 files changed, 303 insertions(+), 83 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 create mode 100644 tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs 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/implied-bounds/implied-bounds-on-trait-hierarchy.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 9c0f53ddb86..05979bfabbd 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 39e94902cfe..1a416a4d10b 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 00000000000..bdbb52e974f --- /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 00000000000..92fd67c316c --- /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 00000000000..805c0d00de5 --- /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 00000000000..3a29edc55c5 --- /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 3ad548450e5..387c78a802a 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 e50aad876d8..3053a299802 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-1.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs new file mode 100644 index 00000000000..b532a110a1c --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs @@ -0,0 +1,38 @@ +// issue: #84591 + +// Subtrait was able to incorrectly extend supertrait lifetimes even when +// supertrait had weaker implied bounds than subtrait. + +trait Subtrait: Supertrait {} +trait Supertrait { + fn action(self); +} + +fn subs_to_soup(x: T) +where + T: Subtrait, +{ + soup(x) +} + +fn soup(x: T) { + x.action(); +} + +impl<'a, 'b: 'a> Supertrait for (&'b str, &mut &'a str) { + fn action(self) { + *self.1 = self.0; + } +} + +impl<'a, 'b> Subtrait<&'a &'b str> for (&'b str, &mut &'a str) {} + +fn main() { + let mut d = "hi"; + { + 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 00000000000..f44defccf58 --- /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 00000000000..511a9ad9a2a --- /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/implied-bounds/implied-bounds-on-trait-hierarchy.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs deleted file mode 100644 index 9c26cd59d10..00000000000 --- a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs +++ /dev/null @@ -1,39 +0,0 @@ -// check-pass -// known-bug: #84591 - -// Should fail. Subtrait can incorrectly extend supertrait lifetimes even when -// supertrait has weaker implied bounds than subtrait. Strongly related to -// issue #25860. - -trait Subtrait: Supertrait {} -trait Supertrait { - fn action(self); -} - -fn subs_to_soup(x: T) -where - T: Subtrait, -{ - soup(x) -} - -fn soup(x: T) { - x.action(); -} - -impl<'a, 'b: 'a> Supertrait for (&'b str, &mut &'a str) { - fn action(self) { - *self.1 = self.0; - } -} - -impl<'a, 'b> Subtrait<&'a &'b str> for (&'b str, &mut &'a str) {} - -fn main() { - let mut d = "hi"; - { - let x = "Hello World".to_string(); - subs_to_soup((x.as_str(), &mut d)); - } - println!("{}", d); -} diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs index ddb8bacce8f..f17e0a678c9 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 677f918fe93..beb838d2ff8 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 dcc4b8021ea..17c1f8897bf 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 121664bd956..f5d3a218542 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 de388329489..2f90c4e00e3 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 c5ff92c8875..00000000000 --- 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); -} -- cgit 1.4.1-3-g733a5 From 8d4693c0f803d87c1ea127093dab5f0499879e5c Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 7 Nov 2022 12:39:54 +0300 Subject: 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 4a76d877af0..011b5b760c2 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 1a416a4d10b..39e94902cfe 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 00000000000..dffa1713eff --- /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 00000000000..e025d5d468a --- /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 7ff195230bf..66546ac489d 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 161609a5f86..6c49098aad3 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 -- cgit 1.4.1-3-g733a5 From aac2f84794d3122216e07a5a6b00b6facf5e9f16 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Wed, 8 Nov 2023 09:22:24 +0000 Subject: wf-check type annotations before normalization --- .../src/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 152ceeee869..0aaeacb6a23 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 dffa1713eff..629d807cb7f 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 e025d5d468a..b0e1a118fab 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 -- cgit 1.4.1-3-g733a5 From 66090ef7ba5f8586879f8029400a1cc851e7c57f Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Thu, 9 Nov 2023 10:12:56 +0000 Subject: 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 e21ede47f6d..14f14ae6e2e 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 } -- cgit 1.4.1-3-g733a5 From 290651be72ef3c33c47ac73093b26f752e213f6d Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 16 Jan 2024 11:06:42 +0100 Subject: don't store const var origins for known vars --- .../src/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 ++--- compiler/rustc_infer/src/infer/relate/combine.rs | 26 +++---- .../rustc_infer/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 4aefadf590d..6e1889d3538 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 c7cab048db1..d256994d8d1 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 8ca97ae1b8e..99033922bdf 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 e164041c599..002aad19c49 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 4b254fc7df5..9e1dab12b4d 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 27d37fd9369..417c8695e24 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 f317ccee691..959b0903127 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 6e50e894046..c35799ef47f 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 }) } - }) + } } } -- cgit 1.4.1-3-g733a5 From 3599c18874b6c8cc74ca2228fe61b17731769771 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 16 Jan 2024 10:03:29 +0000 Subject: 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 ac2ca23ad41..9422a594488 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 21781490637..9bdb9929bec 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 e7a0a96a1e6..37cd94bf7b7 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 { -- cgit 1.4.1-3-g733a5 From 8bb1eaee64e170153d21e64cdb437f3d36acd194 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 22:14:48 +0000 Subject: Introduce helper that deals with moving async args into the coroutine --- compiler/rustc_ast_lowering/src/item.rs | 363 +++++++++++++++++--------------- 1 file changed, 193 insertions(+), 170 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a3ff02f5f69..c8e639b7a96 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1082,194 +1082,217 @@ 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), - }; + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + decl, + body, + coroutine_kind, + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + ); - 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, - ); + // 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); - // 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, - ); + (parameters, expr) + }) + } - statements.push(move_stmt); - statements.push(pattern_stmt); - }; + /// 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); - parameters.push(new_parameter); - } + (ident, false) + } + }; - let mkbody = |this: &mut LoweringContext<'_, 'hir>| { - // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); + let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - // 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)); + // 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), + }; - // As noted above, create the final block like + 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 $param_pattern = $raw_param; - // ... - // drop-temps { } - // } + // let __argN = __argN; + // let = __argN; // ``` - let body = this.block_all( + // + // 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, - this.arena.alloc_from_iter(statements), - Some(user_body), + Some(move_expr), + move_pat, + hir::LocalSource::AsyncFn, ); - 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, + // 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); }; - let coroutine_expr = this.make_desugared_coroutine_expr( - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, - body.span, - desugaring_kind, - hir::CoroutineSource::Fn, - mkbody, + + 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), ); - let hir_id = this.lower_node_id(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.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, + ); - (this.arena.alloc_from_iter(parameters), expr) - }) + 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( -- cgit 1.4.1-3-g733a5 From 450cb5eda6d1db8b5b45a3775cb5316bb623dc63 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 14 Jan 2024 23:23:30 +0100 Subject: Don't ICE if TAIT-defining fn contains a closure with `_` in return type --- .../src/collect/type_of/opaque.rs | 31 +++++++++++-------- tests/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 1f7ca48234a..ade24259ed4 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 00000000000..04e2323ec4a --- /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() {} -- cgit 1.4.1-3-g733a5 From 22833c177e23c1c80e7ad1cbea33d758dcd94c28 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Mon, 15 Jan 2024 01:21:03 +0100 Subject: 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 093aeb4b279..3d6c826d6ac 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 68dd6570d00..c5cacfd3cd3 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`. -- cgit 1.4.1-3-g733a5 From f1ee076f8188c02a2f4d06fc2fde2f58bdb3d6f4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 23:12:46 +0000 Subject: 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 | 39 +++++++++------------- compiler/rustc_ast_lowering/src/item.rs | 29 ++++++++++------ .../rustc_error_codes/src/error_codes/E0708.md | 6 ++-- .../async-borrowck-escaping-closure-error.rs | 3 +- .../async-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, 40 insertions(+), 88 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 e7177402db1..8615016cda5 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 2811fe104cd..4843d36372d 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 e0b1a10c82e..0920de48eb8 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, + 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, - hir::CoroutineDesugaring::Async, + coroutine_kind, hir::CoroutineSource::Closure, - |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), + 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 c8e639b7a96..dd3f7289a60 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 9287fc803d1..61a853ac446 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 e667b72aee5..f8ff9186842 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 1d8d1c67bae..00000000000 --- 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 3b15f35c260..1440d918c50 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 d2659553699..00000000000 --- 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 e65a6eb4939..77631b36e0f 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 -- cgit 1.4.1-3-g733a5 From f4e35c60b04b381395150669f1e8656dccc5f94f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Jan 2024 19:24:03 +0000 Subject: 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 1a4e03d50ca..d486f069989 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 77631b36e0f..e65a6eb4939 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 -- cgit 1.4.1-3-g733a5 From 04a5ee6f1d6ab1270b95c6c91a718d900a762eb8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Jan 2024 19:38:53 +0000 Subject: Deal with additional wrapping of async closure body in clippy --- .../clippy/clippy_lints/src/async_yields_async.rs | 98 +++++++++++++--------- .../clippy_lints/src/redundant_closure_call.rs | 20 ++++- src/tools/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 bb08ac7508b..eeaa3de3725 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 cde08dfcc74..334e6770ae4 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 62de661f8ff..8c4d71e68f8 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 } -- cgit 1.4.1-3-g733a5 From f91ccf9ace393a681922b145e56e7e3fb0041657 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 10 Jan 2024 11:46:17 -0800 Subject: 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 +- tests/ui-fulldeps/stable-mir/check_allocation.rs | 6 +- tests/ui-fulldeps/stable-mir/check_defs.rs | 6 +- tests/ui-fulldeps/stable-mir/check_instance.rs | 6 +- tests/ui-fulldeps/stable-mir/check_item_kind.rs | 6 +- tests/ui-fulldeps/stable-mir/check_ty_fold.rs | 6 +- tests/ui-fulldeps/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 4bac98909ad..7633739f289 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 30b42bc3bfa..7d7469597af 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 93def93127c..fb5e13eb13b 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 e9a2599d873..4a124adb2b6 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 5cb07eabf41..1e039e5ae51 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 72e0e09e6e3..0a7f00029f2 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 b90d47d4540..14cbf9e9f81 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 fc56e24814b..c802316c1d8 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 c2035430a33..8258883436f 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 8c3fda7b6bb..40f2d901a2b 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 b0596b18823..63a6a5e47e8 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 027b0e7d9e8..d7739770b70 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<()> { -- cgit 1.4.1-3-g733a5 From e12101c4db03b1cd35fcc288f8e6568f552ee51c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 16 Jan 2024 21:14:39 +0100 Subject: 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 ea194e10def..c45a4a410f9 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))] -- cgit 1.4.1-3-g733a5 From ee007ab187dc3eb9587a787d1029c539d54710b0 Mon Sep 17 00:00:00 2001 From: novafacing Date: Tue, 16 Jan 2024 13:27:58 -0800 Subject: proc_macro_c_str_literals: Implement Literal::c_string constructor --- library/proc_macro/src/lib.rs | 8 ++++++++ .../feature-gates/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 6e664a162df..ca83e2be5c1 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 00000000000..5554c813925 --- /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 00000000000..9bba1d50ce3 --- /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 3bea5d75779..5a533b9e17e 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 07c9f464961..801c616c804 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 c96aa73175f..2ec62072020 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 -- cgit 1.4.1-3-g733a5 From 666030c51b87509a065867f99bf7317a5486470a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 20 Mar 2023 21:37:36 +0000 Subject: Simplify binary ops. --- compiler/rustc_mir_transform/src/gvn.rs | 111 ++++++- tests/mir-opt/const_prop/boolean_identities.rs | 7 +- .../const_prop/boolean_identities.test.GVN.diff | 12 +- .../const_prop/boxes.main.GVN.panic-abort.diff | 9 +- .../const_prop/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 +- .../mir-opt/const_prop/mult_by_zero.test.GVN.diff | 2 +- tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff | 357 +++++++++++++-------- tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff | 357 +++++++++++++-------- .../gvn.arithmetic_checked.GVN.panic-abort.diff | 101 ++++-- .../gvn.arithmetic_checked.GVN.panic-unwind.diff | 101 ++++-- tests/mir-opt/gvn.comparison.GVN.panic-abort.diff | 10 +- tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff | 10 +- tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff | 18 +- .../mir-opt/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, 808 insertions(+), 431 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index dc3af038d80..3052369c3ca 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 f6575ac8e54..3b7ea25ad46 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 eca87af7527..0bd8413289e 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 b3fdaa5ee82..59ee38f5a2b 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 d0350c97253..9d87bd809d1 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 5227d7b8b8b..d2d61f86d5e 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 2fdb75c3100..b8afaeef43f 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 e9fb34749c1..6c2aab45d48 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 d524ad242fe..84eb6c5cfe8 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]; } - bb7: { -- _19 = Div(move _20, const 1_u64); -+ _19 = Div(_1, const 1_u64); + bb6: { +- _19 = Div(move _20, const 0_u64); ++ _19 = Div(_1, const 0_u64); StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb8, unwind unreachable]; + _18 = opaque::(move _19) -> [return: bb7, unwind unreachable]; } - bb8: { + bb7: { 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]; } - bb9: { -- _23 = Div(const 0_u64, move _24); -+ _23 = Div(const 0_u64, _1); + bb8: { +- _23 = Div(move _24, const 1_u64); ++ _23 = _1; StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb10, unwind unreachable]; +- _22 = opaque::(move _23) -> [return: bb9, unwind unreachable]; ++ _22 = opaque::(_1) -> [return: bb9, unwind unreachable]; } - bb10: { + bb9: { 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]; } - bb11: { -- _27 = Div(const 1_u64, move _28); -+ _27 = Div(const 1_u64, _1); + bb10: { +- _27 = Div(const 0_u64, move _28); ++ _27 = const 0_u64; StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb12, unwind unreachable]; +- _26 = opaque::(move _27) -> [return: bb11, unwind unreachable]; ++ _26 = opaque::(const 0_u64) -> [return: bb11, unwind unreachable]; } - bb12: { + bb11: { 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]; } - bb13: { -- _31 = Rem(move _32, const 0_u64); -+ _31 = Rem(_1, const 0_u64); + bb12: { +- _31 = Div(const 1_u64, move _32); ++ _31 = Div(const 1_u64, _1); StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb14, unwind unreachable]; + _30 = opaque::(move _31) -> [return: bb13, unwind unreachable]; } - bb14: { + bb13: { 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]; } - bb15: { -- _35 = Rem(move _36, const 1_u64); -+ _35 = Rem(_1, const 1_u64); + bb14: { +- _35 = Rem(move _36, const 0_u64); ++ _35 = Rem(_1, const 0_u64); StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb16, unwind unreachable]; + _34 = opaque::(move _35) -> [return: bb15, unwind unreachable]; } - bb16: { + bb15: { 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]; } - bb17: { -- _39 = Rem(const 0_u64, move _40); -+ _39 = Rem(const 0_u64, _1); + bb16: { +- _39 = Rem(move _40, const 1_u64); ++ _39 = const 0_u64; StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb18, unwind unreachable]; +- _38 = opaque::(move _39) -> [return: bb17, unwind unreachable]; ++ _38 = opaque::(const 0_u64) -> [return: bb17, unwind unreachable]; } - bb18: { + bb17: { 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]; } - bb19: { -- _43 = Rem(const 1_u64, move _44); -+ _43 = Rem(const 1_u64, _1); + bb18: { +- _43 = Rem(const 0_u64, move _44); ++ _43 = const 0_u64; StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb20, unwind unreachable]; +- _42 = opaque::(move _43) -> [return: bb19, unwind unreachable]; ++ _42 = opaque::(const 0_u64) -> [return: bb19, unwind unreachable]; } - bb20: { + bb19: { 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 9d69353934c..98e92d2a310 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]; } - bb7: { -- _19 = Div(move _20, const 1_u64); -+ _19 = Div(_1, const 1_u64); + bb6: { +- _19 = Div(move _20, const 0_u64); ++ _19 = Div(_1, const 0_u64); StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb8, unwind continue]; + _18 = opaque::(move _19) -> [return: bb7, unwind continue]; } - bb8: { + bb7: { 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]; } - bb9: { -- _23 = Div(const 0_u64, move _24); -+ _23 = Div(const 0_u64, _1); + bb8: { +- _23 = Div(move _24, const 1_u64); ++ _23 = _1; StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb10, unwind continue]; +- _22 = opaque::(move _23) -> [return: bb9, unwind continue]; ++ _22 = opaque::(_1) -> [return: bb9, unwind continue]; } - bb10: { + bb9: { 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]; } - bb11: { -- _27 = Div(const 1_u64, move _28); -+ _27 = Div(const 1_u64, _1); + bb10: { +- _27 = Div(const 0_u64, move _28); ++ _27 = const 0_u64; StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb12, unwind continue]; +- _26 = opaque::(move _27) -> [return: bb11, unwind continue]; ++ _26 = opaque::(const 0_u64) -> [return: bb11, unwind continue]; } - bb12: { + bb11: { 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]; } - bb13: { -- _31 = Rem(move _32, const 0_u64); -+ _31 = Rem(_1, const 0_u64); + bb12: { +- _31 = Div(const 1_u64, move _32); ++ _31 = Div(const 1_u64, _1); StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb14, unwind continue]; + _30 = opaque::(move _31) -> [return: bb13, unwind continue]; } - bb14: { + bb13: { 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]; } - bb15: { -- _35 = Rem(move _36, const 1_u64); -+ _35 = Rem(_1, const 1_u64); + bb14: { +- _35 = Rem(move _36, const 0_u64); ++ _35 = Rem(_1, const 0_u64); StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb16, unwind continue]; + _34 = opaque::(move _35) -> [return: bb15, unwind continue]; } - bb16: { + bb15: { 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]; } - bb17: { -- _39 = Rem(const 0_u64, move _40); -+ _39 = Rem(const 0_u64, _1); + bb16: { +- _39 = Rem(move _40, const 1_u64); ++ _39 = const 0_u64; StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb18, unwind continue]; +- _38 = opaque::(move _39) -> [return: bb17, unwind continue]; ++ _38 = opaque::(const 0_u64) -> [return: bb17, unwind continue]; } - bb18: { + bb17: { 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]; } - bb19: { -- _43 = Rem(const 1_u64, move _44); -+ _43 = Rem(const 1_u64, _1); + bb18: { +- _43 = Rem(const 0_u64, move _44); ++ _43 = const 0_u64; StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb20, unwind continue]; +- _42 = opaque::(move _43) -> [return: bb19, unwind continue]; ++ _42 = opaque::(const 0_u64) -> [return: bb19, unwind continue]; } - bb20: { + bb19: { 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 6633df3ae70..a45d9920a68 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 d100a77fee5..9033b392bd4 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 ee3b9da2122..fefdf14bddc 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 a1408fe3434..9f19b2b59fa 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 d8248d22d38..0901896af53 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 e38a3d85209..4b95191ba82 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 23e33a0fa49..8c06e3a6385 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 b04728a9b0f..187290785c0 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 fcf99ac6918..99350bac478 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); -- cgit 1.4.1-3-g733a5 From 5fc23ad8e6b7a5ef0b5a6936cb043bd85f8bed59 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 25 Mar 2023 22:33:35 +0000 Subject: Simplify unary operations. --- compiler/rustc_mir_transform/src/gvn.rs | 20 +++ tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff | 18 +-- .../mir-opt/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 3052369c3ca..699b218d46d 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 0901896af53..02bf95840da 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 4b95191ba82..c5dcc8a8ec9 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 8c06e3a6385..f8f4fdcd732 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 00000000000..9469032f294 --- /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 00000000000..e672f6fb6ba --- /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; + } + } + -- cgit 1.4.1-3-g733a5 From 3c48243b6fd28aeb27c856f8d23433e9f3ebaa0d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 20 Mar 2023 20:15:59 +0000 Subject: Simplify Len. --- compiler/rustc_mir_transform/src/gvn.rs | 38 +++++++++++++++++++--- .../array_index.main.GVN.32bit.panic-abort.diff | 7 ++-- .../array_index.main.GVN.32bit.panic-unwind.diff | 7 ++-- .../array_index.main.GVN.64bit.panic-abort.diff | 7 ++-- .../array_index.main.GVN.64bit.panic-unwind.diff | 7 ++-- ...rge_array_index.main.GVN.32bit.panic-abort.diff | 7 ++-- ...ge_array_index.main.GVN.32bit.panic-unwind.diff | 7 ++-- ...rge_array_index.main.GVN.64bit.panic-abort.diff | 7 ++-- ...ge_array_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 699b218d46d..afc75ff1313 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 f9537661e8c..6d00dd5b212 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 07886779fea..7e2f72ab31b 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 f9537661e8c..6d00dd5b212 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 07886779fea..7e2f72ab31b 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 cf36109fdcb..bd987c01ab1 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 40ed9697180..e9ebef84ae0 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 cf36109fdcb..bd987c01ab1 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 40ed9697180..e9ebef84ae0 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 a52e6e35483..71635b8e9c3 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 fe0acee71eb..84205028d6d 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 a52e6e35483..71635b8e9c3 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 fe0acee71eb..84205028d6d 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 d937902e891..8ce05c9b340 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 dd4d24b12ea..7ed547eeb4a 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: { -- cgit 1.4.1-3-g733a5 From 22ed51e136c8ad3a07d181b90e7610501ea69816 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 19:29:08 +0000 Subject: Do not read a scalar on a non-scalar layout. --- compiler/rustc_mir_transform/src/gvn.rs | 9 +- tests/mir-opt/gvn.rs | 23 ++ .../mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff | 386 +++++++++++++++++++++ .../mir-opt/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 afc75ff1313..fc14ea2696f 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 f8f4fdcd732..31ea237cbec 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 00000000000..e49d759b8fc --- /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 00000000000..4e5608a4425 --- /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 │ ................ + } + -- cgit 1.4.1-3-g733a5 From 166fe54eba4b691b9c69b2a3a24e5b82bd9848e3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 8 Jan 2024 22:44:38 +0000 Subject: 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 fc14ea2696f..7a8e3b87b9b 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) { -- cgit 1.4.1-3-g733a5 From 0cc2102c4a615fa8f259de491675d9e64606b022 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 8 Jan 2024 22:54:05 +0000 Subject: 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 7a8e3b87b9b..390ec3e1a36 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, }; -- cgit 1.4.1-3-g733a5 From 2564811e7b7464d4e2ab8cd5a826bf7c2f9f7d8b Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 16 Jan 2024 14:31:25 -0800 Subject: 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 +- .../ui-fulldeps/stable-mir/check_trait_queries.rs | 4 +- tests/ui-fulldeps/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 7633739f289..873bd94e88f 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) => { + run_driver!($args, $callback) }; - ($args:expr, $callback:expr) => {{ +} + +/// 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 fffc454804d..2a2626654a0 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 fb1197e4ecc..c9fbe15ffb0 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 c802316c1d8..e6dd9fa132d 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 63a6a5e47e8..b0811364c09 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<()> { -- cgit 1.4.1-3-g733a5 From 7e1e61a4478b690113c86bf7b547e829969fe29d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 16 Jan 2024 18:34:44 -0500 Subject: Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 84976cd699f..1cff2ee6b92 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 84976cd699f4aea56cb3a90ce3eedeed9e20d5a5 +Subproject commit 1cff2ee6b92e0ad3f87c44b70b28f788b2528b3c -- cgit 1.4.1-3-g733a5 From b99c3ae6d66762b9faf863fa8078f5aad8b36205 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 15 Jan 2024 22:31:02 +0000 Subject: Get rid of the hir_owner query. --- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_incremental/src/assert_dep_graph.rs | 8 +-- .../rustc_incremental/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 6b347f7035a..309850d04d3 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 7b8d91702b3..6f909a0cc9d 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 f6acc60190a..842cc9fae9b 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 1574f0f1b31..949b786e3a7 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 af99c7d55c3..2d4d5deaefa 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 b9200f1abf1..168e7affe99 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 1dc77220881..89e712d47f5 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`. -- cgit 1.4.1-3-g733a5 From 20a8a23cb33fbc59fe89d64fa5dd51ccf33df415 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 16 Jan 2024 23:46:07 +0000 Subject: 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 +- tests/incremental/hashes/function_interfaces.rs | 76 ++--- tests/incremental/hashes/if_expressions.rs | 16 +- tests/incremental/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 +- tests/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 11d999ab328..87a8696b189 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 fe9af9eeb37..f9244d8adbf 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 eaef63386ff..7cba3c159e6 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 f685fe46d70..0a88dd4e155 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 bc83723a908..cb7a4e61e4f 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 1906843c7a2..93a8fcfea32 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 23b81705f9a..2aaaf94492c 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 937fd3ac879..cd80f8aa00a 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 b1ac6f6fa6c..4bccec61a7c 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 285f857c9cb..853fbc79fc8 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 ecb19480d65..ebcf1708a7a 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 bb83f8300d0..2adf05390bc 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 e50e5674c66..eabb8683e02 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 4a2706b4f01..6ea4d890e4d 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 7b8c6245d2d..0a5eba73977 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 3b2e18d17a9..028598244de 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 79398eb07fe..206c0595d54 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); } -- cgit 1.4.1-3-g733a5 From d59968b5f65c8b703f66913181d30d31df113d70 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 16 Jan 2024 23:23:31 +0000 Subject: 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 ---------------------- compiler/rustc_query_system/src/ich/impls_hir.rs | 22 -------------- .../rustc_query_system/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 5387880b6e6..057fe65d0af 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 309850d04d3..6773f7a4c66 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 97fa710b354..baa1635f731 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 eec0433ae68..e7eb9694f47 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 aa008d404c3..00000000000 --- 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 d170cd36ca6..5bd4fe04848 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 0a1c350b2db..86e3ecb1edd 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] = &[ -- cgit 1.4.1-3-g733a5 From 37a5464bc8e630beee4377ec7ccc0ee912291907 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Jan 2024 02:00:45 +0000 Subject: Eagerly instantiate closure ty --- compiler/rustc_hir_typeck/src/closure.rs | 146 ++++++++++----------- ...closure-print-generic-trim-off-verbose-2.stderr | 2 +- .../print/closure-print-generic-verbose-2.stderr | 2 +- .../ui/closures/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 57fdfa4ecb6..d11198d7fd4 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 1a13255429f..02d75ff1228 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 8553817247d..a5367688989 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 3d0af5eb171..fca8f25792a 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 | -- cgit 1.4.1-3-g733a5 From b82d1d32b4c4a998c0a88ea7156edc2c5b4e1439 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 18:07:49 +1100 Subject: 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 239929a2c0e..5144c9b8c13 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}")) + })?)) } /////////////////////////////////////////////////////////////////////////// -- cgit 1.4.1-3-g733a5 From 1ec567b99aa961435ee9b825d70d1f471ac7388b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 18:14:44 +1100 Subject: 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 5144c9b8c13..2cf6410990e 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( -- cgit 1.4.1-3-g733a5 From 19d6f068ee75d258a5f14d609894af49943f907e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 17 Jan 2024 02:59:47 +0100 Subject: Don't rely on contiguous `VariantId`s outside of rustc --- Cargo.lock | 1 + compiler/rustc_pattern_analysis/Cargo.toml | 1 + compiler/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 f85d523fc1b..0df01e5e29a 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 7cc585bea3a..1d0e1cb7e6a 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 c1042d5b66e..76098505b79 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 ed10a515508..867924180dd 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. -- cgit 1.4.1-3-g733a5 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: 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 ++- src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs | 5 ++++- src/tools/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 21077c312bd..d0d98eb3d62 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 450555d0cb5..90677151d25 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 3617df931e2..89f50d3a0a7 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 1c405fac7e4..0af141ff99a 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 f4b424259de..c2fd4558fd7 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 6b347f7035a..6d5917c7b99 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 adc09025809..116de6fb04d 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 5d5a4789734..1c0a1a69513 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 d36e0892d19..e76303bc6df 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 ed3dd1e39df..3ecf6c5e428 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 ce3a4b4c80c..1ce0240f7b8 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 95813cb68a6..fe8c36dbe06 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 0f4528d1d5c..39decf1faab 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 c4987634b78..ff7e985bdfd 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 ff29fc5929c..528a52f4225 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 437517598ac..b2b20c95a7e 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 3c435294252..4e728d61b85 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 c823d07e2bd..5ca161e9309 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 77adcdd0e6b..7246214f9bf 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 8d38b87e1d7..b26ebe5cee3 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 482eaed77d1..979b117db25 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 cdf8528f48a..2e54690d123 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 0fa6edaa5d7..7f576279432 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, } } } -- cgit 1.4.1-3-g733a5 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: 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 0a2280545da..ec5f32539f2 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 -- cgit 1.4.1-3-g733a5 From a87034c2977369c8e7670dbe477e3196c45e4615 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 7 Dec 2023 14:16:11 +0000 Subject: 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 --- .../src/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 e4768c67af5..00000000000 --- 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 95932db14e1..48b58f6f06a 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 eb0a2fda290..95149987033 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 9f92b8995b7..a9340c40f44 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 00000000000..ca6590d1502 --- /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 00000000000..72a35f38eca --- /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 00000000000..06334230400 --- /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 00000000000..7398d7ef790 --- /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 -- cgit 1.4.1-3-g733a5 From 4db93c57507dd7c2c3a5cfe9509b67494824a829 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Jan 2024 21:30:45 +0000 Subject: Stop using track_errors for some forever unstable rustc_attr analyses --- compiler/rustc_hir_analysis/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 1f7ca48234a..4f445386795 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 f5abb7261c0..16e530ca946 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 dea3f1a9930..60cd8c39fa0 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 5264d5aa26f..c211e1af046 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 } -- cgit 1.4.1-3-g733a5 From b1ce8a4ecdcdb179d023d9fd1061575ba651aeeb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Jan 2024 22:13:39 +0000 Subject: Move `check_mod_impl_wf` query call out of track_errors and bubble errors up instead. --- compiler/rustc_hir_analysis/src/impl_wf_check.rs | 46 +++++-- .../src/impl_wf_check/min_specialization.rs | 132 +++++++++++++-------- compiler/rustc_hir_analysis/src/lib.rs | 15 +-- compiler/rustc_middle/src/query/mod.rs | 3 +- .../in-trait/return-dont-satisfy-bounds.rs | 2 + .../in-trait/return-dont-satisfy-bounds.stderr | 26 +++- .../specializing-constness-2.stderr | 14 ++- 7 files changed, 163 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 3f9b1f384d7..2fe08ead72b 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 93dd2342a4d..6d685aec663 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); - - 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 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); - } + let mut res = check_has_items(tcx, impl1_def_id, impl2_node, span); + + 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) + }; + + 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 16e530ca946..1a370ad10cf 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 1dc77220881..6e5870df7c1 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 ad73b12feb5..ff265e576b9 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 db587d069f8..638de01f913 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` + +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 -For more information about this error, try `rustc --explain E0277`. +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 5210a694201..e5b9493b3ce 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` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. -- cgit 1.4.1-3-g733a5 From 49347ee12dd23c357d45374a6e442e2c32fa4202 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 08:57:07 +0000 Subject: 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 4c3455c7240..d66f073b1b4 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 1a370ad10cf..da9a97db9a4 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 6e5870df7c1..15f0dc0208d 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 -- cgit 1.4.1-3-g733a5 From 557b11187090b0ec749b07858c6ac18f95b7490e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 14:29:54 +0000 Subject: Make crate_inherent_impls fallible and stop using `track_errors` for it --- compiler/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 +- compiler/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 +- compiler/rustc_resolve/src/late/diagnostics.rs | 6 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/types.rs | 4 +- src/librustdoc/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 9f4f1413650..b9e72a3b1ea 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 3162004a634..abef365c3ca 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 d66f073b1b4..63ea0272014 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 da9a97db9a4..08956d222d2 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 ac8701a33d4..065052d9a5d 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 10c31d8c641..4dc802008d0 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 3bf1e1312b3..0b8a25eedaf 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 912c2f36eb3..c3d6c21c402 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 a458b528a97..2d4e49e27d9 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 8a4fd01437f..e745913fabc 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 b9200f1abf1..a49825bdd70 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 15f0dc0208d..b3aa02e1aa3 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 a41d4f1ad58..8d88488e167 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 227a0753d04..d85b541d363 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 070580860c1..20e70f87b75 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 58ff4d8c793..5a95f2083f6 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 014bcb1a881..aab974ad79e 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 90eb783c7ca..6710193f961 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 dbff33dc1ec..30b3e5c784d 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, -- cgit 1.4.1-3-g733a5 From 18e66432c40e8c136b5d0fab27137fdabd579ae0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 12 Jan 2024 16:58:29 +0000 Subject: Fix clippy --- src/tools/clippy/clippy_lints/src/derive.rs | 3 ++- src/tools/clippy/clippy_lints/src/inherent_impl.rs | 3 ++- src/tools/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 d8abe411030..d1fe9f5cbec 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 e4781752e75..fb7b82ec304 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 903d3a2ab89..82a37bb4f27 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 c09d3d1862b..c1ab020117c 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 e38c66f6741..0602eeaa704 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 cdf8528f48a..1a4b22799f2 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); -- cgit 1.4.1-3-g733a5 From 12c19a2bb777a87c10afe1a7ea7fbee00def730d Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 17 Jan 2024 10:38:50 +0000 Subject: 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 --- compiler/rustc_target/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 e2e707f4a1a..90df3c69684 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 }, } -- cgit 1.4.1-3-g733a5 From d6b99b9c920f3c12326b0e7110236e9fe7c7ba52 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jan 2024 14:23:41 +0000 Subject: 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 6c9000c45f6..4028de27cae 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 00000000000..529913479ef --- /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 00000000000..b54b9f908b2 --- /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`. -- cgit 1.4.1-3-g733a5 From 8507f5105bb5294d802c38918b0b21916b376c16 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Thu, 11 Jan 2024 01:36:05 +0700 Subject: 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 + .../debuginfo/collapse-debuginfo-external-attr.rs | 31 ++++++++++++ ...se-debuginfo-external-flag-overriden-by-attr.rs | 34 +++++++++++++ .../debuginfo/collapse-debuginfo-external-flag.rs | 26 ++++++++++ tests/debuginfo/collapse-debuginfo-no-attr.rs | 2 +- .../debuginfo/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 475dd348e7b..3e3b4814300 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 0a1c4430397..edc9c5a9130 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 2b43fae6852..4a1c00f0104 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 363b52aef8a..1a39708ed8e 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 4442b67df6e..68b6f69854d 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 588139a303c..555c822ad6d 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 49e849964be..20e3ae3ba94 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 ad9296a4cc8..a5d9e0fcf44 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 ac15c3b407b..e751ff13a34 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 f4bf79f93f2..6c91929fcbe 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 d03965b539c..21623fdc1d2 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 72b62a795fc..44795022cba 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 00000000000..f36b0833ad5 --- /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 00000000000..e5cbc1a685d --- /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 00000000000..9a0aef38ea6 --- /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 230c8795be3..d156c381a15 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 00000000000..76a97a325d7 --- /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); +} -- cgit 1.4.1-3-g733a5 From f1ef930c9d06ebd8a3839346b493f49d40fa69e5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jan 2024 14:52:38 +0000 Subject: Don't ICE when deducing future output if other errors already occurred --- compiler/rustc_hir_typeck/src/closure.rs | 14 +++++++---- .../ui/async-await/inference_var_self_argument.rs | 12 ++++++++++ .../async-await/inference_var_self_argument.stderr | 28 ++++++++++++++++++++++ tests/ui/object-safety/erroneous_signature.rs | 17 +++++++++++++ tests/ui/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 57fdfa4ecb6..8a08ee21fbe 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 00000000000..fd8482f86b4 --- /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 00000000000..8a8c1ea03f1 --- /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 00000000000..cc1841cc4b2 --- /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 00000000000..f3b14ffe34c --- /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`. -- cgit 1.4.1-3-g733a5 From c70773d8a17438194c2415b91d81206ed10480a2 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 17 Jan 2024 14:47:59 -0500 Subject: Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 1cff2ee6b92..1ae631085f0 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 1cff2ee6b92e0ad3f87c44b70b28f788b2528b3c +Subproject commit 1ae631085f01c1a72d05df1ec81f3759a8360042 -- cgit 1.4.1-3-g733a5 From c48cdfe8ee582e3e67c9ffc036d8046add812565 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 14 Jan 2024 16:25:43 -0800 Subject: 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 +-- tests/ui/async-await/in-trait/async-default-fn-overridden.rs | 3 +-- .../in-trait/dont-project-to-specializable-projection.rs | 3 +-- .../in-trait/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 0c30bd1dfea..4f425d7286d 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 6c92735df0a..13400c88c71 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 8e26c4850fa..dab589b4651 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 38cb700fd58..8aeb26a7a95 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 f18c4a3a065..ccee2221e29 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 9bea6ea5742..1a93a6bf664 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 015e03d5165..23161458850 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 abc9e5f7f64..df29682968d 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 acd83de9493..a69eefe72cb 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 393573f7dc9..ae83f0103e6 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 297397ca26c..0e24b80124f 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 9d8647bf1f2..f94bcfe3193 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 2c9bd4ac97a..2336d4d0528 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 a7f0cabb4c2..9f5721b5e26 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 7fa133aaedc..b1a382958a1 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 6345ceb0c27..00dbdfb2389 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 491dfcc6ae0..8c01f1bddef 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 f21abf012ba..e2fd9f9dfea 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 0560cd9c5fe..b7336485eb8 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 aac74d3eacb..80c0b69a6f7 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 ec6464d0048..604156b4d37 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 c4ae279e6c1..151aa9092fb 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) { -- cgit 1.4.1-3-g733a5 From eb8c1f899818273490d32585d03c1bb74263472d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 17 Jan 2024 18:02:14 -0300 Subject: 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 2b818c0a990..bd14640e280 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 = [ -- cgit 1.4.1-3-g733a5 From b9ebeee4da258f1ed8bb93f0273180572a839058 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 17 Jan 2024 21:16:22 +0000 Subject: 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 8ca02452342..a1e4fc7876d 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 { -- cgit 1.4.1-3-g733a5 From 510fcd318b61d0e45165cdb0de880ee2f4f9cde2 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 17 Jan 2024 17:09:04 -0500 Subject: Use UnhashMap for a few more maps This avoids hashing data that's already hashed. --- compiler/rustc_data_structures/src/hashes.rs | 12 +++++++++++- compiler/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 291ee5bbe26..1564eeb4bae 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 afe26f80de8..52304c72a2f 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 d03965b539c..5be794f3e17 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 72a8b23721d..df7635e447d 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 { -- cgit 1.4.1-3-g733a5 From 3f7c7842e6dd0dfc713c52fe7ffd24cd6a54fa87 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 17 Jan 2024 15:59:04 +0000 Subject: Move `removed-syntax` tests to their own directory --- tests/ui/parser/removed-syntax-box.fixed | 14 ------ tests/ui/parser/removed-syntax-box.rs | 14 ------ tests/ui/parser/removed-syntax-box.stderr | 57 ---------------------- tests/ui/parser/removed-syntax-closure-lifetime.rs | 2 - .../parser/removed-syntax-closure-lifetime.stderr | 13 ----- tests/ui/parser/removed-syntax-enum-newtype.rs | 1 - tests/ui/parser/removed-syntax-enum-newtype.stderr | 10 ---- tests/ui/parser/removed-syntax-field-let-2.rs | 12 ----- tests/ui/parser/removed-syntax-field-let-2.stderr | 33 ------------- tests/ui/parser/removed-syntax-field-let.rs | 6 --- tests/ui/parser/removed-syntax-field-let.stderr | 14 ------ tests/ui/parser/removed-syntax-field-semicolon.rs | 6 --- .../parser/removed-syntax-field-semicolon.stderr | 10 ---- tests/ui/parser/removed-syntax-fixed-vec.rs | 1 - tests/ui/parser/removed-syntax-fixed-vec.stderr | 8 --- tests/ui/parser/removed-syntax-fn-sigil.rs | 4 -- tests/ui/parser/removed-syntax-fn-sigil.stderr | 14 ------ tests/ui/parser/removed-syntax-mode.rs | 4 -- tests/ui/parser/removed-syntax-mode.stderr | 8 --- tests/ui/parser/removed-syntax-mut-vec-expr.rs | 3 -- tests/ui/parser/removed-syntax-mut-vec-expr.stderr | 8 --- tests/ui/parser/removed-syntax-mut-vec-ty.rs | 1 - tests/ui/parser/removed-syntax-mut-vec-ty.stderr | 8 --- tests/ui/parser/removed-syntax-ptr-lifetime.rs | 1 - tests/ui/parser/removed-syntax-ptr-lifetime.stderr | 8 --- tests/ui/parser/removed-syntax-record.rs | 1 - tests/ui/parser/removed-syntax-record.stderr | 8 --- tests/ui/parser/removed-syntax-static-fn.rs | 10 ---- tests/ui/parser/removed-syntax-static-fn.stderr | 25 ---------- tests/ui/parser/removed-syntax-uniq-mut-expr.rs | 3 -- .../ui/parser/removed-syntax-uniq-mut-expr.stderr | 8 --- tests/ui/parser/removed-syntax-uniq-mut-ty.rs | 2 - tests/ui/parser/removed-syntax-uniq-mut-ty.stderr | 8 --- tests/ui/parser/removed-syntax-with-1.rs | 10 ---- tests/ui/parser/removed-syntax-with-1.stderr | 11 ----- tests/ui/parser/removed-syntax-with-2.rs | 11 ----- tests/ui/parser/removed-syntax-with-2.stderr | 18 ------- .../parser/removed-syntax/removed-syntax-box.fixed | 14 ++++++ .../ui/parser/removed-syntax/removed-syntax-box.rs | 14 ++++++ .../removed-syntax/removed-syntax-box.stderr | 57 ++++++++++++++++++++++ .../removed-syntax-closure-lifetime.rs | 2 + .../removed-syntax-closure-lifetime.stderr | 13 +++++ .../removed-syntax/removed-syntax-enum-newtype.rs | 1 + .../removed-syntax-enum-newtype.stderr | 10 ++++ .../removed-syntax/removed-syntax-field-let-2.rs | 12 +++++ .../removed-syntax-field-let-2.stderr | 33 +++++++++++++ .../removed-syntax/removed-syntax-field-let.rs | 6 +++ .../removed-syntax/removed-syntax-field-let.stderr | 14 ++++++ .../removed-syntax-field-semicolon.rs | 6 +++ .../removed-syntax-field-semicolon.stderr | 10 ++++ .../removed-syntax/removed-syntax-fixed-vec.rs | 1 + .../removed-syntax/removed-syntax-fixed-vec.stderr | 8 +++ .../removed-syntax/removed-syntax-fn-sigil.rs | 4 ++ .../removed-syntax/removed-syntax-fn-sigil.stderr | 14 ++++++ .../parser/removed-syntax/removed-syntax-mode.rs | 4 ++ .../removed-syntax/removed-syntax-mode.stderr | 8 +++ .../removed-syntax/removed-syntax-mut-vec-expr.rs | 3 ++ .../removed-syntax-mut-vec-expr.stderr | 8 +++ .../removed-syntax/removed-syntax-mut-vec-ty.rs | 1 + .../removed-syntax-mut-vec-ty.stderr | 8 +++ .../removed-syntax/removed-syntax-ptr-lifetime.rs | 1 + .../removed-syntax-ptr-lifetime.stderr | 8 +++ .../parser/removed-syntax/removed-syntax-record.rs | 1 + .../removed-syntax/removed-syntax-record.stderr | 8 +++ .../removed-syntax/removed-syntax-static-fn.rs | 10 ++++ .../removed-syntax/removed-syntax-static-fn.stderr | 25 ++++++++++ .../removed-syntax/removed-syntax-uniq-mut-expr.rs | 3 ++ .../removed-syntax-uniq-mut-expr.stderr | 8 +++ .../removed-syntax/removed-syntax-uniq-mut-ty.rs | 2 + .../removed-syntax-uniq-mut-ty.stderr | 8 +++ .../parser/removed-syntax/removed-syntax-with-1.rs | 10 ++++ .../removed-syntax/removed-syntax-with-1.stderr | 11 +++++ .../parser/removed-syntax/removed-syntax-with-2.rs | 11 +++++ .../removed-syntax/removed-syntax-with-2.stderr | 18 +++++++ 74 files changed, 375 insertions(+), 375 deletions(-) delete mode 100644 tests/ui/parser/removed-syntax-box.fixed delete mode 100644 tests/ui/parser/removed-syntax-box.rs delete mode 100644 tests/ui/parser/removed-syntax-box.stderr delete mode 100644 tests/ui/parser/removed-syntax-closure-lifetime.rs delete mode 100644 tests/ui/parser/removed-syntax-closure-lifetime.stderr delete mode 100644 tests/ui/parser/removed-syntax-enum-newtype.rs delete mode 100644 tests/ui/parser/removed-syntax-enum-newtype.stderr delete mode 100644 tests/ui/parser/removed-syntax-field-let-2.rs delete mode 100644 tests/ui/parser/removed-syntax-field-let-2.stderr delete mode 100644 tests/ui/parser/removed-syntax-field-let.rs delete mode 100644 tests/ui/parser/removed-syntax-field-let.stderr delete mode 100644 tests/ui/parser/removed-syntax-field-semicolon.rs delete mode 100644 tests/ui/parser/removed-syntax-field-semicolon.stderr delete mode 100644 tests/ui/parser/removed-syntax-fixed-vec.rs delete mode 100644 tests/ui/parser/removed-syntax-fixed-vec.stderr delete mode 100644 tests/ui/parser/removed-syntax-fn-sigil.rs delete mode 100644 tests/ui/parser/removed-syntax-fn-sigil.stderr delete mode 100644 tests/ui/parser/removed-syntax-mode.rs delete mode 100644 tests/ui/parser/removed-syntax-mode.stderr delete mode 100644 tests/ui/parser/removed-syntax-mut-vec-expr.rs delete mode 100644 tests/ui/parser/removed-syntax-mut-vec-expr.stderr delete mode 100644 tests/ui/parser/removed-syntax-mut-vec-ty.rs delete mode 100644 tests/ui/parser/removed-syntax-mut-vec-ty.stderr delete mode 100644 tests/ui/parser/removed-syntax-ptr-lifetime.rs delete mode 100644 tests/ui/parser/removed-syntax-ptr-lifetime.stderr delete mode 100644 tests/ui/parser/removed-syntax-record.rs delete mode 100644 tests/ui/parser/removed-syntax-record.stderr delete mode 100644 tests/ui/parser/removed-syntax-static-fn.rs delete mode 100644 tests/ui/parser/removed-syntax-static-fn.stderr delete mode 100644 tests/ui/parser/removed-syntax-uniq-mut-expr.rs delete mode 100644 tests/ui/parser/removed-syntax-uniq-mut-expr.stderr delete mode 100644 tests/ui/parser/removed-syntax-uniq-mut-ty.rs delete mode 100644 tests/ui/parser/removed-syntax-uniq-mut-ty.stderr delete mode 100644 tests/ui/parser/removed-syntax-with-1.rs delete mode 100644 tests/ui/parser/removed-syntax-with-1.stderr delete mode 100644 tests/ui/parser/removed-syntax-with-2.rs delete mode 100644 tests/ui/parser/removed-syntax-with-2.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-box.fixed create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-box.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-box.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-field-let.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-mode.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-mode.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-record.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-record.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-with-1.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-with-2.rs create mode 100644 tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr diff --git a/tests/ui/parser/removed-syntax-box.fixed b/tests/ui/parser/removed-syntax-box.fixed deleted file mode 100644 index 09d1304b775..00000000000 --- a/tests/ui/parser/removed-syntax-box.fixed +++ /dev/null @@ -1,14 +0,0 @@ -// run-rustfix - -fn main() { - #[allow(dead_code)] - struct T { - a: u8, - b: u8, - } - let _ = Box::new(()); //~ ERROR `box_syntax` has been removed - let _ = Box::new(1); //~ ERROR `box_syntax` has been removed - let _ = Box::new(T { a: 12, b: 18 }); //~ ERROR `box_syntax` has been removed - let _ = Box::new([5; 30]); //~ ERROR `box_syntax` has been removed - let _: Box<()> = Box::new(()); //~ ERROR `box_syntax` has been removed -} diff --git a/tests/ui/parser/removed-syntax-box.rs b/tests/ui/parser/removed-syntax-box.rs deleted file mode 100644 index 1f5061b02c7..00000000000 --- a/tests/ui/parser/removed-syntax-box.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-rustfix - -fn main() { - #[allow(dead_code)] - struct T { - a: u8, - b: u8, - } - let _ = box (); //~ ERROR `box_syntax` has been removed - let _ = box 1; //~ ERROR `box_syntax` has been removed - let _ = box T { a: 12, b: 18 }; //~ ERROR `box_syntax` has been removed - let _ = box [5; 30]; //~ ERROR `box_syntax` has been removed - let _: Box<()> = box (); //~ ERROR `box_syntax` has been removed -} diff --git a/tests/ui/parser/removed-syntax-box.stderr b/tests/ui/parser/removed-syntax-box.stderr deleted file mode 100644 index 46b891587d5..00000000000 --- a/tests/ui/parser/removed-syntax-box.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error: `box_syntax` has been removed - --> $DIR/removed-syntax-box.rs:9:13 - | -LL | let _ = box (); - | ^^^^^^ - | -help: use `Box::new()` instead - | -LL | let _ = Box::new(()); - | ~~~~~~~~~~~~ - -error: `box_syntax` has been removed - --> $DIR/removed-syntax-box.rs:10:13 - | -LL | let _ = box 1; - | ^^^^^ - | -help: use `Box::new()` instead - | -LL | let _ = Box::new(1); - | ~~~~~~~~~~~ - -error: `box_syntax` has been removed - --> $DIR/removed-syntax-box.rs:11:13 - | -LL | let _ = box T { a: 12, b: 18 }; - | ^^^^^^^^^^^^^^^^^^^^^^ - | -help: use `Box::new()` instead - | -LL | let _ = Box::new(T { a: 12, b: 18 }); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -error: `box_syntax` has been removed - --> $DIR/removed-syntax-box.rs:12:13 - | -LL | let _ = box [5; 30]; - | ^^^^^^^^^^^ - | -help: use `Box::new()` instead - | -LL | let _ = Box::new([5; 30]); - | ~~~~~~~~~~~~~~~~~ - -error: `box_syntax` has been removed - --> $DIR/removed-syntax-box.rs:13:22 - | -LL | let _: Box<()> = box (); - | ^^^^^^ - | -help: use `Box::new()` instead - | -LL | let _: Box<()> = Box::new(()); - | ~~~~~~~~~~~~ - -error: aborting due to 5 previous errors - diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.rs b/tests/ui/parser/removed-syntax-closure-lifetime.rs deleted file mode 100644 index e807a179473..00000000000 --- a/tests/ui/parser/removed-syntax-closure-lifetime.rs +++ /dev/null @@ -1,2 +0,0 @@ -type closure = Box; -//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax-closure-lifetime.stderr deleted file mode 100644 index 4c991d67ea7..00000000000 --- a/tests/ui/parser/removed-syntax-closure-lifetime.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` - --> $DIR/removed-syntax-closure-lifetime.rs:1:22 - | -LL | type closure = Box; - | ^ expected one of 9 possible tokens - | -help: you might have meant to end the type parameters here - | -LL | type closure = Box/fn()>; - | + - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-enum-newtype.rs b/tests/ui/parser/removed-syntax-enum-newtype.rs deleted file mode 100644 index 518f90b2b83..00000000000 --- a/tests/ui/parser/removed-syntax-enum-newtype.rs +++ /dev/null @@ -1 +0,0 @@ -enum e = isize; //~ ERROR expected one of `<`, `where`, or `{`, found `=` diff --git a/tests/ui/parser/removed-syntax-enum-newtype.stderr b/tests/ui/parser/removed-syntax-enum-newtype.stderr deleted file mode 100644 index 5b917e93853..00000000000 --- a/tests/ui/parser/removed-syntax-enum-newtype.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: expected one of `<`, `where`, or `{`, found `=` - --> $DIR/removed-syntax-enum-newtype.rs:1:8 - | -LL | enum e = isize; - | - ^ expected one of `<`, `where`, or `{` - | | - | while parsing this enum - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-field-let-2.rs b/tests/ui/parser/removed-syntax-field-let-2.rs deleted file mode 100644 index 7ff91b476ae..00000000000 --- a/tests/ui/parser/removed-syntax-field-let-2.rs +++ /dev/null @@ -1,12 +0,0 @@ -struct Foo { - let x: i32, - //~^ ERROR expected identifier, found keyword - let y: i32, - //~^ ERROR expected identifier, found keyword -} - -fn main() { - let _ = Foo { - //~^ ERROR missing fields `x` and `y` in initializer of `Foo` - }; -} diff --git a/tests/ui/parser/removed-syntax-field-let-2.stderr b/tests/ui/parser/removed-syntax-field-let-2.stderr deleted file mode 100644 index fda0919b9b6..00000000000 --- a/tests/ui/parser/removed-syntax-field-let-2.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: expected identifier, found keyword `let` - --> $DIR/removed-syntax-field-let-2.rs:2:5 - | -LL | let x: i32, - | ^^^- - | | - | expected identifier, found keyword - | help: remove this `let` keyword - | - = note: the `let` keyword is not allowed in `struct` fields - = note: see for more information - -error: expected identifier, found keyword `let` - --> $DIR/removed-syntax-field-let-2.rs:4:5 - | -LL | let y: i32, - | ^^^- - | | - | expected identifier, found keyword - | help: remove this `let` keyword - | - = note: the `let` keyword is not allowed in `struct` fields - = note: see for more information - -error[E0063]: missing fields `x` and `y` in initializer of `Foo` - --> $DIR/removed-syntax-field-let-2.rs:9:13 - | -LL | let _ = Foo { - | ^^^ missing `x` and `y` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/removed-syntax-field-let.rs b/tests/ui/parser/removed-syntax-field-let.rs deleted file mode 100644 index 6d64de296f1..00000000000 --- a/tests/ui/parser/removed-syntax-field-let.rs +++ /dev/null @@ -1,6 +0,0 @@ -struct S { - let foo: (), - //~^ ERROR expected identifier, found keyword `let` -} - -fn main() {} diff --git a/tests/ui/parser/removed-syntax-field-let.stderr b/tests/ui/parser/removed-syntax-field-let.stderr deleted file mode 100644 index 339d056e636..00000000000 --- a/tests/ui/parser/removed-syntax-field-let.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: expected identifier, found keyword `let` - --> $DIR/removed-syntax-field-let.rs:2:5 - | -LL | let foo: (), - | ^^^- - | | - | expected identifier, found keyword - | help: remove this `let` keyword - | - = note: the `let` keyword is not allowed in `struct` fields - = note: see for more information - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-field-semicolon.rs b/tests/ui/parser/removed-syntax-field-semicolon.rs deleted file mode 100644 index 808f2a5cc38..00000000000 --- a/tests/ui/parser/removed-syntax-field-semicolon.rs +++ /dev/null @@ -1,6 +0,0 @@ -struct S { - bar: (); - //~^ ERROR struct fields are separated by `,` -} - -fn main() {} diff --git a/tests/ui/parser/removed-syntax-field-semicolon.stderr b/tests/ui/parser/removed-syntax-field-semicolon.stderr deleted file mode 100644 index 522912a9e1c..00000000000 --- a/tests/ui/parser/removed-syntax-field-semicolon.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: struct fields are separated by `,` - --> $DIR/removed-syntax-field-semicolon.rs:2:12 - | -LL | struct S { - | - while parsing this struct -LL | bar: (); - | ^ help: replace `;` with `,` - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax-fixed-vec.rs deleted file mode 100644 index 560efecb91c..00000000000 --- a/tests/ui/parser/removed-syntax-fixed-vec.rs +++ /dev/null @@ -1 +0,0 @@ -type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` diff --git a/tests/ui/parser/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax-fixed-vec.stderr deleted file mode 100644 index 5bc9c2ccf00..00000000000 --- a/tests/ui/parser/removed-syntax-fixed-vec.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` - --> $DIR/removed-syntax-fixed-vec.rs:1:17 - | -LL | type v = [isize * 3]; - | ^ expected one of 7 possible tokens - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-fn-sigil.rs b/tests/ui/parser/removed-syntax-fn-sigil.rs deleted file mode 100644 index d55a032d1f2..00000000000 --- a/tests/ui/parser/removed-syntax-fn-sigil.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let x: fn~() = || (); //~ ERROR missing parameters for function definition - //~| ERROR expected one of `->`, `;`, or `=`, found `~` -} diff --git a/tests/ui/parser/removed-syntax-fn-sigil.stderr b/tests/ui/parser/removed-syntax-fn-sigil.stderr deleted file mode 100644 index 0d377416700..00000000000 --- a/tests/ui/parser/removed-syntax-fn-sigil.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: missing parameters for function definition - --> $DIR/removed-syntax-fn-sigil.rs:2:14 - | -LL | let x: fn~() = || (); - | ^ help: add a parameter list - -error: expected one of `->`, `;`, or `=`, found `~` - --> $DIR/removed-syntax-fn-sigil.rs:2:14 - | -LL | let x: fn~() = || (); - | ^ expected one of `->`, `;`, or `=` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/removed-syntax-mode.rs b/tests/ui/parser/removed-syntax-mode.rs deleted file mode 100644 index a438db3b0c1..00000000000 --- a/tests/ui/parser/removed-syntax-mode.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn f(+x: isize) {} -//~^ ERROR expected parameter name, found `+` - -fn main() {} diff --git a/tests/ui/parser/removed-syntax-mode.stderr b/tests/ui/parser/removed-syntax-mode.stderr deleted file mode 100644 index fd964c4b7f0..00000000000 --- a/tests/ui/parser/removed-syntax-mode.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected parameter name, found `+` - --> $DIR/removed-syntax-mode.rs:1:6 - | -LL | fn f(+x: isize) {} - | ^ expected parameter name - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.rs b/tests/ui/parser/removed-syntax-mut-vec-expr.rs deleted file mode 100644 index 2ee95db5a25..00000000000 --- a/tests/ui/parser/removed-syntax-mut-vec-expr.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - let v = [mut 1, 2, 3, 4]; //~ ERROR expected expression, found keyword `mut` -} diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr b/tests/ui/parser/removed-syntax-mut-vec-expr.stderr deleted file mode 100644 index a1aa1ae49e3..00000000000 --- a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected expression, found keyword `mut` - --> $DIR/removed-syntax-mut-vec-expr.rs:2:14 - | -LL | let v = [mut 1, 2, 3, 4]; - | ^^^ expected expression - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.rs b/tests/ui/parser/removed-syntax-mut-vec-ty.rs deleted file mode 100644 index 923a7ea37a4..00000000000 --- a/tests/ui/parser/removed-syntax-mut-vec-ty.rs +++ /dev/null @@ -1 +0,0 @@ -type v = [mut isize]; //~ ERROR expected type, found keyword `mut` diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr b/tests/ui/parser/removed-syntax-mut-vec-ty.stderr deleted file mode 100644 index beaae7cddaa..00000000000 --- a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected type, found keyword `mut` - --> $DIR/removed-syntax-mut-vec-ty.rs:1:11 - | -LL | type v = [mut isize]; - | ^^^ expected type - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.rs b/tests/ui/parser/removed-syntax-ptr-lifetime.rs deleted file mode 100644 index cc69af44a13..00000000000 --- a/tests/ui/parser/removed-syntax-ptr-lifetime.rs +++ /dev/null @@ -1 +0,0 @@ -type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr deleted file mode 100644 index 5c74efffabf..00000000000 --- a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` - --> $DIR/removed-syntax-ptr-lifetime.rs:1:22 - | -LL | type bptr = &lifetime/isize; - | ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where` - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-record.rs b/tests/ui/parser/removed-syntax-record.rs deleted file mode 100644 index d1d91c8f7dc..00000000000 --- a/tests/ui/parser/removed-syntax-record.rs +++ /dev/null @@ -1 +0,0 @@ -type t = { f: () }; //~ ERROR expected type, found `{` diff --git a/tests/ui/parser/removed-syntax-record.stderr b/tests/ui/parser/removed-syntax-record.stderr deleted file mode 100644 index dbf09f1c75b..00000000000 --- a/tests/ui/parser/removed-syntax-record.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected type, found `{` - --> $DIR/removed-syntax-record.rs:1:10 - | -LL | type t = { f: () }; - | ^ expected type - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-static-fn.rs b/tests/ui/parser/removed-syntax-static-fn.rs deleted file mode 100644 index cd643b874db..00000000000 --- a/tests/ui/parser/removed-syntax-static-fn.rs +++ /dev/null @@ -1,10 +0,0 @@ -struct S; - -impl S { - static fn f() {} - //~^ ERROR expected identifier, found keyword `fn` - //~| ERROR expected one of `:`, `;`, or `=` - //~| ERROR missing type for `static` item -} - -fn main() {} diff --git a/tests/ui/parser/removed-syntax-static-fn.stderr b/tests/ui/parser/removed-syntax-static-fn.stderr deleted file mode 100644 index 52e0658949d..00000000000 --- a/tests/ui/parser/removed-syntax-static-fn.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: expected identifier, found keyword `fn` - --> $DIR/removed-syntax-static-fn.rs:4:12 - | -LL | static fn f() {} - | ^^ expected identifier, found keyword - -error: expected one of `:`, `;`, or `=`, found `f` - --> $DIR/removed-syntax-static-fn.rs:4:15 - | -LL | impl S { - | - while parsing this item list starting here -LL | static fn f() {} - | ^ expected one of `:`, `;`, or `=` -... -LL | } - | - the item list ends here - -error: missing type for `static` item - --> $DIR/removed-syntax-static-fn.rs:4:14 - | -LL | static fn f() {} - | ^ help: provide a type for the item: `: ` - -error: aborting due to 3 previous errors - diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.rs b/tests/ui/parser/removed-syntax-uniq-mut-expr.rs deleted file mode 100644 index 08ef4b43269..00000000000 --- a/tests/ui/parser/removed-syntax-uniq-mut-expr.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - let a_box = box mut 42; //~ ERROR expected expression, found keyword `mut` -} diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr b/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr deleted file mode 100644 index 7aaedad19d8..00000000000 --- a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected expression, found keyword `mut` - --> $DIR/removed-syntax-uniq-mut-expr.rs:2:21 - | -LL | let a_box = box mut 42; - | ^^^ expected expression - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.rs b/tests/ui/parser/removed-syntax-uniq-mut-ty.rs deleted file mode 100644 index a8dee5bbda4..00000000000 --- a/tests/ui/parser/removed-syntax-uniq-mut-ty.rs +++ /dev/null @@ -1,2 +0,0 @@ -type mut_box = Box; -//~^ ERROR expected one of `>`, a const expression, lifetime, or type, found keyword `mut` diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr b/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr deleted file mode 100644 index 5ae1f4f587e..00000000000 --- a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `>`, a const expression, lifetime, or type, found keyword `mut` - --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20 - | -LL | type mut_box = Box; - | ^^^ expected one of `>`, a const expression, lifetime, or type - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-with-1.rs b/tests/ui/parser/removed-syntax-with-1.rs deleted file mode 100644 index 2c1e152dcee..00000000000 --- a/tests/ui/parser/removed-syntax-with-1.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - struct S { - foo: (), - bar: (), - } - - let a = S { foo: (), bar: () }; - let b = S { foo: () with a, bar: () }; - //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with` -} diff --git a/tests/ui/parser/removed-syntax-with-1.stderr b/tests/ui/parser/removed-syntax-with-1.stderr deleted file mode 100644 index 78042678a87..00000000000 --- a/tests/ui/parser/removed-syntax-with-1.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with` - --> $DIR/removed-syntax-with-1.rs:8:25 - | -LL | let b = S { foo: () with a, bar: () }; - | - -^^^^ expected one of `,`, `.`, `?`, `}`, or an operator - | | | - | | help: try adding a comma: `,` - | while parsing this struct - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/removed-syntax-with-2.rs b/tests/ui/parser/removed-syntax-with-2.rs deleted file mode 100644 index 451057c66a1..00000000000 --- a/tests/ui/parser/removed-syntax-with-2.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - struct S { - foo: (), - bar: (), - } - - let a = S { foo: (), bar: () }; - let b = S { foo: (), with a }; - //~^ ERROR expected one of `,`, `:`, or `}`, found `a` - //~| ERROR missing field `bar` in initializer of `S` -} diff --git a/tests/ui/parser/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax-with-2.stderr deleted file mode 100644 index e75c5bcd643..00000000000 --- a/tests/ui/parser/removed-syntax-with-2.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: expected one of `,`, `:`, or `}`, found `a` - --> $DIR/removed-syntax-with-2.rs:8:31 - | -LL | let b = S { foo: (), with a }; - | - ---- ^ expected one of `,`, `:`, or `}` - | | | - | | while parsing this struct field - | while parsing this struct - -error[E0063]: missing field `bar` in initializer of `S` - --> $DIR/removed-syntax-with-2.rs:8:13 - | -LL | let b = S { foo: (), with a }; - | ^ missing `bar` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/removed-syntax/removed-syntax-box.fixed b/tests/ui/parser/removed-syntax/removed-syntax-box.fixed new file mode 100644 index 00000000000..09d1304b775 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-box.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +fn main() { + #[allow(dead_code)] + struct T { + a: u8, + b: u8, + } + let _ = Box::new(()); //~ ERROR `box_syntax` has been removed + let _ = Box::new(1); //~ ERROR `box_syntax` has been removed + let _ = Box::new(T { a: 12, b: 18 }); //~ ERROR `box_syntax` has been removed + let _ = Box::new([5; 30]); //~ ERROR `box_syntax` has been removed + let _: Box<()> = Box::new(()); //~ ERROR `box_syntax` has been removed +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-box.rs b/tests/ui/parser/removed-syntax/removed-syntax-box.rs new file mode 100644 index 00000000000..1f5061b02c7 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-box.rs @@ -0,0 +1,14 @@ +// run-rustfix + +fn main() { + #[allow(dead_code)] + struct T { + a: u8, + b: u8, + } + let _ = box (); //~ ERROR `box_syntax` has been removed + let _ = box 1; //~ ERROR `box_syntax` has been removed + let _ = box T { a: 12, b: 18 }; //~ ERROR `box_syntax` has been removed + let _ = box [5; 30]; //~ ERROR `box_syntax` has been removed + let _: Box<()> = box (); //~ ERROR `box_syntax` has been removed +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-box.stderr b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr new file mode 100644 index 00000000000..46b891587d5 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr @@ -0,0 +1,57 @@ +error: `box_syntax` has been removed + --> $DIR/removed-syntax-box.rs:9:13 + | +LL | let _ = box (); + | ^^^^^^ + | +help: use `Box::new()` instead + | +LL | let _ = Box::new(()); + | ~~~~~~~~~~~~ + +error: `box_syntax` has been removed + --> $DIR/removed-syntax-box.rs:10:13 + | +LL | let _ = box 1; + | ^^^^^ + | +help: use `Box::new()` instead + | +LL | let _ = Box::new(1); + | ~~~~~~~~~~~ + +error: `box_syntax` has been removed + --> $DIR/removed-syntax-box.rs:11:13 + | +LL | let _ = box T { a: 12, b: 18 }; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `Box::new()` instead + | +LL | let _ = Box::new(T { a: 12, b: 18 }); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: `box_syntax` has been removed + --> $DIR/removed-syntax-box.rs:12:13 + | +LL | let _ = box [5; 30]; + | ^^^^^^^^^^^ + | +help: use `Box::new()` instead + | +LL | let _ = Box::new([5; 30]); + | ~~~~~~~~~~~~~~~~~ + +error: `box_syntax` has been removed + --> $DIR/removed-syntax-box.rs:13:22 + | +LL | let _: Box<()> = box (); + | ^^^^^^ + | +help: use `Box::new()` instead + | +LL | let _: Box<()> = Box::new(()); + | ~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs new file mode 100644 index 00000000000..e807a179473 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs @@ -0,0 +1,2 @@ +type closure = Box; +//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr new file mode 100644 index 00000000000..4c991d67ea7 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` + --> $DIR/removed-syntax-closure-lifetime.rs:1:22 + | +LL | type closure = Box; + | ^ expected one of 9 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | type closure = Box/fn()>; + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs new file mode 100644 index 00000000000..518f90b2b83 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs @@ -0,0 +1 @@ +enum e = isize; //~ ERROR expected one of `<`, `where`, or `{`, found `=` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr new file mode 100644 index 00000000000..5b917e93853 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr @@ -0,0 +1,10 @@ +error: expected one of `<`, `where`, or `{`, found `=` + --> $DIR/removed-syntax-enum-newtype.rs:1:8 + | +LL | enum e = isize; + | - ^ expected one of `<`, `where`, or `{` + | | + | while parsing this enum + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs new file mode 100644 index 00000000000..7ff91b476ae --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs @@ -0,0 +1,12 @@ +struct Foo { + let x: i32, + //~^ ERROR expected identifier, found keyword + let y: i32, + //~^ ERROR expected identifier, found keyword +} + +fn main() { + let _ = Foo { + //~^ ERROR missing fields `x` and `y` in initializer of `Foo` + }; +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr new file mode 100644 index 00000000000..fda0919b9b6 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr @@ -0,0 +1,33 @@ +error: expected identifier, found keyword `let` + --> $DIR/removed-syntax-field-let-2.rs:2:5 + | +LL | let x: i32, + | ^^^- + | | + | expected identifier, found keyword + | help: remove this `let` keyword + | + = note: the `let` keyword is not allowed in `struct` fields + = note: see for more information + +error: expected identifier, found keyword `let` + --> $DIR/removed-syntax-field-let-2.rs:4:5 + | +LL | let y: i32, + | ^^^- + | | + | expected identifier, found keyword + | help: remove this `let` keyword + | + = note: the `let` keyword is not allowed in `struct` fields + = note: see for more information + +error[E0063]: missing fields `x` and `y` in initializer of `Foo` + --> $DIR/removed-syntax-field-let-2.rs:9:13 + | +LL | let _ = Foo { + | ^^^ missing `x` and `y` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/removed-syntax/removed-syntax-field-let.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-let.rs new file mode 100644 index 00000000000..6d64de296f1 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-field-let.rs @@ -0,0 +1,6 @@ +struct S { + let foo: (), + //~^ ERROR expected identifier, found keyword `let` +} + +fn main() {} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr new file mode 100644 index 00000000000..339d056e636 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `let` + --> $DIR/removed-syntax-field-let.rs:2:5 + | +LL | let foo: (), + | ^^^- + | | + | expected identifier, found keyword + | help: remove this `let` keyword + | + = note: the `let` keyword is not allowed in `struct` fields + = note: see for more information + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs new file mode 100644 index 00000000000..808f2a5cc38 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs @@ -0,0 +1,6 @@ +struct S { + bar: (); + //~^ ERROR struct fields are separated by `,` +} + +fn main() {} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr new file mode 100644 index 00000000000..522912a9e1c --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr @@ -0,0 +1,10 @@ +error: struct fields are separated by `,` + --> $DIR/removed-syntax-field-semicolon.rs:2:12 + | +LL | struct S { + | - while parsing this struct +LL | bar: (); + | ^ help: replace `;` with `,` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs new file mode 100644 index 00000000000..560efecb91c --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs @@ -0,0 +1 @@ +type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr new file mode 100644 index 00000000000..5bc9c2ccf00 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` + --> $DIR/removed-syntax-fixed-vec.rs:1:17 + | +LL | type v = [isize * 3]; + | ^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs new file mode 100644 index 00000000000..d55a032d1f2 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs @@ -0,0 +1,4 @@ +fn main() { + let x: fn~() = || (); //~ ERROR missing parameters for function definition + //~| ERROR expected one of `->`, `;`, or `=`, found `~` +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr new file mode 100644 index 00000000000..0d377416700 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr @@ -0,0 +1,14 @@ +error: missing parameters for function definition + --> $DIR/removed-syntax-fn-sigil.rs:2:14 + | +LL | let x: fn~() = || (); + | ^ help: add a parameter list + +error: expected one of `->`, `;`, or `=`, found `~` + --> $DIR/removed-syntax-fn-sigil.rs:2:14 + | +LL | let x: fn~() = || (); + | ^ expected one of `->`, `;`, or `=` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-mode.rs b/tests/ui/parser/removed-syntax/removed-syntax-mode.rs new file mode 100644 index 00000000000..a438db3b0c1 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-mode.rs @@ -0,0 +1,4 @@ +fn f(+x: isize) {} +//~^ ERROR expected parameter name, found `+` + +fn main() {} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-mode.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mode.stderr new file mode 100644 index 00000000000..fd964c4b7f0 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-mode.stderr @@ -0,0 +1,8 @@ +error: expected parameter name, found `+` + --> $DIR/removed-syntax-mode.rs:1:6 + | +LL | fn f(+x: isize) {} + | ^ expected parameter name + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs new file mode 100644 index 00000000000..2ee95db5a25 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let v = [mut 1, 2, 3, 4]; //~ ERROR expected expression, found keyword `mut` +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr new file mode 100644 index 00000000000..a1aa1ae49e3 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `mut` + --> $DIR/removed-syntax-mut-vec-expr.rs:2:14 + | +LL | let v = [mut 1, 2, 3, 4]; + | ^^^ expected expression + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs new file mode 100644 index 00000000000..923a7ea37a4 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs @@ -0,0 +1 @@ +type v = [mut isize]; //~ ERROR expected type, found keyword `mut` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr new file mode 100644 index 00000000000..beaae7cddaa --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr @@ -0,0 +1,8 @@ +error: expected type, found keyword `mut` + --> $DIR/removed-syntax-mut-vec-ty.rs:1:11 + | +LL | type v = [mut isize]; + | ^^^ expected type + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs new file mode 100644 index 00000000000..cc69af44a13 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs @@ -0,0 +1 @@ +type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr new file mode 100644 index 00000000000..5c74efffabf --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` + --> $DIR/removed-syntax-ptr-lifetime.rs:1:22 + | +LL | type bptr = &lifetime/isize; + | ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-record.rs b/tests/ui/parser/removed-syntax/removed-syntax-record.rs new file mode 100644 index 00000000000..d1d91c8f7dc --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-record.rs @@ -0,0 +1 @@ +type t = { f: () }; //~ ERROR expected type, found `{` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-record.stderr b/tests/ui/parser/removed-syntax/removed-syntax-record.stderr new file mode 100644 index 00000000000..dbf09f1c75b --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-record.stderr @@ -0,0 +1,8 @@ +error: expected type, found `{` + --> $DIR/removed-syntax-record.rs:1:10 + | +LL | type t = { f: () }; + | ^ expected type + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs new file mode 100644 index 00000000000..cd643b874db --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs @@ -0,0 +1,10 @@ +struct S; + +impl S { + static fn f() {} + //~^ ERROR expected identifier, found keyword `fn` + //~| ERROR expected one of `:`, `;`, or `=` + //~| ERROR missing type for `static` item +} + +fn main() {} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr new file mode 100644 index 00000000000..52e0658949d --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr @@ -0,0 +1,25 @@ +error: expected identifier, found keyword `fn` + --> $DIR/removed-syntax-static-fn.rs:4:12 + | +LL | static fn f() {} + | ^^ expected identifier, found keyword + +error: expected one of `:`, `;`, or `=`, found `f` + --> $DIR/removed-syntax-static-fn.rs:4:15 + | +LL | impl S { + | - while parsing this item list starting here +LL | static fn f() {} + | ^ expected one of `:`, `;`, or `=` +... +LL | } + | - the item list ends here + +error: missing type for `static` item + --> $DIR/removed-syntax-static-fn.rs:4:14 + | +LL | static fn f() {} + | ^ help: provide a type for the item: `: ` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs new file mode 100644 index 00000000000..08ef4b43269 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let a_box = box mut 42; //~ ERROR expected expression, found keyword `mut` +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr new file mode 100644 index 00000000000..7aaedad19d8 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `mut` + --> $DIR/removed-syntax-uniq-mut-expr.rs:2:21 + | +LL | let a_box = box mut 42; + | ^^^ expected expression + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs new file mode 100644 index 00000000000..a8dee5bbda4 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs @@ -0,0 +1,2 @@ +type mut_box = Box; +//~^ ERROR expected one of `>`, a const expression, lifetime, or type, found keyword `mut` diff --git a/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr new file mode 100644 index 00000000000..5ae1f4f587e --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr @@ -0,0 +1,8 @@ +error: expected one of `>`, a const expression, lifetime, or type, found keyword `mut` + --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20 + | +LL | type mut_box = Box; + | ^^^ expected one of `>`, a const expression, lifetime, or type + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-with-1.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-1.rs new file mode 100644 index 00000000000..2c1e152dcee --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-with-1.rs @@ -0,0 +1,10 @@ +fn main() { + struct S { + foo: (), + bar: (), + } + + let a = S { foo: (), bar: () }; + let b = S { foo: () with a, bar: () }; + //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with` +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr new file mode 100644 index 00000000000..78042678a87 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr @@ -0,0 +1,11 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with` + --> $DIR/removed-syntax-with-1.rs:8:25 + | +LL | let b = S { foo: () with a, bar: () }; + | - -^^^^ expected one of `,`, `.`, `?`, `}`, or an operator + | | | + | | help: try adding a comma: `,` + | while parsing this struct + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs new file mode 100644 index 00000000000..451057c66a1 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs @@ -0,0 +1,11 @@ +fn main() { + struct S { + foo: (), + bar: (), + } + + let a = S { foo: (), bar: () }; + let b = S { foo: (), with a }; + //~^ ERROR expected one of `,`, `:`, or `}`, found `a` + //~| ERROR missing field `bar` in initializer of `S` +} diff --git a/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr new file mode 100644 index 00000000000..e75c5bcd643 --- /dev/null +++ b/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr @@ -0,0 +1,18 @@ +error: expected one of `,`, `:`, or `}`, found `a` + --> $DIR/removed-syntax-with-2.rs:8:31 + | +LL | let b = S { foo: (), with a }; + | - ---- ^ expected one of `,`, `:`, or `}` + | | | + | | while parsing this struct field + | while parsing this struct + +error[E0063]: missing field `bar` in initializer of `S` + --> $DIR/removed-syntax-with-2.rs:8:13 + | +LL | let b = S { foo: (), with a }; + | ^ missing `bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0063`. -- cgit 1.4.1-3-g733a5 From 99797bbd9fdb138dd59a782f156db8397d07943c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 16 Jan 2024 13:52:08 +1100 Subject: 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 b02c7e2e4c6..323d6e3c8aa 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 0f2c917e090..a6eeb79a71c 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 9b289141c2e..c3ef9167880 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 14b1525ca0e..5f5e0644278 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 2c9bd4ac97a..da6afa5800f 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 a7f0cabb4c2..00169b18045 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 8dd03acc2f4..ef9faab590b 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 3a9791a0dbd..bd3d4e46880 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 86d19af6f4f..2aa689466fc 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 ab04e746b91..c669b7245ea 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 7c201f482db..a643332bce1 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 854fa062967..a854c17f6d5 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 3a803e3c18f..5e4aae0260b 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 c6d9ad6cf27..6e3696386a7 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 dd8b42c18ce..825e266f111 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 7e84e398f84..1f61b805f62 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 21abb5dce04..7ece467217a 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 050aac26319..04e9cd0e808 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() {} -- cgit 1.4.1-3-g733a5 From c1c7707238bd58242588d75a350def4ceb59c581 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 02:11:55 +0000 Subject: 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 65036bcdc36..098b8f2d6d0 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 7b927c89ba0..a42e8c41c2e 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 7cbda25e417..4ea924ddcb8 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 -- cgit 1.4.1-3-g733a5 From ec263df5e440598159f19a42c104c3b5f13888a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 03:01:05 +0000 Subject: 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 d515e86a182..e3ecd24b6a5 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 34b34a1bad6..8f57b2eb5aa 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 8ca02452342..f858706805d 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 1a8bbf0a157..1bae5b32240 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 4ea924ddcb8..887455913d8 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 -- cgit 1.4.1-3-g733a5 From e68f3039d4f2b12dcfc348ebb50fd7855e6d7fd1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 17 Jan 2024 13:53:25 -0500 Subject: 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. --- compiler/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 7ff970661d6..3afd14eb574 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); } } } -- cgit 1.4.1-3-g733a5 From d96003dd2a780ecb19252229b1927b1dc09f699b Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 10 Dec 2023 20:13:21 -0500 Subject: Correctly handle normalization in implied bounds Special-case Bevy dependents to not error --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 7 +- .../src/check/compare_impl_item/refine.rs | 2 +- compiler/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 +- compiler/rustc_trait_selection/src/traits/misc.rs | 4 +- .../src/traits/outlives_bounds.rs | 196 +++++++++++---------- .../query/type_op/implied_outlives_bounds.rs | 86 ++++++++- .../rustc_traits/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 +- tests/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 +- tests/ui/implied-bounds/sod_service_chain.stderr | 31 ++++ 20 files changed, 373 insertions(+), 168 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 77914802bf7..d7b1447d980 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 774feb94f7d..e2cdeb5b204 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 f7fc0c81b95..3509a39fec9 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 4772bae58c4..1af6282070e 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 93dd2342a4d..a922209deb8 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 b9200f1abf1..7122f131731 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 1dc77220881..f5b76f08f0b 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 5f02dd22961..61d96cad57d 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 073174127d6..52de8c4ceae 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 5b349d576b6..ec17024345a 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(), - param_env, - &canonical_var_values, - canonical_result, - &mut constraints, - ) - else { - return vec![]; - }; - assert_eq!(&obligations, &[]); + 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()); - // 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); - if !constraints.is_empty() { - let span = self.tcx.def_span(body_id); + debug!(?constraints); + if !constraints.member_constraints.is_empty() { + span_bug!(span, "{:#?}", constraints.member_constraints); + } - 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, + )); + } - // 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() { + infcx.dcx().span_delayed_bug( + span, + "implied_outlives_bounds failed to solve obligations from instantiation", + ); + } + }; - 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 +} - 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 ba6ed298774..bdc53f895fe 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 959838ab348..24e91c263e3 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 b373d39f4d9..00000000000 --- 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 f8e64632676..d5de0e9ef21 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 d13fddd9b8d..6e126575aa9 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 00000000000..4151d206ae2 --- /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 98951af8ac2..cd5500cb458 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 e020230d86a..041892c7542 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 f45ced71f75..7443a29f30c 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 00000000000..1c0ef573e7d --- /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`. -- cgit 1.4.1-3-g733a5 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: Add -Zno-implied-bounds-compat option and use it --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/compare_impl_item.rs | 7 +++---- .../src/check/compare_impl_item/refine.rs | 2 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 17 ++++++++++++----- .../src/impl_wf_check/min_specialization.rs | 3 +-- compiler/rustc_session/src/options.rs | 2 ++ compiler/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 d7b1447d980..03e2b0e0022 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 e2cdeb5b204..5b264f6f034 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 3509a39fec9..0d8de0cabd1 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 1af6282070e..58046173fb1 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 a922209deb8..6964446f9c7 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 f4bf79f93f2..5bc88ae6ed1 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 52de8c4ceae..0cd376fcbbd 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 ec17024345a..52631d4353b 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, + ) + }) } } -- cgit 1.4.1-3-g733a5 From 63446d00ee2005125b1e4a7c3f00547101065709 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 26 Sep 2023 22:34:09 +0200 Subject: 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 266e54604a6..a9ccfbed411 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 48edfba8da0..adcb6ceaebf 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 3f6c70a18d3..cba6ce0d235 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, -- cgit 1.4.1-3-g733a5 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: Don't use compat versions of implied bounds in ImpliedOutlivesBounds query --- .../src/traits/query/type_op/implied_outlives_bounds.rs | 4 ++-- tests/ui/associated-inherent-types/issue-111404-1.rs | 1 + tests/ui/associated-inherent-types/issue-111404-1.stderr | 10 +++++++++- tests/ui/implied-bounds/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 bdc53f895fe..2fdb63d7dee 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 dd62e59f07d..74f9434b881 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 cf4d4a5f19b..1613161a873 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 041892c7542..00000000000 --- 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 87903783a67..3f569aa1ace 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 80cad6dfc46..d36688978e9 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 00000000000..7bb4786db3a --- /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 + -- cgit 1.4.1-3-g733a5 From 0373ce6876864a2f31b0ab885c7ba80e1f69eb15 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 18 Jan 2024 14:36:17 +1100 Subject: 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 34d48559c37..42c751bb6be 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); } -- cgit 1.4.1-3-g733a5 From 6a573cbc60af8319e11cf0f0a578f8a12caa932d Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 17 Jan 2024 19:35:19 -0800 Subject: 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 873bd94e88f..b99640d2f2d 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 2a2626654a0..fffc454804d 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 b0811364c09..b4faaeb4fc0 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(()) } -- cgit 1.4.1-3-g733a5 From 9650c30fbb9e3741fbc4d01bc64496f7d725212e Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 18 Jan 2024 06:50:06 +0000 Subject: 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. --- .../crates/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 6cf2b5643e5..e6903fb8d4a 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])); } } -- cgit 1.4.1-3-g733a5 From 2cc81baaf4b71cb2903f93cfe2222d37feb9a34d Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 18 Jan 2024 12:48:38 +0000 Subject: 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 1352fb3771b..6bc38811f1b 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 00000000000..4926293bb88 --- /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 d06796e33d5..9398a87df62 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 840b250f87d..b54b3560447 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 | ^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From c13c746b477cfa3887bd88236c452bb57048f6c6 Mon Sep 17 00:00:00 2001 From: James Dietz Date: Thu, 18 Jan 2024 09:39:38 -0500 Subject: 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 239929a2c0e..f74715468a0 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 { .. } -- cgit 1.4.1-3-g733a5 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: 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 a07d6587bf9..59ebe685c11 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); } -- cgit 1.4.1-3-g733a5 From e532b0dd7e632fc017f9f66a1fb24c7183a40dff Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 1 Feb 2023 14:23:51 +0000 Subject: Don't forget that the lifetime on hir types is `'tcx` --- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir_analysis/src/astconv/bounds.rs | 8 +-- .../rustc_hir_analysis/src/astconv/generics.rs | 2 +- compiler/rustc_hir_analysis/src/astconv/mod.rs | 61 ++++++++++++---------- .../src/astconv/object_safety.rs | 2 +- compiler/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 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 12 ++--- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 6 +-- compiler/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/clippy_lints/src/implicit_hasher.rs | 2 +- src/tools/clippy/clippy_lints/src/types/mod.rs | 18 +++---- .../clippy_lints/src/types/redundant_allocation.rs | 2 +- src/tools/clippy/clippy_lints/src/types/vec_box.rs | 6 +-- .../clippy_lints/src/unconditional_recursion.rs | 4 +- .../clippy_lints/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 6b347f7035a..f1baa0e4dcc 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 2ad96a24891..401efff9242 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 e2cd4d5f21c..f9628d1d6f3 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 9f4f1413650..67119461108 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 f77f250cd28..8967b51749c 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 4772bae58c4..2a55a58a668 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 e557f36037b..d8ce2307995 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 f5abb7261c0..4b371a4d2e6 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 d11198d7fd4..210d383ac7f 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 0576ab3b80c..e15754877d9 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 a4cd9ccc984..3ea409827b4 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 f42f58322dc..ddb4224b60d 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 fde3d41faec..40a40b0a73f 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 81b7de7f634..2778ada655e 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 b2ead3cd40b..6f18cc51b11 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 c746fb8af89..af172b59a14 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 95813cb68a6..b87f9bc8b19 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 db01ff2cd22..bfd89bfd2c7 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 788fe828727..87f6f5e7959 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 81efec65343..7882bfdd09f 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 5a986254fad..a0d609501a0 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 9d5066199bd..a285f771f1b 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 e90306ded61..b418db53ea4 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 903593ecfd7..6732a43a19e 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 fa033838ef3..a1b08d105b9 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 b36c4ef91dc..81d4a26e9da 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 { -- cgit 1.4.1-3-g733a5 From 108732590d010c701dd6f665b5ebddff52ef0ab0 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Fri, 19 Jan 2024 01:25:15 +0900 Subject: 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 1d6e4796d0a..d7aef47235f 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" -- cgit 1.4.1-3-g733a5 From 21b4fe222f73e5f2b1791004071d73c19a63d08c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 18 Jan 2024 15:50:40 +0300 Subject: Set RUSTC_BOOTSTRAP=1 consistently Signed-off-by: onur-ozkan --- src/bootstrap/bootstrap.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6f3be1f6e93..28d96cb1cfe 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) - - # preserve existing RUSTFLAGS - env.setdefault("RUSTFLAGS", "") + # 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" + + 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": -- cgit 1.4.1-3-g733a5 From d95d6ceecb372c66ed18a4e7a0bbb79e74ee8fed Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 12:54:01 -0500 Subject: `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 9422a594488..d7f17ac4547 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 00000000000..5dd6f93fd03 --- /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); +} -- cgit 1.4.1-3-g733a5 From fb7762b1c51d67a56324b92fd79c85b33d5d1d3b Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:14 -0500 Subject: 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 9463b73b574..f83c8f83cc9 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 { -- cgit 1.4.1-3-g733a5 From 92cc57bafcea1380e2a8f7a6a732302b04c28c5f Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:35 -0500 Subject: 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 65e5700d083..5044d99ec51 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 8d6cea10933..e87c402f8f9 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 6c2907c86e9..ddfc86f74d3 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>); -- cgit 1.4.1-3-g733a5 From aeeaed9ce137d489f7157202548d2ce3d65c60ae Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:24 -0500 Subject: 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 9542673b0d9..387253a3f98 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 2283231eb01..d71d5954a40 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) {} -- cgit 1.4.1-3-g733a5 From 9d15b5037f7b263a6e9e4a675f026851578be744 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Jan 2024 00:41:56 +0000 Subject: 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 d11198d7fd4..a67def2f5b1 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 fde3d41faec..f3d70867e37 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> { -- cgit 1.4.1-3-g733a5 From 7fead95cec9a4a0c05de6d1d22a6fbe0b8594dd8 Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Thu, 18 Jan 2024 21:04:31 +0100 Subject: Remove myself from review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index bd14640e280..b3f3051e177 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -644,7 +644,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", - "@WaffleLapkin", "@b-naber", ] compiler = [ -- cgit 1.4.1-3-g733a5 From a947c4c2c34a5bc1f25d5e9fd5cc269b4ae0d330 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 17:19:28 +0100 Subject: Add tests --- tests/ui/pattern/never_patterns.rs | 73 ---------------- tests/ui/pattern/never_patterns.stderr | 17 ---- tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs | 111 ++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 90 deletions(-) delete mode 100644 tests/ui/pattern/never_patterns.rs delete mode 100644 tests/ui/pattern/never_patterns.stderr create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs deleted file mode 100644 index 8f44f8a6559..00000000000 --- a/tests/ui/pattern/never_patterns.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![feature(never_patterns)] -#![allow(incomplete_features)] - -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 - let (Ok(_x) | Err(!)) = &res; - let (Ok(_x) | Err(&!)) = res.as_ref(); -} - -// Check we only accept `!` where we want to. -fn never_pattern_location(void: Void) { - // FIXME(never_patterns): Don't accept on a non-empty type. - 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 => {} - !, - } - // 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(!) - } - match None::<&Void> { - None => {} - Some(!), - } - // Accept on a composite empty type. - match None::<&(u32, Void)> { - None => {} - Some(&!), - } - // Accept on an simple empty type. - match None:: { - None => {} - Some(!), - } - match None::<&Void> { - None => {} - Some(&!), - } - match None::<&(u32, Void)> { - None => {} - Some(&(_, !)), - } -} diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr deleted file mode 100644 index 20eeb01cf71..00000000000 --- 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/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs new file mode 100644 index 00000000000..90ff34e2f02 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -0,0 +1,111 @@ +// 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; + let (Ok(_x) | Err(!)) = &res; + let (Ok(_x) | Err(!)) = res.as_ref(); +} + +// 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. + 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(!), + } + match None::<&Void> { + None => {} + Some(!), + } + + // Accept on a directly empty type. + match void { + !, + } + match &void { + &!, + } + match None:: { + None => {} + Some(!), + } + match None::<&Void> { + None => {} + Some(&!), + } + match None::<&(u32, 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(!), + } +} -- cgit 1.4.1-3-g733a5 From d8b72e796e4e2bc31701e2197c4bc6f324adbf64 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jan 2024 17:21:09 +0100 Subject: 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 ++++++ tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs | 17 ++++-- .../ui/rfcs/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 fe8c36dbe06..2060e01e1d6 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 615b553434f..2f11cb123ee 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 61ad99acf38..e3cc21cef11 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 f6c5e4a5cd6..6b08f6eb7c5 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 90ff34e2f02..333108e92c0 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 00000000000..8c0475894de --- /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 + -- cgit 1.4.1-3-g733a5 From ff6fa67a9dd61cafe44446ff2910e14ad78584c2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 16 Jan 2024 16:39:38 +0100 Subject: Split-off the passing tests to ensure they pass --- .../rfc-0000-never_patterns/typeck.fail.stderr | 66 ++++++++++++++++++++++ tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs | 25 +++++--- .../ui/rfcs/rfc-0000-never_patterns/typeck.stderr | 66 ---------------------- 3 files changed, 82 insertions(+), 75 deletions(-) create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr delete mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr new file mode 100644 index 00000000000..013a8b53a55 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr @@ -0,0 +1,66 @@ +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 `()` + +error: mismatched types + --> $DIR/typeck.rs:29: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:33: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:38: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:45: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:52: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:57: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:63: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 + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 333108e92c0..31a23fa002c 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 { !, diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr deleted file mode 100644 index 8c0475894de..00000000000 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.stderr +++ /dev/null @@ -1,66 +0,0 @@ -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 - -- cgit 1.4.1-3-g733a5 From b28a95391b85e17b1d2f7edc1115291d8a86bcd2 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Jan 2024 22:47:20 +0100 Subject: 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 e976552cf2b..33dd4139bc0 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; -- cgit 1.4.1-3-g733a5 From 85d17879623116be76a68c2170c4cb6ff58f4ceb Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Jan 2024 22:50:14 +0100 Subject: 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 ec5f32539f2..5a783e66752 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); -- cgit 1.4.1-3-g733a5 From be9668d3989b721bfaa2ec517b307965476431fa Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 31 Dec 2023 01:53:51 +0000 Subject: Use an interpreter in jump threading. --- compiler/rustc_mir_transform/src/jump_threading.rs | 102 +++++++++++++++------ ...eading.aggregate.JumpThreading.panic-abort.diff | 52 +++++++++++ ...ading.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 dcab124505e..fc77076e4e7 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 00000000000..66aa892c6f3 --- /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 00000000000..66aa892c6f3 --- /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 0cbdaa085bc..7c2fa42828b 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 -- cgit 1.4.1-3-g733a5 From b22742e8f3ddc9370d149ff89be47603b0f80ff8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 31 Dec 2023 02:00:30 +0000 Subject: Extract process_constant. --- compiler/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 fc77076e4e7..c491cb22cbe 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) => { -- cgit 1.4.1-3-g733a5 From e72b2b18c01919e9146e2bfb7b6ea0f0ea72997c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 31 Dec 2023 02:04:09 +0000 Subject: Extract process_assign. --- compiler/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 c491cb22cbe..e87f68a0905 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)?; } _ => {} } -- cgit 1.4.1-3-g733a5 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: 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 8aa0c6e7ed6..35ea97bfe60 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 /// -- cgit 1.4.1-3-g733a5 From 1a343424f3ba3ce230b2b9ceeff9cc7449f354d3 Mon Sep 17 00:00:00 2001 From: kapilsinha Date: Thu, 18 Jan 2024 17:49:06 -0800 Subject: 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 0a1c4430397..054ab2d126a 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 -- cgit 1.4.1-3-g733a5 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: 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 bd14640e280..0e60153ce2e 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"] -- cgit 1.4.1-3-g733a5 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: 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 ++ tests/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 5baa108ed3c..a230ba0e439 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 00000000000..05b7ec26379 --- /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 00000000000..9f3659aac16 --- /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 00000000000..2840fc0a761 --- /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`. -- cgit 1.4.1-3-g733a5 From dbff90c2a7c751cf9d6843cd585429beb100c17d Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 12 Oct 2023 17:36:01 +0000 Subject: 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 +++++++++--- compiler/rustc_target/src/spec/targets/i386_apple_ios.rs | 2 +- compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs | 2 +- compiler/rustc_target/src/spec/targets/i686_linux_android.rs | 2 +- .../rustc_target/src/spec/targets/i686_pc_windows_gnu.rs | 2 +- .../rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs | 2 +- .../rustc_target/src/spec/targets/i686_pc_windows_msvc.rs | 2 +- .../rustc_target/src/spec/targets/i686_unknown_freebsd.rs | 2 +- compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs | 2 +- .../rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs | 2 +- .../rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs | 2 +- .../rustc_target/src/spec/targets/i686_unknown_linux_musl.rs | 2 +- .../rustc_target/src/spec/targets/i686_unknown_netbsd.rs | 2 +- .../rustc_target/src/spec/targets/i686_unknown_openbsd.rs | 2 +- .../rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs | 2 +- .../rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs | 2 +- compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs | 2 +- .../rustc_target/src/spec/targets/x86_64_apple_darwin.rs | 4 ++-- compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs | 4 ++-- compiler/rustc_target/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 ++-- .../rustc_target/src/spec/targets/x86_64_linux_android.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs | 4 ++-- compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs | 4 ++-- .../src/spec/targets/x86_64_pc_windows_gnullvm.rs | 4 ++-- .../rustc_target/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 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_haiku.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_hermit.rs | 4 ++-- .../rustc_target/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 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_none.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_redox.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_unknown_uefi.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs | 4 ++-- .../rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs | 4 ++-- compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs | 4 ++-- .../rustc_target/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 d0d98eb3d62..7f5213431f7 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 1d1b6e6148d..f3b2caf9b80 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 36f5ba161d5..624ae8c22f9 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 13f8b6b5a0a..a221538b902 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 59069fe4e3a..25617b4436c 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 79471040f0d..12ebf0c72f8 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 8d4a39b5811..11818034414 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 bb410cd8caf..f4e33b88178 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 5abc3017bf8..9f1c8f4676c 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 927b2ab877d..d90f481c68c 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 bc7fd6fbc68..330a390c981 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 6884e078c27..c32f7177c1a 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 3b7be48dbbc..9bc38a72f4d 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 ef58b4fb458..4a82e0986c7 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 5f3afbe5afd..ea72656607e 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 f44584a10be..945dc0f8967 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 ec211a710eb..0830033dc23 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 7cca2fc6b9f..534dd6ee54f 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 ee501c5165e..30c2295e402 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 59df3937ea6..356c6721868 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 d0e2ac44a2a..55165ea4ec6 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 8ef4b88b8b1..ff21e489333 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 17efd437f2f..20b01612553 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 b1f72ee2f21..806a58e980b 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 f4117edc3ff..c38a1a08536 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 0e6d41abc9b..30b1ee73630 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 93aec4c425a..0ef01597399 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 f15ad8dda63..ade4dd6d431 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 6d3e0727051..9e964d248bf 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 a56ebfa585e..1facf9450cd 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 3a4da91c244..357261073a8 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 e6159fca3ae..6c9d1147548 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 80adb8fa2d9..ce682bb8005 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 fa321035367..6d6940e7891 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 5b19ed1b5ff..50139e5c1d8 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 0f927be962b..c00c689f7ef 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 df191f515bd..fb46848ba8c 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 eb2b13cb5c2..3e3f4921322 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 7b86fe738b1..646623668c6 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 bf10f7e5d2d..2296b58f45d 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 8dc5503e336..c71dc65670c 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 35862656aa2..c25105f6e35 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 e2cee0513ba..466498acb0b 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 8f7655d8ccd..ceded7790a6 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 1133b50f3d2..b542a569bbd 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 c1f57311292..550b7a3d282 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 5abfb8162f7..95847e57a0f 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 a46d3a0e27b..c2981ddbad6 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 a3bc27aa065..3f0702c7ad6 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 765239bdd39..f7a78b48f95 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 0c731e369eb..e0e4cb93e31 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 }, } -- cgit 1.4.1-3-g733a5 From 7a0415ce3728cb29e313429118cd113405273745 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 18 Jan 2024 14:34:17 +0100 Subject: 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 00000000000..ef1313ddb67 --- /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 }; +} -- cgit 1.4.1-3-g733a5 From ce2d91dccd48b1adc7224993829394682fd5ce19 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 19 Jan 2024 09:28:42 +0100 Subject: 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 ef1313ddb67..aaf5785dc9f 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] -- cgit 1.4.1-3-g733a5 From ec55a05374d89d206be5140a4759af92f1b42f15 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 19 Jan 2024 11:09:30 +0100 Subject: 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 +- compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs | 2 +- compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs | 2 +- compiler/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 3ebf4bcf523..ea8b919e748 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 8375fa4c0c0..574dc658b78 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 25315e19cdd..37d57c1cdf3 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 5b91682e168..35ad81dc052 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 1856c6afd52..d4b6519262e 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 5a59839ebc6..fd26b6e8cae 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, } -- cgit 1.4.1-3-g733a5 From 867831a1703c0ea7c062a5139538ea20f5921b62 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 10 Jan 2024 16:54:43 +0000 Subject: Always use RevealAll for const eval queries --- .../src/const_eval/eval_queries.rs | 38 ++++------------ compiler/rustc_middle/src/mir/interpret/queries.rs | 4 +- ...-24949-assoc-const-static-recursion-impl.stderr | 5 --- ...soc-const-static-recursion-trait-default.stderr | 5 --- ...24949-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 --- .../ui/consts/recursive-zst-static.default.stderr | 9 +--- .../ui/consts/recursive-zst-static.unleash.stderr | 9 +--- .../ui/consts/write-to-static-mut-in-static.stderr | 9 +--- tests/ui/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 +++++++++++++ .../ui/impl-trait/in-ctfe/match-arm-exhaustive.rs | 24 +++++++++++ tests/ui/impl-trait/transmute/in-defining-scope.rs | 14 ++++++ .../impl-trait/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 +++-- .../recursion/recursive-static-definition.stderr | 9 +--- .../ui/specialization/ctfe/default-assoc-const.rs | 18 ++++++++ .../specialization/ctfe/default-assoc-const.stderr | 12 ++++++ tests/ui/specialization/ctfe/default-assoc-type.rs | 27 ++++++++++++ .../specialization/ctfe/default-assoc-type.stderr | 12 ++++++ tests/ui/treat-err-as-bug/err.stderr | 2 +- .../self-in-enum-definition.stderr | 5 --- tests/ui/type-alias-impl-trait/in-where-clause.rs | 16 +++++++ .../type-alias-impl-trait/in-where-clause.stderr | 50 ++++++++++++++++++++++ 32 files changed, 363 insertions(+), 108 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 9d22df50d4f..4236117d75b 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. - - // 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, - } - } + // 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); 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 092b59deeff..b20df1b2343 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 21062fdaf58..88b17be601c 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 e4abf6203e8..fd1b4f2f964 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 05ebd76f500..303400f928e 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 01fb8153cf3..1b60f7f3f2d 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 a5679400c2f..cd0ea556425 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 4f2d92ba3cd..de70a457f16 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 adb5747c424..641945fce9f 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 3bbb685a678..5b4a0418b1e 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 3bbb685a678..5b4a0418b1e 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 5665e56439e..caee433a681 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 00000000000..01ba902ef0c --- /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 00000000000..73ae20495d5 --- /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 00000000000..8e4384adaa4 --- /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 00000000000..82a9a30a623 --- /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 00000000000..8e3269726fc --- /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 00000000000..b0b77d60b24 --- /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 00000000000..69812f43072 --- /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 00000000000..7bc22ea416f --- /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 5c2758dc609..53131f9130d 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 93665af69dd..d55d88762be 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 b3e933a2171..e23957c6de7 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 570d203d07f..4fc3ee68ebc 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 00000000000..bb3b735caa3 --- /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 00000000000..933b6dcf8f9 --- /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 00000000000..3624a0f160c --- /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 00000000000..23fa213caff --- /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 3a56445a26b..7eeec4604c4 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 94113b336c3..7f80c3cfaba 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 00000000000..0ad6e7a6f60 --- /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 00000000000..9c08b8f127d --- /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`. -- cgit 1.4.1-3-g733a5 From 058ab53dc58b70d4b0b60374d4f7ddfede4dae65 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 19 Jan 2024 08:19:18 +0100 Subject: use implied bounds compat mode in MIR borrowck --- .../traits/query/type_op/implied_outlives_bounds.rs | 12 ++++++++++-- tests/ui/associated-inherent-types/issue-111404-1.rs | 1 - .../associated-inherent-types/issue-111404-1.stderr | 10 +--------- tests/ui/implied-bounds/bevy_world_query.rs | 4 +++- .../normalization-nested.lifetime.stderr | 10 ++++++++++ tests/ui/implied-bounds/normalization-nested.rs | 14 ++++++++++---- tests/ui/inference/issue-80409.no-compat.stderr | 6 ++++++ tests/ui/inference/issue-80409.rs | 19 ++++++++++++------- tests/ui/inference/issue-80409.stderr | 6 ------ 9 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 tests/ui/implied-bounds/normalization-nested.lifetime.stderr create mode 100644 tests/ui/inference/issue-80409.no-compat.stderr delete 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 2fdb63d7dee..83d23597c0c 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 74f9434b881..dd62e59f07d 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 1613161a873..cf4d4a5f19b 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 d5de0e9ef21..2e3d4e6a7c6 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 00000000000..c43cc0999f1 --- /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 3f569aa1ace..6ceb13e9473 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.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr new file mode 100644 index 00000000000..7bb4786db3a --- /dev/null +++ b/tests/ui/inference/issue-80409.no-compat.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 + diff --git a/tests/ui/inference/issue-80409.rs b/tests/ui/inference/issue-80409.rs index d36688978e9..49c9978fe15 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)] diff --git a/tests/ui/inference/issue-80409.stderr b/tests/ui/inference/issue-80409.stderr deleted file mode 100644 index 7bb4786db3a..00000000000 --- a/tests/ui/inference/issue-80409.stderr +++ /dev/null @@ -1,6 +0,0 @@ -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 - -- cgit 1.4.1-3-g733a5 From 130b7e713e879c4c989186d94643be8c834de355 Mon Sep 17 00:00:00 2001 From: Gavin Gray Date: Tue, 21 Nov 2023 20:37:36 +0100 Subject: 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 ++ .../rustc_trait_selection/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 67c35d717a1..80467ca9381 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 e60e3ffeaa7..0f1af81d9f0 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 e164041c599..39c41a93c3b 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 fdae093aac8..72ec07375ac 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 c847425ebf4..f08622816ec 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| { -- cgit 1.4.1-3-g733a5 From 50b4ca637d5d24e47df5cd453d136185d5ece7df Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 18 Jan 2024 16:43:49 +0000 Subject: 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 8e791a7dc69..d673ce7a736 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 { -- cgit 1.4.1-3-g733a5 From 93740f94938bc0b082514736be0051946ec8d732 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 31 Jan 2023 12:44:15 +0000 Subject: 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 ede8416125d..0b25628b9e1 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 bff93859645..83efbfb855f 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 } } -- cgit 1.4.1-3-g733a5 From 225f0b9fef38bd7b841bff9911e0ced586dce812 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 19 Jan 2024 16:37:50 +0000 Subject: 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 eba2ac57012..b0a08cd9b79 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; -- cgit 1.4.1-3-g733a5 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: 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 9c897ae1bb7..dd9c68aba7f 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 32a04cfd5d1..d329fe997cd 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": [ -- cgit 1.4.1-3-g733a5 From 615946db4fc812bff3bb015dfe860c10da4b20c1 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Tue, 5 Dec 2023 22:15:26 +0000 Subject: Stabilize simple offset_of --- .../rustc_error_codes/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-gates/feature-gate-offset-of-enum.rs | 2 +- .../feature-gates/feature-gate-offset-of-nested.rs | 28 +++++++++++ .../feature-gate-offset-of-nested.stderr | 55 ++++++++++++++++++++++ .../lint/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 - tests/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/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 20f51441c29..ad77d72c913 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 2f2b551e6ec..c512ccc90db 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 4b1ad28f094..242e8dc95e2 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 44795022cba..7b0138d50ba 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 1a8f245c8be..81bf6f28693 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 407954001e4..f04ccce40f1 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 8604d41eb68..02af3e6f947 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 7a8d9d0ceec..4b33ad5dfe0 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 e19dcf9f6a5..1f2f7ee1e19 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 00000000000..c4eb4720fde --- /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 00000000000..ebc251fd663 --- /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 2c6fcef2500..ae81a252439 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 da91de3862f..5269426d2ff 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 7b92698c25e..c86e61a61a7 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 af0d42de30d..4cb24b3d034 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 e393b159e64..016ebfadd14 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 a2d6aace47d..cb2f04786ac 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 ba87574eae0..1b1ae25e1ee 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 1845822f11d..8bd104ed7e2 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 e30145d7a2f..e4b092fcedf 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 5fe387a7255..b6d88e098d0 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 50c2e93841f..76a33154ba3 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 233d4987643..34ad931d0ca 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 b7affdb7943..1c326b5c79a 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 04dcaf7c0a6..1558e13b530 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 59b02e3c5c4..212176b2427 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 b6fc1e32229..75ba8d77f2f 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 49c8328da5c..b70529ed7b8 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 7d2eb46c056..be275564a0a 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 1e19f2091f2..da0882abd22 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; -- cgit 1.4.1-3-g733a5 From 803b810eac520c11c7f1ea0a81af535ee9bddd61 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 5 Jan 2024 21:25:01 +0000 Subject: 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 02af3e6f947..13fb97fdc7f 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 43ecbbed186..f15d15bfcb2 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 e71b3f59eca..c1be6910258 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 e1783432857..1307c335ad3 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 23588ba36ee..e59e063df99 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)] -- cgit 1.4.1-3-g733a5 From 7924c9bcdfa0ec5980474ac680439d7fc2a4690f Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 19 Jan 2024 20:29:40 +0000 Subject: Split remaining offset_of features into new tracking issues --- compiler/rustc_feature/src/unstable.rs | 4 ++-- compiler/rustc_hir_typeck/src/expr.rs | 2 +- tests/ui/feature-gates/feature-gate-offset-of-enum.stderr | 4 ++-- .../ui/feature-gates/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 c512ccc90db..371b651f5e8 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 242e8dc95e2..33d7ba6268a 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 02ee54e8607..fc7dd7923f7 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 ebc251fd663..f367fc9fa0d 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 -- cgit 1.4.1-3-g733a5 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: add test issue-117965 --- tests/ui/single-use-lifetime/issue-117965.rs | 18 ++++++++++++++++++ tests/ui/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 00000000000..5eb2a03e13d --- /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 00000000000..e789e183546 --- /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 + -- cgit 1.4.1-3-g733a5 From 4459be7bd59c781c850ab48679ef3a1e420e9f99 Mon Sep 17 00:00:00 2001 From: SOFe Date: Sat, 29 Oct 2022 22:15:04 +0800 Subject: 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 7d60686597a..582c6796781 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] -- cgit 1.4.1-3-g733a5 From 3acb445f15d69c982c37df15a27d06b43ca6e388 Mon Sep 17 00:00:00 2001 From: SOFe Date: Sun, 30 Oct 2022 14:49:24 +0800 Subject: 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 582c6796781..53ee6efcba7 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. -- cgit 1.4.1-3-g733a5 From 596410eb36c90c501fc57f68d81a57b6e0053a5c Mon Sep 17 00:00:00 2001 From: SOFe Date: Fri, 30 Dec 2022 22:50:41 +0800 Subject: 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 53ee6efcba7..bda691b16d4 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> { -- cgit 1.4.1-3-g733a5 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: 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 5a95f2083f6..abb0a7a465a 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 e789e183546..ed14ab92f4d 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 -- cgit 1.4.1-3-g733a5 From b72af9fe9b01002fd0e352cd7e98ab811a014452 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 19 Jan 2024 18:02:05 -0500 Subject: 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 c3506175715..1b38ba72114 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 e4b7bfeeb84..f8fc84440ae 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 7a8d9d0ceec..11d655042b7 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 cacd02bbfae..80a47c85269 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 5f2d4489f4a..1bb44d56bf6 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)] -- cgit 1.4.1-3-g733a5 From b1688b48d2841a1421cb7ed0afd32ce0c3eeb20a Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 8 Jan 2024 23:00:06 +0000 Subject: Avoid ICE: Check diagnostic is error before downgrading Fix #119633. --- compiler/rustc_hir_analysis/src/astconv/lint.rs | 8 ++-- tests/ui/object-safety/avoid-ice-on-warning-2.rs | 9 ++++ .../ui/object-safety/avoid-ice-on-warning-2.stderr | 50 ++++++++++++++++++++++ tests/ui/object-safety/avoid-ice-on-warning.rs | 6 +++ tests/ui/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 3761d529517..bf668f311cc 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 00000000000..cd34362d3dd --- /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 00000000000..2755eee6f35 --- /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 00000000000..d2a1eeb5286 --- /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 00000000000..1046f177e82 --- /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`. -- cgit 1.4.1-3-g733a5 From 6b7e6ea590ad0179e9c61c5e007220ae1e4b9644 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Tue, 9 Jan 2024 00:22:35 +0000 Subject: Account for traits using self-trait by name without `dyn` Fix #119652. --- compiler/rustc_hir_analysis/src/astconv/lint.rs | 24 +++-- ...nsafe-trait-should-use-self-2021-without-dyn.rs | 19 ++++ ...e-trait-should-use-self-2021-without-dyn.stderr | 105 +++++++++++++++++++++ .../object-unsafe-trait-should-use-self-2021.rs | 17 ++++ ...object-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 bf668f311cc..b5f42e98127 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 00000000000..6382480b7e3 --- /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 00000000000..1d8ed548046 --- /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 00000000000..a598e883f3f --- /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 00000000000..d6376be9c04 --- /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`. -- cgit 1.4.1-3-g733a5 From 7edbc95c27664428ba22c448ca85ee4bd4de05dc Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Fri, 19 Jan 2024 23:49:40 +0000 Subject: Update tests after rebase Fix #119652. --- tests/ui/object-safety/avoid-ice-on-warning-3.rs | 17 +++ .../ui/object-safety/avoid-ice-on-warning-3.stderr | 148 +++++++++++++++++++++ ...nsafe-trait-should-use-self-2021-without-dyn.rs | 4 + ...e-trait-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 00000000000..caaf4d0fd99 --- /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 00000000000..0fc67770b96 --- /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 6382480b7e3..f48c3d124dd 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 1d8ed548046..73d5a24f831 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`. -- cgit 1.4.1-3-g733a5 From c3364a23d2a0ec8557f52fcf5a705503619274c3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 15 Jan 2024 14:41:12 -0500 Subject: 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). --- compiler/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 01f7bfcadb6..e147f62011d 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 48444a6b6f7..cf28e62177f 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); } } -- cgit 1.4.1-3-g733a5 From 078a979229b2e68570bf736c0a48be95d1ad41a7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 20 Jan 2024 02:33:49 +0000 Subject: 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 cbf01feae06..89b203f80a4 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; } -- cgit 1.4.1-3-g733a5 From 60208a0517dcc4b1358a51b1411f0cf4c8079905 Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Sun, 3 Jul 2022 00:31:02 +0300 Subject: 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 407954001e4..47dab575253 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 27bc00bc3ab..2c675174479 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) +} -- cgit 1.4.1-3-g733a5 From 6237bebd349c7ba9286e2daa76eef07bd6b7c5be Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 16:46:54 +0100 Subject: 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 df955421ba4..1bea93c7842 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; } } -- cgit 1.4.1-3-g733a5 From 0933f48ac0a8631b3f7c9c508f38843ef10e839d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 15 Jan 2024 16:47:14 +0100 Subject: Add regression test for #119015 and update tests --- tests/rustdoc/async-fn.rs | 18 ++++++++++------- tests/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 70bcbcb6ff4..b3c35c8c3f3 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 00000000000..68996deae6f --- /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) {} +} -- cgit 1.4.1-3-g733a5 From 862011e1cad78b956a2047e2a89e83ad9743c8dd Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Thu, 16 Feb 2023 19:29:11 +0100 Subject: 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 92dd45cf520..051b2a25716 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 1f09de0ed70..0f57688063e 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 eecbf86c173..02b3c740b63 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 3bb2cc5634f..9158ba00901 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 { -- cgit 1.4.1-3-g733a5 From 796cdc590c0f6badb9629feb2a2b55873408cc0f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 Dec 2023 00:21:27 +0100 Subject: Remove Ty: Copy bound --- .../rustc_mir_build/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 ++++++++++---------- compiler/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 e8ba83a5527..693dc49c6e8 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 21fa8e68d82..4fd01b5e638 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 d9dbd8250ef..f9f065fbe8b 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 75fe59edf88..8cd0ecb073c 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 87e70d68c1b..27b25802427 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 dac354a1c52..d7852a2b2cb 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. -- cgit 1.4.1-3-g733a5 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: 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 f1a7ad93548..ded17e69bd9 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. -- cgit 1.4.1-3-g733a5 From 606eeb84ad780a1cfe35e4d1265d7be4a412389e Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 10 Dec 2023 23:29:11 +0100 Subject: Use bool instead of PartiolOrd in is_sorted_by --- compiler/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 c2b307910e4..547f9f93109 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 8e2c887a161..e203533e08e 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 fc54ea23770..be67bfc7aa4 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 b14d9712794..e485e5f0525 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 995bbf0e261..e2b31658d0f 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 33a30339856..6a6eea3c072 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()); -- cgit 1.4.1-3-g733a5 From 384b2ab37529ba0ad07ea8271baf0f212bab2e5a Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sun, 21 Jan 2024 05:39:01 +0000 Subject: 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 ad3a534b7ed..aa05d224c21 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3deb9bbf84f6431ebcbb7cbdbe3d89bc2636bc1b +867d39cdf625e4db4b381faff993346582e598b4 -- cgit 1.4.1-3-g733a5 From bdfc64ac984e892f6061deebaee5a9301b8d271f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 21 Jan 2024 12:18:48 +1100 Subject: 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 00000000000..7cdb1b641bf --- /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 00000000000..4642d92cc19 --- /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 00000000000..2dcd7355b2f --- /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) {} -- cgit 1.4.1-3-g733a5 From 6d7e80c5bc3cc3b176834322afc50dc8dd100599 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 21 Jan 2024 11:26:28 +1100 Subject: 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 f60b73fbe9b..3e9b06a5b05 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 4d44e340ae1..0631f796894 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 a2437feeeb9..9bbaf62a5ca 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 7cdb1b641bf..aa702a48681 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 4642d92cc19..64945dc6415 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 6940d2e2824..f75328b11c9 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 ff6009f6fce..c3f660506fb 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 fd9386be8f3..fbdad0c323f 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] -- cgit 1.4.1-3-g733a5 From 7092c660077d185df375eaf07d649be2b49018d0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 21 Jan 2024 13:11:00 +0000 Subject: 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 6cd22a91518..8cd996d8564 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", -- cgit 1.4.1-3-g733a5