Skip to content

Commit 3f1552a

Browse files
committed
Auto merge of #146650 - matthiaskrgr:rollup-rjrklz9, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #146442 (Display ?Sized, const, and lifetime parameters in trait item suggestions across a crate boundary) - #146474 (Improve `core::ascii` coverage) - #146605 (Bump rustfix 0.8.1 -> 0.8.7) - #146611 (bootstrap: emit hint if a config key is used in the wrong section) - #146618 (Do not run ui test if options specific to LLVM are used when another codegen backend is used) r? `@ghost` `@rustbot` modify labels: rollup
2 parents a9d0a6f + cf03552 commit 3f1552a

File tree

15 files changed

+183
-43
lines changed

15 files changed

+183
-43
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4817,9 +4817,9 @@ dependencies = [
48174817

48184818
[[package]]
48194819
name = "rustfix"
4820-
version = "0.8.1"
4820+
version = "0.8.7"
48214821
source = "registry+https://github.com/rust-lang/crates.io-index"
4822-
checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
4822+
checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a"
48234823
dependencies = [
48244824
"serde",
48254825
"serde_json",

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub mod intrinsic;
7070
mod region;
7171
pub mod wfcheck;
7272

73+
use std::borrow::Cow;
7374
use std::num::NonZero;
7475

7576
pub use check::{check_abi, check_custom_abi};
@@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
8687
use rustc_middle::ty::error::{ExpectedFound, TypeError};
8788
use rustc_middle::ty::print::with_types_for_signature;
8889
use rustc_middle::ty::{
89-
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
90+
self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
9091
};
9192
use rustc_middle::{bug, span_bug};
9293
use rustc_session::parse::feature_err;
@@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
335336
assoc: ty::AssocItem,
336337
) -> (String, String) {
337338
let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
339+
let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
338340
let mut projections = vec![];
339341
for (predicate, _) in predicates {
340342
debug!("predicate {:?}", predicate);
@@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
351353
ty::ClauseKind::Projection(projection_pred) => {
352354
projections.push(bound_predicate.rebind(projection_pred));
353355
}
356+
ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
357+
regions.entry(a).or_default().push(b);
358+
}
354359
_ => {}
355360
}
356361
}
357362

358363
let mut where_clauses = vec![];
359364
let generics = tcx.generics_of(assoc.def_id);
360-
let types_str = generics
365+
let params = generics
361366
.own_params
362367
.iter()
363-
.filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
364-
.map(|p| {
365-
// we just checked that it's a type, so the unwrap can't fail
366-
let ty = tcx.mk_param_from_def(p).as_type().unwrap();
367-
if let Some(bounds) = types.get(&ty) {
368+
.filter(|p| !p.kind.is_synthetic())
369+
.map(|p| match tcx.mk_param_from_def(p).kind() {
370+
ty::GenericArgKind::Type(ty) => {
371+
let bounds =
372+
types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
368373
let mut bounds_str = vec![];
369374
for bound in bounds.iter().copied() {
370375
let mut projections_str = vec![];
@@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
377382
projections_str.push(format!("{} = {}", name, p.term));
378383
}
379384
}
380-
let bound_def_path = tcx.def_path_str(bound);
385+
let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
386+
String::from("?Sized")
387+
} else {
388+
tcx.def_path_str(bound)
389+
};
381390
if projections_str.is_empty() {
382391
where_clauses.push(format!("{}: {}", ty, bound_def_path));
383392
} else {
@@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
393402
} else {
394403
format!("{}: {}", ty, bounds_str.join(" + "))
395404
}
396-
} else {
397-
ty.to_string()
405+
}
406+
ty::GenericArgKind::Const(ct) => {
407+
format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
408+
}
409+
ty::GenericArgKind::Lifetime(region) => {
410+
if let Some(v) = regions.get(&region)
411+
&& !v.is_empty()
412+
{
413+
format!(
414+
"{region}: {}",
415+
v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
416+
)
417+
} else {
418+
region.to_string()
419+
}
398420
}
399421
})
400422
.collect::<Vec<_>>();
@@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
409431
}
410432

411433
let generics =
412-
if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
434+
if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };
413435

