Auto merge of #148075 - cuviper:beta-next, r=cuviper

[beta] backports

- Revert constification of `AsRef for Cow` due to inference failure rust-lang/rust#148011
- Revert constification of `Borrow` and `Deref for Cow` due to inference failure rust-lang/rust#148016
- Revert "fix: Filter suggestion parts that match existing code" rust-lang/rust#148043
- Revert "feat: implement `hash_map!` macro" rust-lang/rust#148049
- fix panic when rustc tries to reduce intermediate filenames len with utf8 rust-lang/rust#148018

r? cuviper
This commit is contained in:
bors
2025-10-25 11:05:15 +00:00
17 changed files with 174 additions and 115 deletions
+5
View File
@@ -945,6 +945,11 @@ pub fn multipart_suggestion_with_style(
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 }],
+1
View File
@@ -2354,6 +2354,7 @@ fn emit_suggestion_default(
.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
+10 -17
View File
@@ -381,17 +381,6 @@ fn push_trailing(
// 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 @@ fn push_trailing(
_ => 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
+12 -3
View File
@@ -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-<suffix>" 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::<Hash64>();
path.set_file_name(format!("{:x}-{}", hash, &filename[stripped_len..]));
path.set_file_name(format!("{:x}-{}", hash, &filename[split_at..]));
}
path
}
+1
View File
@@ -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)]
+18 -13
View File
@@ -16,12 +16,13 @@
#[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<B> for Cow<'a, B>
where
B: ToOwned,
B::Owned: [const] Borrow<B>,
impl<'a, B: ?Sized + ToOwned> Borrow<B> for Cow<'a, B>
// where
// B::Owned: [const] Borrow<B>,
{
fn borrow(&self) -> &B {
&**self
@@ -327,11 +328,13 @@ pub fn into_owned(self) -> <B as ToOwned>::Owned {
}
}
// 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<B: ?Sized + ToOwned> const Deref for Cow<'_, B>
where
B::Owned: [const] Borrow<B>,
impl<B: ?Sized + ToOwned> Deref for Cow<'_, B>
// where
// B::Owned: [const] Borrow<B>,
{
type Target = B;
@@ -441,11 +444,13 @@ fn hash<H: Hasher>(&self, state: &mut H) {
}
}
// 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<T: ?Sized + ToOwned> const AsRef<T> for Cow<'_, T>
where
T::Owned: [const] Borrow<T>,
impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T>
// where
// T::Owned: [const] Borrow<T>,
{
fn as_ref(&self) -> &T {
self
-2
View File
@@ -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)]
-74
View File
@@ -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
}}
}
+17
View File
@@ -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! {}
}
@@ -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
+13
View File
@@ -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)
}
+15
View File
@@ -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<T>;
enum Foo<T> {
Bar { t: T },
}
fn main() {
Alias::Bar::<u32> { t: 0 };
}
+14
View File
@@ -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);
}
@@ -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 {}
};
}
@@ -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:
@@ -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();
}
}
}
@@ -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<Owned = U>, U>(cow: Cow<'a, T>) {
let _: &T = &cow;
}
pub fn generic_borrow<'a, T: ToOwned<Owned = U>, U>(cow: Cow<'a, T>) {
let _: &T = cow.borrow();
}
pub fn generic_as_ref<'a, T: ToOwned<Owned = U>, U>(cow: Cow<'a, T>) {
let _: &T = cow.as_ref();
}
fn main() {}