diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index ae23ef1e25536..96a4ed3218fbf 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -945,6 +945,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { None, "Span must not be empty and have no suggestion", ); + debug_assert_eq!( + parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)), + None, + "suggestion must not have overlapping parts", + ); self.push_suggestion(CodeSuggestion { substitutions: vec![Substitution { parts }], diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 93b1e6b761520..b94370e8e9b40 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2354,6 +2354,7 @@ impl HumanEmitter { .sum(); let underline_start = (span_start_pos + start) as isize + offset; let underline_end = (span_start_pos + start + sub_len) as isize + offset; + assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { if let DisplaySuggestion::Underline = show_code_change diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8869799ce90d9..a56e0f3fae132 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -381,17 +381,6 @@ impl CodeSuggestion { // Assumption: all spans are in the same file, and all spans // are disjoint. Sort in ascending order. substitution.parts.sort_by_key(|part| part.span.lo()); - // Verify the assumption that all spans are disjoint - assert_eq!( - substitution.parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)), - None, - "all spans must be disjoint", - ); - - // Account for cases where we are suggesting the same code that's already - // there. This shouldn't happen often, but in some cases for multipart - // suggestions it's much easier to handle it here than in the origin. - substitution.parts.retain(|p| is_different(sm, &p.snippet, p.span)); // Find the bounding span. let lo = substitution.parts.iter().map(|part| part.span.lo()).min()?; @@ -481,12 +470,16 @@ impl CodeSuggestion { _ => 1, }) .sum(); - - line_highlight.push(SubstitutionHighlight { - start: (cur_lo.col.0 as isize + acc) as usize, - end: (cur_lo.col.0 as isize + acc + len) as usize, - }); - + if !is_different(sm, &part.snippet, part.span) { + // Account for cases where we are suggesting the same code that's already + // there. This shouldn't happen often, but in some cases for multipart + // suggestions it's much easier to handle it here than in the origin. + } else { + line_highlight.push(SubstitutionHighlight { + start: (cur_lo.col.0 as isize + acc) as usize, + end: (cur_lo.col.0 as isize + acc + len) as usize, + }); + } buf.push_str(&part.snippet); let cur_hi = sm.lookup_char_pos(part.span.hi()); // Account for the difference between the width of the current code and the diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 297df7c2c9765..5e47559847e00 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1207,13 +1207,22 @@ fn maybe_strip_file_name(mut path: PathBuf) -> PathBuf { if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH { let filename = path.file_name().unwrap().to_string_lossy(); let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex - let stripped_len = filename.len() - MAX_FILENAME_LENGTH + hash_len; + let hyphen_len = 1; // the '-' we insert between hash and suffix + + // number of bytes of suffix we can keep so that "hash-" fits + let allowed_suffix = MAX_FILENAME_LENGTH.saturating_sub(hash_len + hyphen_len); + + // number of bytes to remove from the start + let stripped_bytes = filename.len().saturating_sub(allowed_suffix); + + // ensure we don't cut in a middle of a char + let split_at = filename.ceil_char_boundary(stripped_bytes); let mut hasher = StableHasher::new(); - filename[..stripped_len].hash(&mut hasher); + filename[..split_at].hash(&mut hasher); let hash = hasher.finish::(); - path.set_file_name(format!("{:x}-{}", hash, &filename[stripped_len..])); + path.set_file_name(format!("{:x}-{}", hash, &filename[split_at..])); } path } diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 5e5872ee06815..ac11e792fc2e3 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,5 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![feature(default_field_values)] #![feature(iter_intersperse)] #![feature(rustc_attrs)] diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index cb32896161e5c..d2ab5412eeabc 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -16,12 +16,13 @@ use crate::fmt; #[cfg(not(no_global_oom_handling))] use crate::string::String; +// FIXME(inference): const bounds removed due to inference regressions found by crater; +// see https://github.com/rust-lang/rust/issues/147964 +// #[rustc_const_unstable(feature = "const_convert", issue = "143773")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl<'a, B: ?Sized> const Borrow for Cow<'a, B> -where - B: ToOwned, - B::Owned: [const] Borrow, +impl<'a, B: ?Sized + ToOwned> Borrow for Cow<'a, B> +// where +// B::Owned: [const] Borrow, { fn borrow(&self) -> &B { &**self @@ -327,11 +328,13 @@ impl Cow<'_, B> { } } +// FIXME(inference): const bounds removed due to inference regressions found by crater; +// see https://github.com/rust-lang/rust/issues/147964 +// #[rustc_const_unstable(feature = "const_convert", issue = "143773")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const Deref for Cow<'_, B> -where - B::Owned: [const] Borrow, +impl Deref for Cow<'_, B> +// where +// B::Owned: [const] Borrow, { type Target = B; @@ -441,11 +444,13 @@ where } } +// FIXME(inference): const bounds removed due to inference regressions found by crater; +// see https://github.com/rust-lang/rust/issues/147964 +// #[rustc_const_unstable(feature = "const_convert", issue = "143773")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const AsRef for Cow<'_, T> -where - T::Owned: [const] Borrow, +impl AsRef for Cow<'_, T> +// where +// T::Owned: [const] Borrow, { fn as_ref(&self) -> &T { self diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 33e3bf0c085da..39c76ddba568f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -294,8 +294,6 @@ #![feature(ffi_const)] #![feature(formatting_options)] #![feature(funnel_shifts)] -#![feature(hash_map_internals)] -#![feature(hash_map_macro)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] #![feature(iter_advance_by)] diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 254570ae9c836..25e2b7ea13703 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -379,77 +379,3 @@ macro_rules! dbg { ($($crate::dbg!($val)),+,) }; } - -#[doc(hidden)] -#[macro_export] -#[allow_internal_unstable(hash_map_internals)] -#[unstable(feature = "hash_map_internals", issue = "none")] -macro_rules! repetition_utils { - (@count $($tokens:tt),*) => {{ - [$($crate::repetition_utils!(@replace $tokens => ())),*].len() - }}; - - (@replace $x:tt => $y:tt) => { $y } -} - -/// Creates a [`HashMap`] containing the arguments. -/// -/// `hash_map!` allows specifying the entries that make -/// up the [`HashMap`] where the key and value are separated by a `=>`. -/// -/// The entries are separated by commas with a trailing comma being allowed. -/// -/// It is semantically equivalent to using repeated [`HashMap::insert`] -/// on a newly created hashmap. -/// -/// `hash_map!` will attempt to avoid repeated reallocations by -/// using [`HashMap::with_capacity`]. -/// -/// # Examples -/// -/// ```rust -/// #![feature(hash_map_macro)] -/// -/// let map = hash_map! { -/// "key" => "value", -/// "key1" => "value1" -/// }; -/// -/// assert_eq!(map.get("key"), Some(&"value")); -/// assert_eq!(map.get("key1"), Some(&"value1")); -/// assert!(map.get("brrrrrrooooommm").is_none()); -/// ``` -/// -/// And with a trailing comma -/// -///```rust -/// #![feature(hash_map_macro)] -/// -/// let map = hash_map! { -/// "key" => "value", // notice the , -/// }; -/// -/// assert_eq!(map.get("key"), Some(&"value")); -/// ``` -/// -/// The key and value are moved into the HashMap. -/// -/// [`HashMap`]: crate::collections::HashMap -/// [`HashMap::insert`]: crate::collections::HashMap::insert -/// [`HashMap::with_capacity`]: crate::collections::HashMap::with_capacity -#[macro_export] -#[allow_internal_unstable(hash_map_internals)] -#[unstable(feature = "hash_map_macro", issue = "144032")] -macro_rules! hash_map { - () => {{ - $crate::collections::HashMap::new() - }}; - - ( $( $key:expr => $value:expr ),* $(,)? ) => {{ - let mut map = $crate::collections::HashMap::with_capacity( - const { $crate::repetition_utils!(@count $($key),*) } - ); - $( map.insert($key, $value); )* - map - }} -} diff --git a/library/std/tests/ambiguous-hash_map.rs b/library/std/tests/ambiguous-hash_map.rs new file mode 100644 index 0000000000000..bd5ae5a8957b5 --- /dev/null +++ b/library/std/tests/ambiguous-hash_map.rs @@ -0,0 +1,17 @@ +//! Make sure that a `std` macro `hash_map!` does not cause ambiguity +//! with a local glob import with the same name. +//! +//! See regression https://github.com/rust-lang/rust/issues/147971 + +mod module { + macro_rules! hash_map { + () => {}; + } + pub(crate) use hash_map; +} + +use module::*; + +fn main() { + hash_map! {} +} diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr index 72aa6303a2026..f823f08f31dca 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr @@ -272,8 +272,10 @@ LL | assert_eq!(a!(), true); | help: replace it with `assert!(..)` | -LL - assert_eq!(a!(), true); -LL + assert!(a!()); +LL | true +... +LL | +LL ~ assert!(a!()); | error: used `assert_eq!` with a literal bool @@ -284,8 +286,10 @@ LL | assert_eq!(true, b!()); | help: replace it with `assert!(..)` | -LL - assert_eq!(true, b!()); -LL + assert!(b!()); +LL | true +... +LL | +LL ~ assert!(b!()); | error: used `debug_assert_eq!` with a literal bool diff --git a/tests/crashes/146261.rs b/tests/crashes/146261.rs new file mode 100644 index 0000000000000..f901497a769c2 --- /dev/null +++ b/tests/crashes/146261.rs @@ -0,0 +1,13 @@ +// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with +// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121. + +//@ needs-rustc-debug-assertions +//@ known-bug: #146261 + +enum U { + B(), +} + +fn main() { + A(U::C) +} diff --git a/tests/crashes/146706.rs b/tests/crashes/146706.rs new file mode 100644 index 0000000000000..358ce3e8600a8 --- /dev/null +++ b/tests/crashes/146706.rs @@ -0,0 +1,15 @@ +// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with +// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121. + +//@ needs-rustc-debug-assertions +//@ known-bug: #146706 + +type Alias<'a, T> = Foo; + +enum Foo { + Bar { t: T }, +} + +fn main() { + Alias::Bar:: { t: 0 }; +} diff --git a/tests/crashes/147973.rs b/tests/crashes/147973.rs new file mode 100644 index 0000000000000..7271c54846f15 --- /dev/null +++ b/tests/crashes/147973.rs @@ -0,0 +1,14 @@ +// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with +// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121. +// This is one MCVE from the beta crater run regressions from issue 147973. + +//@ needs-rustc-debug-assertions +//@ known-bug: #147973 + +//@ aux-build: overlapping_spans_helper.rs +extern crate overlapping_spans_helper; + +fn main() { + let _name = Some(1); + overlapping_spans_helper::do_loop!(_name); +} diff --git a/tests/crashes/auxiliary/overlapping_spans_helper.rs b/tests/crashes/auxiliary/overlapping_spans_helper.rs new file mode 100644 index 0000000000000..e449fcd36c376 --- /dev/null +++ b/tests/crashes/auxiliary/overlapping_spans_helper.rs @@ -0,0 +1,15 @@ +// Auxiliary lib for the issue 147973 regression test with ICEs due to overlapping spans. + +#[macro_export] +macro_rules! identity { + ($x:ident) => { + $x + }; +} + +#[macro_export] +macro_rules! do_loop { + ($x:ident) => { + for $crate::identity!($x) in $x {} + }; +} diff --git a/tests/run-make/lto-long-filenames/rmake.rs b/tests/run-make/lto-long-filenames/rmake.rs index 9e0ba63e9f5b8..98ce54e5efc82 100644 --- a/tests/run-make/lto-long-filenames/rmake.rs +++ b/tests/run-make/lto-long-filenames/rmake.rs @@ -9,8 +9,6 @@ //@ ignore-cross-compile -use std::fs; - use run_make_support::{rfs, rustc}; // This test make sure we don't get such following error: diff --git a/tests/run-make/lto-long-filenames_cn/rmake.rs b/tests/run-make/lto-long-filenames_cn/rmake.rs new file mode 100644 index 0000000000000..fc25a2ac166b2 --- /dev/null +++ b/tests/run-make/lto-long-filenames_cn/rmake.rs @@ -0,0 +1,25 @@ +//@ ignore-cross-compile +// gnu ld is confused with intermediate files having multibytes characters in their names: +// = note: ld.exe: cannot find f0d5ff18d6510ebc-???_???_??????????_?_?????_?_???????.d50c2 \ +// 4c0c4ea93cc-cgu.0.rcgu.o: Invalid argument +// as this is not something rustc can fix by itself, +// we just skip the test on windows-gnu for now. Hence: +//@ ignore-windows-gnu + +use run_make_support::{rfs, rustc}; + +// This test make sure we don't crash when lto creates output files with long names. +// cn characters can be multi-byte and thus trigger the long filename reduction code more easily. +// we need to make sure that the code is properly generating names at char boundaries. +// as reported in issue #147975 +fn main() { + let lto_flags = ["-Clto", "-Clto=yes", "-Clto=off", "-Clto=thin", "-Clto=fat"]; + for prefix_len in 0..4 { + let prefix: String = std::iter::repeat("_").take(prefix_len).collect(); + let main_file = format!("{}ⵅⴻⵎⵎⴻⵎ_ⴷⵉⵎⴰ_ⵖⴻⴼ_ⵢⵉⵙⴻⴽⴽⵉⵍⴻⵏ_ⵏ_ⵡⴰⵟⴰⵙ_ⵏ_ⵢⵉⴱⵢⵜⴻⵏ.rs", prefix); + rfs::write(&main_file, "fn main() {}\n"); + for flag in lto_flags { + rustc().input(&main_file).arg(flag).run(); + } + } +} diff --git a/tests/ui/traits/generic-cow-inference-regression.rs b/tests/ui/traits/generic-cow-inference-regression.rs new file mode 100644 index 0000000000000..6fd4715f85bbd --- /dev/null +++ b/tests/ui/traits/generic-cow-inference-regression.rs @@ -0,0 +1,20 @@ +//@ run-pass + +// regression test for #147964: +// constification of these traits resulted in inference errors due to additional where clauses + +use std::borrow::{Cow, Borrow}; + +pub fn generic_deref<'a, T: ToOwned, U>(cow: Cow<'a, T>) { + let _: &T = &cow; +} + +pub fn generic_borrow<'a, T: ToOwned, U>(cow: Cow<'a, T>) { + let _: &T = cow.borrow(); +} + +pub fn generic_as_ref<'a, T: ToOwned, U>(cow: Cow<'a, T>) { + let _: &T = cow.as_ref(); +} + +fn main() {}