Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4817,9 +4817,9 @@ dependencies = [

[[package]]
name = "rustfix"
version = "0.8.1"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a"
dependencies = [
"serde",
"serde_json",
Expand Down
44 changes: 33 additions & 11 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub mod intrinsic;
mod region;
pub mod wfcheck;

use std::borrow::Cow;
use std::num::NonZero;

pub use check::{check_abi, check_custom_abi};
Expand All @@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::print::with_types_for_signature;
use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
};
use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
Expand Down Expand Up @@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
assoc: ty::AssocItem,
) -> (String, String) {
let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
let mut projections = vec![];
for (predicate, _) in predicates {
debug!("predicate {:?}", predicate);
Expand All @@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
ty::ClauseKind::Projection(projection_pred) => {
projections.push(bound_predicate.rebind(projection_pred));
}
ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
regions.entry(a).or_default().push(b);
}
_ => {}
}
}

let mut where_clauses = vec![];
let generics = tcx.generics_of(assoc.def_id);
let types_str = generics
let params = generics
.own_params
.iter()
.filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
.map(|p| {
// we just checked that it's a type, so the unwrap can't fail
let ty = tcx.mk_param_from_def(p).as_type().unwrap();
if let Some(bounds) = types.get(&ty) {
.filter(|p| !p.kind.is_synthetic())
.map(|p| match tcx.mk_param_from_def(p).kind() {
ty::GenericArgKind::Type(ty) => {
let bounds =
types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
let mut bounds_str = vec![];
for bound in bounds.iter().copied() {
let mut projections_str = vec![];
Expand All @@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
projections_str.push(format!("{} = {}", name, p.term));
}
}
let bound_def_path = tcx.def_path_str(bound);
let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
String::from("?Sized")
} else {
tcx.def_path_str(bound)
};
if projections_str.is_empty() {
where_clauses.push(format!("{}: {}", ty, bound_def_path));
} else {
Expand All @@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
} else {
format!("{}: {}", ty, bounds_str.join(" + "))
}
} else {
ty.to_string()
}
ty::GenericArgKind::Const(ct) => {
format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
}
ty::GenericArgKind::Lifetime(region) => {
if let Some(v) = regions.get(&region)
&& !v.is_empty()
{
format!(
"{region}: {}",
v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
)
} else {
region.to_string()
}
}
})
.collect::<Vec<_>>();
Expand All @@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
}

let generics =
if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };

let where_clauses = if where_clauses.is_empty() {
"".to_string()
Expand Down
7 changes: 7 additions & 0 deletions library/coretests/tests/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,3 +505,10 @@ fn test_escape_ascii_iter() {
let _ = it.advance_back_by(4);
assert_eq!(it.to_string(), r#"fastpath\xffremainder"#);
}

#[test]
fn test_invalid_u8() {
for c in 128..=255 {
assert_eq!(core::ascii::Char::from_u8(c), None);
}
}
109 changes: 98 additions & 11 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1853,13 +1853,7 @@ fn load_toml_config(
} else {
toml_path.clone()
});
(
get_toml(&toml_path).unwrap_or_else(|e| {
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
exit!(2);
}),
path,
)
(get_toml(&toml_path).unwrap_or_else(|e| bad_config(&toml_path, e)), path)
} else {
(TomlConfig::default(), None)
}
Expand Down Expand Up @@ -1892,10 +1886,8 @@ fn postprocess_toml(
.unwrap()
.join(include_path);

let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
exit!(2);
});
let included_toml =
get_toml(&include_path).unwrap_or_else(|e| bad_config(&include_path, e));
toml.merge(
Some(include_path),
&mut Default::default(),
Expand Down Expand Up @@ -2398,3 +2390,98 @@ pub(crate) fn read_file_by_commit<'a>(
git.arg("show").arg(format!("{commit}:{}", file.to_str().unwrap()));
git.run_capture_stdout(dwn_ctx.exec_ctx).stdout()
}

fn bad_config(toml_path: &Path, e: toml::de::Error) -> ! {
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
let e_s = e.to_string();
if e_s.contains("unknown field")
&& let Some(field_name) = e_s.split("`").nth(1)
&& let sections = find_correct_section_for_field(field_name)
&& !sections.is_empty()
{
if sections.len() == 1 {
match sections[0] {
WouldBeValidFor::TopLevel { is_section } => {
if is_section {
eprintln!(
"hint: section name `{field_name}` used as a key within a section"
);
} else {
eprintln!("hint: try using `{field_name}` as a top level key");
}
}
WouldBeValidFor::Section(section) => {
eprintln!("hint: try moving `{field_name}` to the `{section}` section")
}
}
} else {
eprintln!(
"hint: `{field_name}` would be valid {}",
join_oxford_comma(sections.iter(), "or"),
);
}
}

exit!(2);
}

#[derive(Copy, Clone, Debug)]
enum WouldBeValidFor {
TopLevel { is_section: bool },
Section(&'static str),
}

fn join_oxford_comma(
mut parts: impl ExactSizeIterator<Item = impl std::fmt::Display>,
conj: &str,
) -> String {
use std::fmt::Write;
let mut out = String::new();

assert!(parts.len() > 1);
while let Some(part) = parts.next() {
if parts.len() == 0 {
write!(&mut out, "{conj} {part}")
} else {
write!(&mut out, "{part}, ")
}
.unwrap();
}
out
}

impl std::fmt::Display for WouldBeValidFor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::TopLevel { .. } => write!(f, "at top level"),
Self::Section(section_name) => write!(f, "in section `{section_name}`"),
}
}
}

