diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 72839643b4dc3..060fd74c1db21 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -12,7 +12,7 @@ use rustc_ast::{AttrStyle, MetaItemLit, Safety}; use rustc_attr_ir::target::Target; use rustc_attr_ir::{AttrPath, Attribute, AttributeKind}; use rustc_data_structures::sync::{DynSend, DynSync}; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; +use rustc_errors::{Diag, DiagCtxtHandle, DiagLocation, Diagnostic, Level, MultiSpan}; use rustc_feature::AttributeStability; use rustc_lint_defs::builtin::UNUSED_ATTRIBUTES; use rustc_lint_defs::{Lint, LintId}; @@ -408,6 +408,7 @@ pub struct AcceptContext<'f, 'sess> { } impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { + #[track_caller] pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed { self.cx.emit_err(diag) } @@ -415,15 +416,21 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing /// must be delayed until after HIR is built. This method will take care of the details of /// that. + #[track_caller] pub(crate) fn emit_lint( &mut self, lint: &'static Lint, diagnostic: impl for<'x> Diagnostic<'x> + DynSend + DynSync + 'static, span: impl Into, ) { + let emitted_at = DiagLocation::caller(); self.emit_lint_inner( lint, - EmitAttribute(Box::new(move |dcx, level, _| diagnostic.into_diag(dcx, level))), + EmitAttribute(Box::new(move |dcx, level, _| { + let mut diag = diagnostic.into_diag(dcx, level); + diag.emitted_at = emitted_at; + diag + })), span, ); } @@ -497,6 +504,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// The provided span is used as a fallback for diagnostic generation in case `arg` does not /// contain any. It should be the span of the node that contains `arg`. + #[track_caller] pub(crate) fn expect_single_element_list<'arg>( &mut self, arg: &'arg ArgParser, @@ -529,6 +537,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_list<'arg>( &mut self, args: &'arg ArgParser, @@ -550,6 +559,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_single<'arg>( &mut self, list: &'arg MetaItemListParser, @@ -589,6 +599,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_name_value<'arg, Arg>( &mut self, arg: &'arg Arg, @@ -609,6 +620,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<()> { if let Err(span) = arg.as_no_args() { self.adcx().expected_no_args(span); @@ -631,6 +643,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_string_literal<'arg, Arg>(&mut self, arg: &'arg Arg) -> Option where Arg: ExpectStringLiteral, @@ -644,6 +657,7 @@ pub(crate) trait ExpectNameValue { where Self: 'a; + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -655,6 +669,7 @@ pub(crate) trait ExpectNameValue { impl ExpectNameValue for MetaItemOrLitParser { type Output<'a> = (Ident, &'a NameValueParser); + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -673,6 +688,7 @@ impl ExpectNameValue for MetaItemOrLitParser { impl ExpectNameValue for MetaItemParser { type Output<'a> = (Ident, &'a NameValueParser); + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -697,6 +713,7 @@ impl ExpectNameValue for MetaItemParser { impl ExpectNameValue for ArgParser { type Output<'a> = &'a NameValueParser; + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -713,11 +730,13 @@ impl ExpectNameValue for ArgParser { } pub(crate) trait ExpectStringLiteral { + #[track_caller] fn expect_string_literal<'f, 'sess>(&self, cx: &mut AcceptContext<'f, 'sess>) -> Option; } impl ExpectStringLiteral for NameValueParser { + #[track_caller] fn expect_string_literal<'f, 'sess>( &self, cx: &mut AcceptContext<'f, 'sess>, @@ -731,6 +750,7 @@ impl ExpectStringLiteral for NameValueParser { } impl ExpectStringLiteral for MetaItemOrLitParser { + #[track_caller] fn expect_string_literal<'f, 'sess>( &self, cx: &mut AcceptContext<'f, 'sess>, @@ -893,6 +913,7 @@ pub enum ShouldEmit { } impl ShouldEmit { + #[track_caller] pub(crate) fn emit_err(self, diag: Diag<'_>) -> ErrorGuaranteed { match self { ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit_err(), @@ -912,6 +933,7 @@ pub(crate) struct AttributeDiagnosticContext<'a, 'f, 'sess> { } impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { + #[track_caller] fn emit_parse_error( &mut self, mut span: Span, @@ -950,6 +972,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// Helpers that can be used to generate errors during attribute parsing. impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { + #[track_caller] pub(crate) fn expected_integer_literal_in_range( &mut self, span: Span, @@ -964,6 +987,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// The provided span is used as a fallback in case `args` does not contain any. It should be /// the span of the node that contains `args`. + #[track_caller] pub(crate) fn expected_list(&mut self, span: Span, args: &ArgParser) -> ErrorGuaranteed { let span = match args { ArgParser::NoArgs => span, @@ -973,6 +997,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList) } + #[track_caller] pub(crate) fn expected_list_with_num_args_or_more( &mut self, args: usize, @@ -984,45 +1009,54 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { ) } + #[track_caller] pub(crate) fn expected_list_or_no_args(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs) } + #[track_caller] pub(crate) fn expected_nv_or_no_args(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueOrNoArgs) } + #[track_caller] pub(crate) fn expected_non_empty_string_literal(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNonEmptyStringLiteral) } + #[track_caller] pub(crate) fn expected_no_args(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNoArgs) } /// Emit an error that a `name` was expected here + #[track_caller] pub(crate) fn expected_identifier(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIdentifier) } /// Emit an error that a `name = value` pair was expected at this span. The symbol can be given for /// a nicer error message talking about the specific name that was found lacking a value. + #[track_caller] fn expected_name_value(&mut self, span: Span, name: Option) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValue(name)) } /// Emit an error that a `name = value` argument is missing in a list of name-value pairs. + #[track_caller] pub(crate) fn missing_name_value(&mut self, span: Span, name: Symbol) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::MissingNameValue(name)) } /// Emit an error that a `name = value` pair was found where that name was already seen. + #[track_caller] pub(crate) fn duplicate_key(&mut self, span: Span, key: Symbol) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key)) } /// An error that should be emitted when a [`MetaItemOrLitParser`] /// was expected *not* to be a literal, but instead a meta item. + #[track_caller] pub(crate) fn expected_not_literal(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNotLiteral) } @@ -1031,6 +1065,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// The `provided_arguments` argument allows distinguishing between "expected an argument here" /// (when zero arguments are provided) and "expect a single argument here" (when two or more /// arguments are provided). + #[track_caller] pub(crate) fn expected_single_argument( &mut self, span: Span, @@ -1045,11 +1080,13 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { self.emit_parse_error(span, reason) } + #[track_caller] pub(crate) fn expected_at_least_one_argument(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedAtLeastOneArgument) } /// Produces an error along the lines of `expected one of [foo, meow]` + #[track_caller] pub(crate) fn expected_specific_argument( &mut self, span: Span, @@ -1067,6 +1104,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// Produces an error along the lines of `expected one of [foo, meow] as an argument`. /// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument). + #[track_caller] pub(crate) fn expected_specific_argument_and_list( &mut self, span: Span, @@ -1083,6 +1121,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { } /// produces an error along the lines of `expected one of ["foo", "meow"]` + #[track_caller] pub(crate) fn expected_specific_argument_strings( &mut self, span: Span, diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 95412c34be371..4ce284a0a9d5a 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -304,6 +304,7 @@ impl<'sess> AttributeParser<'sess> { self.sess().dcx() } + #[track_caller] pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed { self.should_emit.emit_err(self.sess.dcx().create_err(diag)) } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index d964faa30b1f8..695eca6225858 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,6 +27,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] +#![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![cfg_attr(doc, feature(intra_doc_pointers))] #![feature(allocator_ext)] #![feature(associated_type_defaults)] @@ -34,7 +35,6 @@ #![feature(const_default)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] -#![feature(debug_closure_helpers)] #![feature(decl_macro)] #![feature(default_field_values)] #![feature(deref_patterns)] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 3655d4594aa38..8822ffee65c29 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp::min; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diag, DiagLocation, Diagnostic, EmissionOverride, MultiSpan}; +use rustc_errors::{Diag, Diagnostic, EmissionOverride, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_lint_defs::{ EditionFcw, FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, @@ -494,8 +494,6 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( } else { Diag::new(sess.dcx(), err_level, "") }; - // FIXME: Find a nicer way to expose the `DiagLocation` - err.emitted_at = DiagLocation::caller(); if let Some(span) = span && err.span.primary_span().is_none() diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 8a73215351aea..edd280743e437 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,8 +1,8 @@ //! The main parser interface. // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![cfg_attr(test, feature(iter_order_by))] -#![feature(debug_closure_helpers)] #![feature(default_field_values)] #![feature(deref_patterns)] #![feature(iter_intersperse)] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 6a44f9ef5374e..20ce752dd7c41 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -187,8 +187,6 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Bar { @@ -211,11 +209,12 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// r#"Bar { bar: 0x0000000a, another: "Hello World" }"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] + pub fn field_with( + &mut self, + name: &str, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.field(name, &DebugOnce(Cell::new(Some(value_fmt)))) } @@ -408,8 +407,6 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(i32, String); @@ -429,11 +426,11 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// r#"Foo(0x0000000a, "Hello World")"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn field_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] + pub fn field_with( + &mut self, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.field(&DebugOnce(Cell::new(Some(value_fmt)))) } @@ -552,10 +549,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { self.has_fields = true; } - fn entry_with(&mut self, entry_fmt: F) - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + fn entry_with(&mut self, entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) { self.entry(&DebugOnce(Cell::new(Some(entry_fmt)))); } @@ -639,8 +633,6 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec, Vec); @@ -660,11 +652,11 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{[10, 11], {12, 13}}", /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] + pub fn entry_with( + &mut self, + entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.inner.entry_with(entry_fmt); self } @@ -856,8 +848,6 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec, Vec); @@ -877,11 +867,11 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[[10, 11], {12, 13}]", /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] + pub fn entry_with( + &mut self, + entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.inner.entry_with(entry_fmt); self } @@ -1075,8 +1065,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// @@ -1136,11 +1127,15 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// This method is equivalent to [`DebugMap::key`], but formats the /// key using a provided closure rather than by calling [`Debug::fmt`]. /// + /// # Panics + /// + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. + /// /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); @@ -1163,11 +1158,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{entry A: 0x0000000a, entry B: 0x0000000b}"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn key_with(&mut self, key_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] + pub fn key_with( + &mut self, + key_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.key(&DebugOnce(Cell::new(Some(key_fmt)))) } @@ -1179,8 +1174,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// @@ -1229,11 +1225,15 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// This method is equivalent to [`DebugMap::value`], but formats the /// value using a provided closure rather than by calling [`Debug::fmt`]. /// + /// # Panics + /// + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. + /// /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); @@ -1256,11 +1256,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{entry A: 0x0000000a, entry B: 0x0000000b}"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn value_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] + pub fn value_with( + &mut self, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.value(&DebugOnce(Cell::new(Some(value_fmt)))) } @@ -1359,8 +1359,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 9b623d1c5d25b..1fdb0c820d662 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -47,7 +47,6 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] -#![feature(debug_closure_helpers)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index e063b3d6cc632..922e965bbb06e 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, Level, MultiSpan}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagLocation, DiagMessage, Diagnostic, Level, MultiSpan}; #[cfg(debug_assertions)] use rustc_errors::{SubstitutionPart, Suggestions}; use rustc_hir::HirId; @@ -251,12 +251,15 @@ where } let sp = sp.into(); + let emitted_at = DiagLocation::caller(); + #[expect(clippy::disallowed_methods)] cx.emit_span_lint( lint, sp.clone(), ClippyDiag(|diag: &mut Diag<'_>| { diag.primary_message(msg); + diag.emitted_at = emitted_at; diag.span(sp); f(diag); docs_link(diag, lint); @@ -329,6 +332,8 @@ pub fn span_lint_hir_and_then( msg: impl Into, f: impl FnOnce(&mut Diag<'_>), ) { + let emitted_at = DiagLocation::caller(); + #[expect(clippy::disallowed_methods)] cx.tcx.emit_node_span_lint( lint, @@ -336,6 +341,7 @@ pub fn span_lint_hir_and_then( sp, rustc_errors::DiagDecorator(|diag| { diag.primary_message(msg); + diag.emitted_at = emitted_at; f(diag); docs_link(diag, lint); diff --git a/tests/ui/track-diagnostics/track8.rs b/tests/ui/track-diagnostics/track8.rs new file mode 100644 index 0000000000000..6690d8fca63df --- /dev/null +++ b/tests/ui/track-diagnostics/track8.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Z track-diagnostics +//@ forbid-output:interface +//@ dont-require-annotations: NOTE +#![warn(unreachable_cfg_select_predicates)] + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" +//@ normalize-stderr: "/rustc(?:-dev)?/[a-z0-9.]+/" -> "" + +cfg_select!{ + _ => {}, + _ => {}, //~ WARN unreachable configuration predicate +} + +#[repr(ferris)] //~ ERROR: malformed `repr` attribute input +#[diagnostic::ferris] //~ WARN unknown diagnostic attribute +#[doc(ferris)] //~ WARN unknown `doc` attribute `ferris` +fn main(){ + // Also check locations for buffered lints + #[doc(ferris)] //~ WARN unknown `doc` attribute `ferris` + println!(); +} diff --git a/tests/ui/track-diagnostics/track8.stderr b/tests/ui/track-diagnostics/track8.stderr new file mode 100644 index 0000000000000..8a729ca91eb32 --- /dev/null +++ b/tests/ui/track-diagnostics/track8.stderr @@ -0,0 +1,55 @@ +warning: unreachable configuration predicate + --> $DIR/track8.rs:LL:CC + | +LL | _ => {}, + | - always matches +LL | _ => {}, + | ^ this configuration predicate is never reached + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/cfg_select.rs:LL:CC +note: the lint level is defined here + --> $DIR/track8.rs:LL:CC + | +LL | #![warn(unreachable_cfg_select_predicates)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unknown `doc` attribute `ferris` + --> $DIR/track8.rs:LL:CC + | +LL | #[doc(ferris)] + | ^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/doc.rs:LL:CC + = note: `#[warn(invalid_doc_attributes)]` on by default + +error[E0539]: malformed `repr` attribute input + --> $DIR/track8.rs:LL:CC + | +LL | #[repr(ferris)] + | ^^^^^------^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/repr.rs:LL:CC + = note: for more information, visit + +warning: unknown diagnostic attribute + --> $DIR/track8.rs:LL:CC + | +LL | #[diagnostic::ferris] + | ^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs:LL:CC + = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default + +warning: unknown `doc` attribute `ferris` + --> $DIR/track8.rs:LL:CC + | +LL | #[doc(ferris)] + | ^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/doc.rs:LL:CC + +error: aborting due to 1 previous error; 4 warnings emitted + +For more information about this error, try `rustc --explain E0539`.