diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8df211b0840ec..aa67ca3a60397 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1027,6 +1027,7 @@ symbols! { format_args_capture, format_args_macro, format_args_nl, + format_args_nl_macro, format_argument, format_arguments, format_count, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 78f9287b407b3..828db296ad342 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -21,7 +21,7 @@ use rustc_infer::traits::{ }; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{ErrorGuaranteed, ExpnKind, Span}; +use rustc_span::{ErrorGuaranteed, ExpnKind, Span, sym}; use tracing::{info, instrument}; pub use self::overflow::*; @@ -136,6 +136,15 @@ pub enum DefIdOrName { Name(&'static str), } +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +enum ErrorSortKey { + SubtypeFormat(usize, usize), + OtherKind, + ClauseTraitSized, + Coerce, + ClauseWellFormed, +} + impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub fn report_fulfillment_errors( &self, @@ -162,15 +171,36 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics // with more relevant type information and hide redundant E0282 errors. - errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) - if self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) => - { - 1 + errors.sort_by_key(|e| { + let span = e.obligation.cause.span; + let outer_expn_data = span.ctxt().outer_expn_data(); + let source_span = outer_expn_data.call_site.source_callsite(); + let source_map = self.tcx.sess.source_map(); + + match e.obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Subtype(_) + if let Some(def_id) = outer_expn_data.macro_def_id + && let (Some(span_file), row, col, ..) = + source_map.span_to_location_info(span) + && let (Some(source_file), ..) = + source_map.span_to_location_info(source_span) + && (self.tcx.is_diagnostic_item(sym::format_args_nl_macro, def_id) + || self.tcx.is_diagnostic_item(sym::format_args_macro, def_id)) + && span_file.src_hash == source_file.src_hash => + { + ErrorSortKey::SubtypeFormat(row, col) + } + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) + if self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) => + { + ErrorSortKey::ClauseTraitSized + } + ty::PredicateKind::Coerce(_) => ErrorSortKey::Coerce, + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => { + ErrorSortKey::ClauseWellFormed + } + _ => ErrorSortKey::OtherKind, } - ty::PredicateKind::Coerce(_) => 2, - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3, - _ => 0, }); for (index, error) in errors.iter().enumerate() { diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7dc8c060cd5bc..e2beb525697c3 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1027,6 +1027,7 @@ pub(crate) mod builtin { reason = "`format_args_nl` is only for internal \ language use and is subject to change" )] + #[rustc_diagnostic_item = "format_args_nl_macro"] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] #[macro_export] diff --git a/tests/ui/errors/span-format_args-issue-140578.rs b/tests/ui/errors/span-format_args-issue-140578.rs new file mode 100644 index 0000000000000..8c91ded833753 --- /dev/null +++ b/tests/ui/errors/span-format_args-issue-140578.rs @@ -0,0 +1,32 @@ +fn check_format_args() { + print!("{:?} {a} {a:?}", [], a = 1 + 1); + //~^ ERROR type annotations needed +} + +fn check_format_args_nl() { + println!("{:?} {a} {a:?}", [], a = 1 + 1); + //~^ ERROR type annotations needed +} + +fn check_multi1() { + println!("{:?} {:?} {a} {a:?}", [], [], a = 1 + 1); + //~^ ERROR type annotations needed +} + +fn check_multi2() { + println!("{:?} {:?} {a} {a:?} {b:?}", [], [], a = 1 + 1, b = []); + //~^ ERROR type annotations needed +} + +fn check_unformatted() { + println!(" + {:?} {:?} +{a} +{a:?}", + [], + //~^ ERROR type annotations needed + [], +a = 1 + 1); +} + +fn main() {} diff --git a/tests/ui/errors/span-format_args-issue-140578.stderr b/tests/ui/errors/span-format_args-issue-140578.stderr new file mode 100644 index 0000000000000..6a273e5cd515c --- /dev/null +++ b/tests/ui/errors/span-format_args-issue-140578.stderr @@ -0,0 +1,43 @@ +error[E0282]: type annotations needed + --> $DIR/span-format_args-issue-140578.rs:2:28 + | +LL | print!("{:?} {a} {a:?}", [], a = 1 + 1); + | ^^ cannot infer type + | + = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the macro `print` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0282]: type annotations needed + --> $DIR/span-format_args-issue-140578.rs:7:30 + | +LL | println!("{:?} {a} {a:?}", [], a = 1 + 1); + | ^^ cannot infer type + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0282]: type annotations needed + --> $DIR/span-format_args-issue-140578.rs:12:35 + | +LL | println!("{:?} {:?} {a} {a:?}", [], [], a = 1 + 1); + | ^^ cannot infer type + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0282]: type annotations needed + --> $DIR/span-format_args-issue-140578.rs:17:41 + | +LL | println!("{:?} {:?} {a} {a:?} {b:?}", [], [], a = 1 + 1, b = []); + | ^^ cannot infer type + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0282]: type annotations needed + --> $DIR/span-format_args-issue-140578.rs:26:9 + | +LL | [], + | ^^ cannot infer type + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0282`.