414436
let where_clauses = if where_clauses.is_empty() {
415437
"".to_string()

library/coretests/tests/ascii.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,10 @@ fn test_escape_ascii_iter() {
505505
let _ = it.advance_back_by(4);
506506
assert_eq!(it.to_string(), r#"fastpath\xffremainder"#);
507507
}
508+
509+
#[test]
510+
fn test_invalid_u8() {
511+
for c in 128..=255 {
512+
assert_eq!(core::ascii::Char::from_u8(c), None);
513+
}
514+
}

src/bootstrap/src/core/config/config.rs

Lines changed: 98 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,13 +1853,7 @@ fn load_toml_config(
18531853
} else {
18541854
toml_path.clone()
18551855
});
1856-
(
1857-
get_toml(&toml_path).unwrap_or_else(|e| {
1858-
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
1859-
exit!(2);
1860-
}),
1861-
path,
1862-
)
1856+
(get_toml(&toml_path).unwrap_or_else(|e| bad_config(&toml_path, e)), path)
18631857
} else {
18641858
(TomlConfig::default(), None)
18651859
}
@@ -1892,10 +1886,8 @@ fn postprocess_toml(
18921886
.unwrap()
18931887
.join(include_path);
18941888

1895-
let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
1896-
eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
1897-
exit!(2);
1898-
});
1889+
let included_toml =
1890+
get_toml(&include_path).unwrap_or_else(|e| bad_config(&include_path, e));
18991891
toml.merge(
19001892
Some(include_path),
19011893
&mut Default::default(),
@@ -2398,3 +2390,98 @@ pub(crate) fn read_file_by_commit<'a>(
23982390
git.arg("show").arg(format!("{commit}:{}", file.to_str().unwrap()));
23992391
git.run_capture_stdout(dwn_ctx.exec_ctx).stdout()
24002392
}
2393+
2394+
fn bad_config(toml_path: &Path, e: toml::de::Error) -> ! {
2395+
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
2396+
let e_s = e.to_string();
2397+
if e_s.contains("unknown field")
2398+
&& let Some(field_name) = e_s.split("`").nth(1)
2399+
&& let sections = find_correct_section_for_field(field_name)
2400+
&& !sections.is_empty()
2401+
{
2402+
if sections.len() == 1 {
2403+
match sections[0] {
2404+
WouldBeValidFor::TopLevel { is_section } => {
2405+
if is_section {
2406+
eprintln!(
2407+
"hint: section name `{field_name}` used as a key within a section"
2408+
);
2409+
} else {
2410+
eprintln!("hint: try using `{field_name}` as a top level key");
2411+
}
2412+
}
2413+
WouldBeValidFor::Section(section) => {
2414+
eprintln!("hint: try moving `{field_name}` to the `{section}` section")
2415+
}
2416+
}
2417+
} else {
2418+
eprintln!(
2419+
"hint: `{field_name}` would be valid {}",
2420+
join_oxford_comma(sections.iter(), "or"),
2421+
);
2422+
}
2423+
}
2424+
2425+
exit!(2);
2426+
}
2427+
2428+
#[derive(Copy, Clone, Debug)]
2429+
enum WouldBeValidFor {
2430+
TopLevel { is_section: bool },
2431+
Section(&'static str),
2432+
}
2433+
2434+
fn join_oxford_comma(
2435+
mut parts: impl ExactSizeIterator<Item = impl std::fmt::Display>,
2436+
conj: &str,
2437+
) -> String {
2438+
use std::fmt::Write;
2439+
let mut out = String::new();
2440+
2441+
assert!(parts.len() > 1);
2442+
while let Some(part) = parts.next() {
2443+
if parts.len() == 0 {
2444+
write!(&mut out, "{conj} {part}")
2445+
} else {
2446+
write!(&mut out, "{part}, ")
2447+
}
2448+
.unwrap();
2449+
}
2450+
out
2451+
}
2452+
2453+
impl std::fmt::Display for WouldBeValidFor {
2454+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2455+
match self {
2456+
Self::TopLevel { .. } => write!(f, "at top level"),
2457+
Self::Section(section_name) => write!(f, "in section `{section_name}`"),
2458+
}
2459+
}
2460+
}
2461+
2462+
fn find_correct_section_for_field(field_name: &str) -> Vec<WouldBeValidFor> {
2463+
let sections = ["build", "install", "llvm", "gcc", "rust", "dist"];
2464+
sections
2465+
.iter()
2466+
.map(Some)
2467+
.chain([None])
2468+
.filter_map(|section_name| {
2469+
let dummy_config_str = if let Some(section_name) = section_name {
2470+
format!("{section_name}.{field_name} = 0\n")
2471+
} else {
2472+
format!("{field_name} = 0\n")
2473+
};
2474+
let is_unknown_field = toml::from_str::<toml::Value>(&dummy_config_str)
2475+
.and_then(TomlConfig::deserialize)
2476+
.err()
2477+
.is_some_and(|e| e.to_string().contains("unknown field"));
2478+
if is_unknown_field {
2479+
None
2480+
} else {
2481+
Some(section_name.copied().map(WouldBeValidFor::Section).unwrap_or_else(|| {
2482+
WouldBeValidFor::TopLevel { is_section: sections.contains(&field_name) }
2483+
}))
2484+
}
2485+
})
2486+
.collect()
2487+
}