fn find_correct_section_for_field(field_name: &str) -> Vec<WouldBeValidFor> {
let sections = ["build", "install", "llvm", "gcc", "rust", "dist"];
sections
.iter()
.map(Some)
.chain([None])
.filter_map(|section_name| {
let dummy_config_str = if let Some(section_name) = section_name {
format!("{section_name}.{field_name} = 0\n")
} else {
format!("{field_name} = 0\n")
};
let is_unknown_field = toml::from_str::<toml::Value>(&dummy_config_str)
.and_then(TomlConfig::deserialize)
.err()
.is_some_and(|e| e.to_string().contains("unknown field"));
if is_unknown_field {
None
} else {
Some(section_name.copied().map(WouldBeValidFor::Section).unwrap_or_else(|| {
WouldBeValidFor::TopLevel { is_section: sections.contains(&field_name) }
}))
}
})
.collect()
}
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ impl CodegenBackend {
Self::Llvm => "llvm",
}
}

pub fn is_llvm(self) -> bool {
matches!(self, Self::Llvm)
}
}

/// Configuration for `compiletest` *per invocation*.
Expand Down
13 changes: 8 additions & 5 deletions src/tools/compiletest/src/directives/needs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ pub(super) fn handle_needs(
},
Need {
name: "needs-enzyme",
condition: config.has_enzyme,
ignore_reason: "ignored when LLVM Enzyme is disabled",
condition: config.has_enzyme && config.default_codegen_backend.is_llvm(),
ignore_reason: "ignored when LLVM Enzyme is disabled or LLVM is not the default codegen backend",
},
Need {
name: "needs-run-enabled",
Expand Down Expand Up @@ -161,8 +161,8 @@ pub(super) fn handle_needs(
},
Need {
name: "needs-llvm-zstd",
condition: cache.llvm_zstd,
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
condition: cache.llvm_zstd && config.default_codegen_backend.is_llvm(),
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression or LLVM is not the default codegen backend",
},
Need {
name: "needs-rustc-debug-assertions",
Expand Down Expand Up @@ -279,7 +279,10 @@ pub(super) fn handle_needs(

// Handled elsewhere.
if name == "needs-llvm-components" {
return IgnoreDecision::Continue;
if config.default_codegen_backend.is_llvm() {
return IgnoreDecision::Continue;
}
return IgnoreDecision::Ignore { reason: "LLVM specific test".into() };
}

let mut found_valid = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait Get {
}

trait Other {
fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get, Self: Get {}
fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get {}
//~^ ERROR the trait bound `Self: Get` is not satisfied
//~| ERROR the trait bound `Self: Get` is not satisfied
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lifetimes/issue-105507.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<T> ProjectedMyTrait for T

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

fn foo<T : MyTrait + 'static + 'static, U : MyTrait + 'static + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
fn foo<T : MyTrait + 'static, U : MyTrait + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
//~^ HELP consider restricting the type parameter to the `'static` lifetime
//~| HELP consider restricting the type parameter to the `'static` lifetime
require_trait(wrap);
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/parser/expr-as-stmt.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fn asteroids() -> impl FnOnce() -> bool {

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

Expand All @@ -82,7 +82,7 @@ fn matches() -> bool {
(match () { _ => true }) && match () { _ => true }; //~ ERROR mismatched types
//~^ ERROR expected `;`, found keyword `match`
(match () { _ => true }) && true; //~ ERROR mismatched types
((match () { _ => true })) && true //~ ERROR mismatched types
(match () { _ => true }) && true //~ ERROR mismatched types
//~^ ERROR mismatched types
}
fn main() {}
5 changes: 4 additions & 1 deletion tests/ui/suggestions/apitit-unimplemented-method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ extern crate dep;
use dep::*;

struct Local;

impl Trait for Local {}
//~^ ERROR not all trait items implemented
//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
//~| HELP implement the missing item: `fn baz<const N: usize>() { todo!() }`
//~| HELP implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`

fn main() {}
10 changes: 6 additions & 4 deletions tests/ui/suggestions/apitit-unimplemented-method.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
error[E0046]: not all trait items implemented, missing: `foo`, `bar`
--> $DIR/apitit-unimplemented-method.rs:7:1
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `quux`
--> $DIR/apitit-unimplemented-method.rs:8:1
|
LL | impl Trait for Local {}
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `quux` in implementation
|
= help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
= help: implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
= help: implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
= help: implement the missing item: `fn baz<const N: usize>() { todo!() }`
= help: implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`

error: aborting due to 1 previous error

Expand Down
14 changes: 13 additions & 1 deletion tests/ui/suggestions/auxiliary/dep.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
#![feature(sized_hierarchy)]

use std::marker::MetaSized;

pub struct Foo<T> {
inner: T,
}

pub trait Trait {
fn foo(_: impl Sized);
fn bar<T>(_: impl Sized);
fn bar<T>(_: impl Sized)
where
Foo<T>: MetaSized;
fn baz<'a, const N: usize>();
fn quux<'a: 'b, 'b, T: ?Sized>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone> {
}

#[derive(Debug, Copy, Clone)]
pub struct AABB<K: Debug + std::marker::Copy + std::marker::Copy + std::marker::Copy + std::marker::Copy> {
pub struct AABB<K: Debug + std::marker::Copy> {
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
//~^ ERROR the trait bound `K: Copy` is not satisfied
//~| ERROR the trait bound `K: Copy` is not satisfied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone>{
}

#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type
pub struct AABB<K: Copy + Debug + std::fmt::Debug + std::fmt::Debug + std::fmt::Debug>{
pub struct AABB<K: Copy + Debug + std::fmt::Debug>{
pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug`
//~^ ERROR `K` doesn't implement `Debug`
pub size: Vector2<K> //~ ERROR `K` doesn't implement `Debug`
Expand Down
Loading
Loading