src/tools/compiletest/src/common.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ impl CodegenBackend {
203203
Self::Llvm => "llvm",
204204
}
205205
}
206+
207+
pub fn is_llvm(self) -> bool {
208+
matches!(self, Self::Llvm)
209+
}
206210
}
207211

208212
/// Configuration for `compiletest` *per invocation*.

src/tools/compiletest/src/directives/needs.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ pub(super) fn handle_needs(
8181
},
8282
Need {
8383
name: "needs-enzyme",
84-
condition: config.has_enzyme,
85-
ignore_reason: "ignored when LLVM Enzyme is disabled",
84+
condition: config.has_enzyme && config.default_codegen_backend.is_llvm(),
85+
ignore_reason: "ignored when LLVM Enzyme is disabled or LLVM is not the default codegen backend",
8686
},
8787
Need {
8888
name: "needs-run-enabled",
@@ -161,8 +161,8 @@ pub(super) fn handle_needs(
161161
},
162162
Need {
163163
name: "needs-llvm-zstd",
164-
condition: cache.llvm_zstd,
165-
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
164+
condition: cache.llvm_zstd && config.default_codegen_backend.is_llvm(),
165+
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression or LLVM is not the default codegen backend",
166166
},
167167
Need {
168168
name: "needs-rustc-debug-assertions",
@@ -279,7 +279,10 @@ pub(super) fn handle_needs(
279279

280280
// Handled elsewhere.
281281
if name == "needs-llvm-components" {
282-
return IgnoreDecision::Continue;
282+
if config.default_codegen_backend.is_llvm() {
283+
return IgnoreDecision::Continue;
284+
}
285+
return IgnoreDecision::Ignore { reason: "LLVM specific test".into() };
283286
}
284287

285288
let mut found_valid = false;

tests/ui/associated-types/associated-types-for-unimpl-trait.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ trait Get {
88
}
99

1010
trait Other {
11-
fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get, Self: Get {}
11+
fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get {}
1212
//~^ ERROR the trait bound `Self: Get` is not satisfied
1313
//~| ERROR the trait bound `Self: Get` is not satisfied
1414
}

tests/ui/lifetimes/issue-105507.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl<T> ProjectedMyTrait for T
3131

3232
fn require_trait<T: MyTrait>(_: T) {}
3333

34-
fn foo<T : MyTrait + 'static + 'static, U : MyTrait + 'static + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
34+
fn foo<T : MyTrait + 'static, U : MyTrait + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
3535
//~^ HELP consider restricting the type parameter to the `'static` lifetime
3636
//~| HELP consider restricting the type parameter to the `'static` lifetime
3737
require_trait(wrap);

tests/ui/parser/expr-as-stmt.fixed

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn asteroids() -> impl FnOnce() -> bool {
6666

6767
// https://github.com/rust-lang/rust/issues/105179
6868
fn r#match() -> i32 {
69-
((match () { () => 1 })) + match () { () => 1 } //~ ERROR expected expression, found `+`
69+
(match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
7070
//~^ ERROR mismatched types
7171
}
7272

@@ -82,7 +82,7 @@ fn matches() -> bool {
8282
(match () { _ => true }) && match () { _ => true }; //~ ERROR mismatched types
8383
//~^ ERROR expected `;`, found keyword `match`
8484
(match () { _ => true }) && true; //~ ERROR mismatched types
85-
((match () { _ => true })) && true //~ ERROR mismatched types
85+
(match () { _ => true }) && true //~ ERROR mismatched types
8686
//~^ ERROR mismatched types
8787
}
8888
fn main() {}

tests/ui/suggestions/apitit-unimplemented-method.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ extern crate dep;
44
use dep::*;
55

66
struct Local;
7+
78
impl Trait for Local {}
89
//~^ ERROR not all trait items implemented
910
//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
10-
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
11+
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
12+
//~| HELP implement the missing item: `fn baz<const N: usize>() { todo!() }`
13+
//~| HELP implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
1114

1215
fn main() {}

0 commit comments

Comments
 (0)