From 0005f628f068a766647bb0b159dac2c6cefcefa1 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 08:46:05 +0200 Subject: [PATCH 1/9] Refactor diagnostics in `handle_errors` function --- compiler/rustc_attr/src/builtin.rs | 58 +++--- compiler/rustc_attr/src/lib.rs | 1 + .../rustc_attr/src/session_diagnostics.rs | 196 ++++++++++++++++++ .../locales/en-US/attr.ftl | 29 +++ compiler/rustc_error_messages/src/lib.rs | 1 + 5 files changed, 254 insertions(+), 31 deletions(-) create mode 100644 compiler/rustc_attr/src/session_diagnostics.rs create mode 100644 compiler/rustc_error_messages/locales/en-US/attr.ftl diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 62ccd734fe720..b43551db43d67 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -14,6 +14,8 @@ use rustc_span::hygiene::Transparency; use rustc_span::{symbol::sym, symbol::Symbol, Span}; use std::num::NonZeroU32; +use crate::session_diagnostics; + pub fn is_builtin_attr(attr: &Attribute) -> bool { attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some() } @@ -25,46 +27,38 @@ enum AttrError { NonIdentFeature, MissingFeature, MultipleStabilityLevels, - UnsupportedLiteral(&'static str, /* is_bytestr */ bool), + UnsupportedLiteral(UnsupportedLiteralReason, /* is_bytestr */ bool), +} + +pub(crate) enum UnsupportedLiteralReason { + Generic, + CfgString, + DeprecatedString, + DeprecatedKvPair, } fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { - let diag = &sess.span_diagnostic; match error { AttrError::MultipleItem(item) => { - struct_span_err!(diag, span, E0538, "multiple '{}' items", item).emit(); + sess.emit_err(session_diagnostics::MultipleItem { span, item }); } AttrError::UnknownMetaItem(item, expected) => { - let expected = expected.iter().map(|name| format!("`{}`", name)).collect::>(); - struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item) - .span_label(span, format!("expected one of {}", expected.join(", "))) - .emit(); + sess.emit_err(session_diagnostics::UnknownMetaItem { span, item, expected }); } AttrError::MissingSince => { - struct_span_err!(diag, span, E0542, "missing 'since'").emit(); + sess.emit_err(session_diagnostics::MissingSince { span }); } AttrError::NonIdentFeature => { - struct_span_err!(diag, span, E0546, "'feature' is not an identifier").emit(); + sess.emit_err(session_diagnostics::NonIdentFeature { span }); } AttrError::MissingFeature => { - struct_span_err!(diag, span, E0546, "missing 'feature'").emit(); + sess.emit_err(session_diagnostics::MissingFeature { span }); } AttrError::MultipleStabilityLevels => { - struct_span_err!(diag, span, E0544, "multiple stability levels").emit(); + sess.emit_err(session_diagnostics::MultipleStabilityLevels { span }); } - AttrError::UnsupportedLiteral(msg, is_bytestr) => { - let mut err = struct_span_err!(diag, span, E0565, "{}", msg); - if is_bytestr { - if let Ok(lint_str) = sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "consider removing the prefix", - &lint_str[1..], - Applicability::MaybeIncorrect, - ); - } - } - err.emit(); + AttrError::UnsupportedLiteral(reason, is_bytestr) => { + sess.emit_err(session_diagnostics::UnsupportedLiteral { span, reason, is_bytestr }); } } } @@ -326,7 +320,7 @@ where handle_errors( &sess.parse_sess, meta.span(), - AttrError::UnsupportedLiteral("unsupported literal", false), + AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false), ); continue 'outer; }; @@ -494,7 +488,10 @@ where handle_errors( &sess.parse_sess, lit.span, - AttrError::UnsupportedLiteral("unsupported literal", false), + AttrError::UnsupportedLiteral( + UnsupportedLiteralReason::Generic, + false, + ), ); continue 'outer; } @@ -711,7 +708,7 @@ pub fn eval_condition( handle_errors( sess, mi.span(), - AttrError::UnsupportedLiteral("unsupported literal", false), + AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false), ); return false; } @@ -790,7 +787,7 @@ pub fn eval_condition( sess, lit.span, AttrError::UnsupportedLiteral( - "literal in `cfg` predicate value must be a string", + UnsupportedLiteralReason::CfgString, lit.kind.is_bytestr(), ), ); @@ -870,8 +867,7 @@ where &sess.parse_sess, lit.span, AttrError::UnsupportedLiteral( - "literal in `deprecated` \ - value must be a string", + UnsupportedLiteralReason::DeprecatedString, lit.kind.is_bytestr(), ), ); @@ -934,7 +930,7 @@ where &sess.parse_sess, lit.span, AttrError::UnsupportedLiteral( - "item in `deprecated` must be a key/value pair", + UnsupportedLiteralReason::DeprecatedKvPair, false, ), ); diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index c95c1c40a34c2..36a3620b6b9a2 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -10,6 +10,7 @@ extern crate rustc_macros; mod builtin; +mod session_diagnostics; pub use builtin::*; pub use IntType::*; diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs new file mode 100644 index 0000000000000..92ce9336edc59 --- /dev/null +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -0,0 +1,196 @@ +use std::num::IntErrorKind; + +use rustc_errors::{error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_macros::SessionDiagnostic; +use rustc_session::{parse::ParseSess, SessionDiagnostic}; +use rustc_span::Span; + +use crate::UnsupportedLiteralReason; + +#[derive(SessionDiagnostic)] +#[error(attr::multiple_item, code = "E0538")] +pub(crate) struct MultipleItem { + #[primary_span] + pub span: Span, + + pub item: String, +} + +#[derive(SessionDiagnostic)] +#[error(attr::missing_since, code = "E0542")] +pub(crate) struct MissingSince { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::non_ident_feature, code = "E0546")] +pub(crate) struct NonIdentFeature { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::missing_feature, code = "E0546")] +pub(crate) struct MissingFeature { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::multiple_stability_levels, code = "E0544")] +pub(crate) struct MultipleStabilityLevels { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::invalid_meta_item, code = "E0539")] +pub(crate) struct InvalidMetaItem { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::missing_issue, code = "E0547")] +pub(crate) struct MissingIssue { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::rustc_promotable_pairing, code = "E0717")] +pub(crate) struct RustcPromotablePairing { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::rustc_allowed_unstable_pairing, code = "E0789")] +pub(crate) struct RustcAllowedUnstablePairing { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::soft_no_args)] +pub(crate) struct SoftNoArgs { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::invalid_issue_string, code = "E0545")] +pub(crate) struct InvalidIssueString { + #[primary_span] + pub span: Span, + + #[subdiagnostic] + pub cause: Option, +} + +// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be +// translatable. +#[derive(SessionSubdiagnostic)] +pub(crate) enum InvalidIssueStringCause { + #[label(attr::must_not_be_zero)] + MustNotBeZero { + #[primary_span] + span: Span, + }, + + #[label(attr::empty)] + Empty { + #[primary_span] + span: Span, + }, + + #[label(attr::invalid_digit)] + InvalidDigit { + #[primary_span] + span: Span, + }, + + #[label(attr::pos_overflow)] + PosOverflow { + #[primary_span] + span: Span, + }, + + #[label(attr::neg_overflow)] + NegOverflow { + #[primary_span] + span: Span, + }, +} + +impl InvalidIssueStringCause { + pub fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option { + match kind { + IntErrorKind::Empty => Some(Self::Empty { span }), + IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }), + IntErrorKind::PosOverflow => Some(Self::PosOverflow { span }), + IntErrorKind::NegOverflow => Some(Self::NegOverflow { span }), + IntErrorKind::Zero => Some(Self::MustNotBeZero { span }), + _ => None, + } + } +} + +pub(crate) struct UnknownMetaItem<'a> { + pub span: Span, + pub item: String, + pub expected: &'a [&'a str], +} + +// Manual implementation to be able to format `expected` items correctly. +impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> { + fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::>(); + let mut diag = sess.span_diagnostic.struct_span_err_with_code( + self.span, + fluent::attr::unknown_meta_item, + error_code!(E0541), + ); + diag.set_arg("item", self.item); + diag.set_arg("expected", expected.join(", ")); + diag.span_label(self.span, fluent::attr::label); + diag + } +} + +pub(crate) struct UnsupportedLiteral { + pub span: Span, + pub reason: UnsupportedLiteralReason, + pub is_bytestr: bool, +} + +impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral { + fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut diag = sess.span_diagnostic.struct_span_err_with_code( + self.span, + match self.reason { + UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic, + UnsupportedLiteralReason::CfgString => fluent::attr::unsupported_literal_cfg_string, + UnsupportedLiteralReason::DeprecatedString => { + fluent::attr::unsupported_literal_deprecated_string + } + UnsupportedLiteralReason::DeprecatedKvPair => { + fluent::attr::unsupported_literal_deprecated_kv_pair + } + }, + error_code!(E0565), + ); + if self.is_bytestr { + if let Ok(lint_str) = sess.source_map().span_to_snippet(self.span) { + diag.span_suggestion( + self.span, + fluent::attr::unsupported_literal_suggestion, + &lint_str[1..], + Applicability::MaybeIncorrect, + ); + } + } + diag + } +} diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_error_messages/locales/en-US/attr.ftl new file mode 100644 index 0000000000000..a8207b1f7bc37 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/attr.ftl @@ -0,0 +1,29 @@ +attr_multiple_item = + multiple '{$item}' items + +attr_unknown_meta_item = + unknown meta item '{$item}' + .label = expected one of {$expected} + +attr_missing_since = + missing 'since' + +attr_non_ident_feature = + 'feature' is not an identifier + +attr_missing_feature = + missing 'feature' + +attr_multiple_stability_levels = + multiple stability levels + +attr_unsupported_literal_generic = + unsupported literal +attr_unsupported_literal_cfg_string = + literal in `cfg` predicate value must be a string +attr_unsupported_literal_deprecated_string = + literal in `deprecated` value must be a string +attr_unsupported_literal_deprecated_kv_pair = + item in `deprecated` must be a key/value pair +attr_unsupported_literal_suggestion = + consider removing the prefix diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 3569c7f063064..ab09a902b0a7a 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -33,6 +33,7 @@ pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. fluent_messages! { ast_passes => "../locales/en-US/ast_passes.ftl", + attr => "../locales/en-US/attr.ftl", borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", const_eval => "../locales/en-US/const_eval.ftl", From 83a724eab5e7f6c7b03374efd625b71ff9cf92a3 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 08:48:14 +0200 Subject: [PATCH 2/9] Refactor more diagnostics in `rustc_attr` --- compiler/rustc_attr/src/builtin.rs | 69 ++++++------------- .../locales/en-US/attr.ftl | 28 ++++++++ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index b43551db43d67..98a171488caba 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -237,8 +237,6 @@ where let mut promotable = false; let mut allowed_through_unstable_modules = false; - let diagnostic = &sess.parse_sess.span_diagnostic; - 'outer: for attr in attrs_iter { if ![ sym::rustc_const_unstable, @@ -278,7 +276,7 @@ where *item = Some(v); true } else { - struct_span_err!(diagnostic, meta.span, E0539, "incorrect meta item").emit(); + sess.emit_err(session_diagnostics::InvalidMetaItem { span: meta.span }); false } }; @@ -344,39 +342,28 @@ where // is a name/value pair string literal. issue_num = match issue.unwrap().as_str() { "none" => None, - issue => { - let emit_diag = |msg: &str| { - struct_span_err!( - diagnostic, - mi.span, - E0545, - "`issue` must be a non-zero numeric string \ - or \"none\"", - ) - .span_label(mi.name_value_literal_span().unwrap(), msg) - .emit(); - }; - match issue.parse() { - Ok(0) => { - emit_diag( - "`issue` must not be \"0\", \ - use \"none\" instead", - ); - continue 'outer; - } - Ok(num) => NonZeroU32::new(num), - Err(err) => { - emit_diag(&err.to_string()); - continue 'outer; - } + issue => match issue.parse::() { + Ok(num) => Some(num), + Err(err) => { + sess.emit_err( + session_diagnostics::InvalidIssueString { + span: mi.span, + cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind( + mi.name_value_literal_span().unwrap(), + err.kind(), + ), + }, + ); + continue 'outer; } - } + }, }; } sym::soft => { if !mi.is_word() { - let msg = "`soft` should not have any arguments"; - sess.parse_sess.span_diagnostic.span_err(mi.span, msg); + sess.emit_err(session_diagnostics::SoftNoArgs { + span: mi.span, + }); } is_soft = true; } @@ -434,8 +421,7 @@ where continue; } _ => { - struct_span_err!(diagnostic, attr.span, E0547, "missing 'issue'") - .emit(); + sess.emit_err(session_diagnostics::MissingIssue { span: attr.span }); continue; } } @@ -530,14 +516,7 @@ where if let Some((ref mut stab, _)) = const_stab { stab.promotable = promotable; } else { - struct_span_err!( - diagnostic, - item_sp, - E0717, - "`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \ - or a `rustc_const_stable` attribute" - ) - .emit(); + sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }); } } @@ -552,13 +531,7 @@ where { *allowed_through_unstable_modules = true; } else { - struct_span_err!( - diagnostic, - item_sp, - E0789, - "`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute" - ) - .emit(); + sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp }); } } diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_error_messages/locales/en-US/attr.ftl index a8207b1f7bc37..45dda0ea7c458 100644 --- a/compiler/rustc_error_messages/locales/en-US/attr.ftl +++ b/compiler/rustc_error_messages/locales/en-US/attr.ftl @@ -27,3 +27,31 @@ attr_unsupported_literal_deprecated_kv_pair = item in `deprecated` must be a key/value pair attr_unsupported_literal_suggestion = consider removing the prefix + +attr_invalid_meta_item = + incorrect meta item + +attr_invalid_issue_string = + `issue` must be a non-zero numeric string or "none" +attr_must_not_be_zero = + `issue` must not be "0", use "none" instead +attr_empty = + cannot parse integer from empty string +attr_invalid_digit = + invalid digit found in string +attr_pos_overflow = + number too large to fit in target type +attr_neg_overflow = + number too small to fit in target type + +attr_missing_issue = + missing 'issue' + +attr_rustc_promotable_pairing = + `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute + +attr_rustc_allowed_unstable_pairing = + `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute + +attr_soft_no_args = + `soft` should not have any arguments From 40c5184eec0c607e856fba385d186684fdd25412 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 10:03:28 +0200 Subject: [PATCH 3/9] Add internal diagnistics lints --- compiler/rustc_attr/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 36a3620b6b9a2..3a43f1aad02d6 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -5,6 +5,8 @@ //! to this crate. #![feature(let_else)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; From b3be7698d60f0e6840856daffce0ed22737a5289 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 12:36:16 +0200 Subject: [PATCH 4/9] Refactor additional diagnostics in `rustc_attr` --- compiler/rustc_attr/src/builtin.rs | 56 ++++++----------- .../rustc_attr/src/session_diagnostics.rs | 62 +++++++++++++++++++ .../locales/en-US/attr.ftl | 26 ++++++++ 3 files changed, 106 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 98a171488caba..b752daecc8820 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -645,25 +645,18 @@ pub fn eval_condition( NestedMetaItem::Literal(Lit { span, .. }) | NestedMetaItem::MetaItem(MetaItem { span, .. }), ] => { - sess.span_diagnostic - .struct_span_err(*span, "expected a version literal") - .emit(); + sess.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span }); return false; } [..] => { - sess.span_diagnostic - .struct_span_err(cfg.span, "expected single version literal") - .emit(); + sess.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { + span: cfg.span, + }); return false; } }; let Some(min_version) = parse_version(min_version.as_str(), false) else { - sess.span_diagnostic - .struct_span_warn( - *span, - "unknown version literal format, assuming it refers to a future version", - ) - .emit(); + sess.emit_warning(session_diagnostics::UnknownVersionLiteral { span: *span }); return false; }; let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap(); @@ -706,13 +699,9 @@ pub fn eval_condition( }), sym::not => { if mis.len() != 1 { - struct_span_err!( - sess.span_diagnostic, - cfg.span, - E0536, - "expected 1 cfg-pattern" - ) - .emit(); + sess.emit_err(session_diagnostics::ExpectedOneCfgPattern { + span: cfg.span, + }); return false; } @@ -738,21 +727,16 @@ pub fn eval_condition( }) } _ => { - struct_span_err!( - sess.span_diagnostic, - cfg.span, - E0537, - "invalid predicate `{}`", - pprust::path_to_string(&cfg.path) - ) - .emit(); + sess.emit_err(session_diagnostics::InvalidPredicate { + span: cfg.span, + predicate: pprust::path_to_string(&cfg.path), + }); false } } } ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => { - sess.span_diagnostic - .span_err(cfg.path.span, "`cfg` predicate key must be an identifier"); + sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span }); true } MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => { @@ -868,14 +852,10 @@ where } sym::suggestion => { if !sess.features_untracked().deprecated_suggestion { - let mut diag = sess.struct_span_err( - mi.span, - "suggestions on deprecated items are unstable", - ); - if sess.is_nightly_build() { - diag.help("add `#![feature(deprecated_suggestion)]` to the crate root"); - } - diag.note("see #94785 for more details").emit(); + sess.emit_err(session_diagnostics::DeprecatedItemSuggestion { + span: mi.span, + is_nightly: sess.is_nightly_build().then_some(()), + }); } if !get(mi, &mut suggestion) { @@ -921,7 +901,7 @@ where } if note.is_none() { - struct_span_err!(diagnostic, attr.span, E0543, "missing 'note'").emit(); + sess.emit_err(session_diagnostics::MissingNote { span: attr.span }); continue; } } diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 92ce9336edc59..4b9f1541f4733 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -79,6 +79,68 @@ pub(crate) struct SoftNoArgs { pub span: Span, } +#[derive(SessionDiagnostic)] +#[error(attr::expected_version_literal)] +pub(crate) struct ExpectedVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::expected_single_version_literal)] +pub(crate) struct ExpectedSingleVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[warning(attr::unknown_version_literal)] +pub(crate) struct UnknownVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::expected_one_cfg_pattern, code = "E0536")] +pub(crate) struct ExpectedOneCfgPattern { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::invalid_predicate, code = "E0537")] +pub(crate) struct InvalidPredicate { + #[primary_span] + pub span: Span, + + pub predicate: String, +} + +#[derive(SessionDiagnostic)] +#[error(attr::cfg_predicate_identifier)] +pub(crate) struct CfgPredicateIdentifier { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::deprecated_item_suggestion)] +#[note] +pub(crate) struct DeprecatedItemSuggestion { + #[primary_span] + pub span: Span, + + #[help] + pub is_nightly: Option<()>, +} + +#[derive(SessionDiagnostic)] +#[error(attr::missing_note, code = "E0543")] +pub(crate) struct MissingNote { + #[primary_span] + pub span: Span, +} + #[derive(SessionDiagnostic)] #[error(attr::invalid_issue_string, code = "E0545")] pub(crate) struct InvalidIssueString { diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_error_messages/locales/en-US/attr.ftl index 45dda0ea7c458..378377ed8660d 100644 --- a/compiler/rustc_error_messages/locales/en-US/attr.ftl +++ b/compiler/rustc_error_messages/locales/en-US/attr.ftl @@ -55,3 +55,29 @@ attr_rustc_allowed_unstable_pairing = attr_soft_no_args = `soft` should not have any arguments + +attr_expected_version_literal = + expected a version literal + +attr_expected_single_version_literal = + expected single version literal + +attr_unknown_version_literal = + unknown version literal format, assuming it refers to a future version + +attr_expected_one_cfg_pattern = + expected 1 cfg-pattern + +attr_invalid_predicate = + invalid predicate `{$predicate}` + +attr_cfg_predicate_identifier = + `cfg` predicate key must be an identifier + +attr_deprecated_item_suggestion = + suggestions on deprecated items are unstable + .help = add `#![feature(deprecated_suggestion)]` to the crate root + .note = see #94785 for more details + +attr_missing_note = + missing 'note' From b731bfa2d42641472028e35aeb088bf1e113f366 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 12:38:22 +0200 Subject: [PATCH 5/9] Refactor 'invalid issue' diagnostic to use labels within the same Fluent object --- .../rustc_error_messages/locales/en-US/attr.ftl | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_error_messages/locales/en-US/attr.ftl index 378377ed8660d..56473e9c3692d 100644 --- a/compiler/rustc_error_messages/locales/en-US/attr.ftl +++ b/compiler/rustc_error_messages/locales/en-US/attr.ftl @@ -33,16 +33,11 @@ attr_invalid_meta_item = attr_invalid_issue_string = `issue` must be a non-zero numeric string or "none" -attr_must_not_be_zero = - `issue` must not be "0", use "none" instead -attr_empty = - cannot parse integer from empty string -attr_invalid_digit = - invalid digit found in string -attr_pos_overflow = - number too large to fit in target type -attr_neg_overflow = - number too small to fit in target type + .must_not_be_zero = `issue` must not be "0", use "none" instead + .empty = cannot parse integer from empty string + .invalid_digit = invalid digit found in string + .pos_overflow = number too large to fit in target type + .neg_overflow = number too small to fit in target type attr_missing_issue = missing 'issue' From c4f59605d2f460aadaa23c92dda826b8906ebc4b Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 20:56:29 +0200 Subject: [PATCH 6/9] Refactor remaining diagnostics --- compiler/rustc_attr/src/builtin.rs | 165 +++++++----------- .../locales/en-US/attr.ftl | 31 +++- 2 files changed, 93 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index b752daecc8820..96cedfd6fb06e 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -3,7 +3,6 @@ use rustc_ast as ast; use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem, NodeId}; use rustc_ast_pretty::pprust; -use rustc_errors::{struct_span_err, Applicability}; use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}; use rustc_macros::HashStable_Generic; use rustc_session::lint::builtin::UNEXPECTED_CFGS; @@ -14,7 +13,7 @@ use rustc_span::hygiene::Transparency; use rustc_span::{symbol::sym, symbol::Symbol, Span}; use std::num::NonZeroU32; -use crate::session_diagnostics; +use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; pub fn is_builtin_attr(attr: &Attribute) -> bool { attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some() @@ -276,7 +275,7 @@ where *item = Some(v); true } else { - sess.emit_err(session_diagnostics::InvalidMetaItem { span: meta.span }); + sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span }); false } }; @@ -788,7 +787,6 @@ where I: Iterator, { let mut depr: Option<(Deprecation, Span)> = None; - let diagnostic = &sess.parse_sess.span_diagnostic; let is_rustc = sess.features_untracked().staged_api; 'outer: for attr in attrs_iter { @@ -829,8 +827,12 @@ where ), ); } else { - struct_span_err!(diagnostic, meta.span, E0551, "incorrect meta item") - .emit(); + // FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring + // the error code. Consider changing this to `IncorrectMetaItem`. See + // #51489. + sess.emit_err(session_diagnostics::IncorrectMetaItem2 { + span: meta.span, + }); } false @@ -971,19 +973,9 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { sym::simd => Some(ReprSimd), sym::transparent => Some(ReprTransparent), sym::align => { - let mut err = struct_span_err!( - diagnostic, - item.span(), - E0589, - "invalid `repr(align)` attribute: `align` needs an argument" - ); - err.span_suggestion( - item.span(), - "supply an argument here", - "align(...)", - Applicability::HasPlaceholders, - ); - err.emit(); + sess.emit_err(session_diagnostics::InvalidReprAlignNeedArg { + span: item.span(), + }); recognised = true; None } @@ -1012,57 +1004,44 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { || int_type_of_word(name).is_some() { recognised = true; - struct_span_err!( - diagnostic, - item.span(), - E0552, - "invalid representation hint: `{}` does not take a parenthesized argument list", - name.to_ident_string(), - ).emit(); + sess.emit_err(session_diagnostics::InvalidReprHintNoParen { + span: item.span(), + name: name.to_ident_string(), + }); } if let Some(literal_error) = literal_error { - struct_span_err!( - diagnostic, - item.span(), - E0589, - "invalid `repr({})` attribute: {}", - name.to_ident_string(), - literal_error - ) - .emit(); + sess.emit_err(session_diagnostics::InvalidReprGeneric { + span: item.span(), + repr_arg: name.to_ident_string(), + error_part: literal_error, + }); } } else if let Some(meta_item) = item.meta_item() { if let MetaItemKind::NameValue(ref value) = meta_item.kind { if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { let name = meta_item.name_or_empty().to_ident_string(); recognised = true; - let mut err = struct_span_err!( - diagnostic, - item.span(), - E0693, - "incorrect `repr({})` attribute format", - name, - ); - match value.kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("{}({})", name, int), - Applicability::MachineApplicable, - ); - } - ast::LitKind::Str(s, _) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("{}({})", name, s), - Applicability::MachineApplicable, - ); - } - _ => {} - } - err.emit(); + sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric { + span: item.span(), + repr_arg: &name, + cause: match value.kind { + ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { + Some(IncorrectReprFormatGenericCause::Int { + span: item.span(), + name: &name, + int, + }) + } + ast::LitKind::Str(symbol, _) => { + Some(IncorrectReprFormatGenericCause::Symbol { + span: item.span(), + name: &name, + symbol, + }) + } + _ => None, + }, + }); } else { if matches!( meta_item.name_or_empty(), @@ -1070,51 +1049,33 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { ) || int_type_of_word(meta_item.name_or_empty()).is_some() { recognised = true; - struct_span_err!( - diagnostic, - meta_item.span, - E0552, - "invalid representation hint: `{}` does not take a value", - meta_item.name_or_empty().to_ident_string(), - ) - .emit(); + sess.emit_err(session_diagnostics::InvalidReprHintNoValue { + span: meta_item.span, + name: meta_item.name_or_empty().to_ident_string(), + }); } } } else if let MetaItemKind::List(_) = meta_item.kind { if meta_item.has_name(sym::align) { recognised = true; - struct_span_err!( - diagnostic, - meta_item.span, - E0693, - "incorrect `repr(align)` attribute format: \ - `align` takes exactly one argument in parentheses" - ) - .emit(); + sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { + span: meta_item.span, + }); } else if meta_item.has_name(sym::packed) { recognised = true; - struct_span_err!( - diagnostic, - meta_item.span, - E0552, - "incorrect `repr(packed)` attribute format: \ - `packed` takes exactly one parenthesized argument, \ - or no parentheses at all" - ) - .emit(); + sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg { + span: meta_item.span, + }); } else if matches!( meta_item.name_or_empty(), sym::C | sym::simd | sym::transparent ) || int_type_of_word(meta_item.name_or_empty()).is_some() { recognised = true; - struct_span_err!( - diagnostic, - meta_item.span, - E0552, - "invalid representation hint: `{}` does not take a parenthesized argument list", - meta_item.name_or_empty().to_ident_string(), - ).emit(); + sess.emit_err(session_diagnostics::InvalidReprHintNoParen { + span: meta_item.span, + name: meta_item.name_or_empty().to_ident_string(), + }); } } } @@ -1211,10 +1172,10 @@ fn allow_unstable<'a>( let list = attrs .filter_map(move |attr| { attr.meta_item_list().or_else(|| { - sess.diagnostic().span_err( - attr.span, - &format!("`{}` expects a list of feature names", symbol.to_ident_string()), - ); + sess.emit_err(session_diagnostics::ExpectsFeatureList { + span: attr.span, + name: symbol.to_ident_string(), + }); None }) }) @@ -1223,10 +1184,10 @@ fn allow_unstable<'a>( list.into_iter().filter_map(move |it| { let name = it.ident().map(|ident| ident.name); if name.is_none() { - sess.diagnostic().span_err( - it.span(), - &format!("`{}` expects feature names", symbol.to_ident_string()), - ); + sess.emit_err(session_diagnostics::ExpectsFeatures { + span: it.span(), + name: symbol.to_ident_string(), + }); } name }) diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_error_messages/locales/en-US/attr.ftl index 56473e9c3692d..ad4a70fac8c5f 100644 --- a/compiler/rustc_error_messages/locales/en-US/attr.ftl +++ b/compiler/rustc_error_messages/locales/en-US/attr.ftl @@ -28,7 +28,7 @@ attr_unsupported_literal_deprecated_kv_pair = attr_unsupported_literal_suggestion = consider removing the prefix -attr_invalid_meta_item = +attr_incorrect_meta_item = incorrect meta item attr_invalid_issue_string = @@ -76,3 +76,32 @@ attr_deprecated_item_suggestion = attr_missing_note = missing 'note' + +attr_invalid_repr_align_need_arg = + invalid `repr(align)` attribute: `align` needs an argument + .suggestion = supply an argument here + +attr_invalid_repr_generic = + invalid `repr({$repr_arg})` attribute: {$error_part} + +attr_invalid_repr_hint_no_paren = + invalid representation hint: `{$name}` does not take a parenthesized argument list + +attr_invalid_repr_hint_no_value = + invalid representation hint: `{$name}` does not take a value + +attr_incorrect_repr_format_generic = + incorrect `repr({$repr_arg})` attribute format + .suggestion = use parentheses instead + +attr_incorrect_repr_format_align_one_arg = + incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + +attr_incorrect_repr_format_packed_one_or_zero_arg = + incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all + +attr_expects_feature_list = + `{$name}` expects a list of feature names + +attr_expects_features = + `{$name}` expects feature names From 1c28006bf6f6e0f989c725c74c1ee7d14cd62b81 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 21:43:03 +0200 Subject: [PATCH 7/9] Reorder diagnostics in code order, then alphabetical order --- compiler/rustc_attr/src/builtin.rs | 3 - .../rustc_attr/src/session_diagnostics.rs | 343 ++++++++++++------ .../locales/en-US/attr.ftl | 114 +++--- 3 files changed, 290 insertions(+), 170 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 96cedfd6fb06e..17ea47082d446 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -827,9 +827,6 @@ where ), ); } else { - // FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring - // the error code. Consider changing this to `IncorrectMetaItem`. See - // #51489. sess.emit_err(session_diagnostics::IncorrectMetaItem2 { span: meta.span, }); diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 4b9f1541f4733..d0b1f02cf3c16 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -3,140 +3,82 @@ use std::num::IntErrorKind; use rustc_errors::{error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_macros::SessionDiagnostic; use rustc_session::{parse::ParseSess, SessionDiagnostic}; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use crate::UnsupportedLiteralReason; #[derive(SessionDiagnostic)] -#[error(attr::multiple_item, code = "E0538")] -pub(crate) struct MultipleItem { - #[primary_span] - pub span: Span, - - pub item: String, -} - -#[derive(SessionDiagnostic)] -#[error(attr::missing_since, code = "E0542")] -pub(crate) struct MissingSince { - #[primary_span] - pub span: Span, -} - -#[derive(SessionDiagnostic)] -#[error(attr::non_ident_feature, code = "E0546")] -pub(crate) struct NonIdentFeature { - #[primary_span] - pub span: Span, -} - -#[derive(SessionDiagnostic)] -#[error(attr::missing_feature, code = "E0546")] -pub(crate) struct MissingFeature { - #[primary_span] - pub span: Span, -} - -#[derive(SessionDiagnostic)] -#[error(attr::multiple_stability_levels, code = "E0544")] -pub(crate) struct MultipleStabilityLevels { - #[primary_span] - pub span: Span, -} - -#[derive(SessionDiagnostic)] -#[error(attr::invalid_meta_item, code = "E0539")] -pub(crate) struct InvalidMetaItem { - #[primary_span] - pub span: Span, -} - -#[derive(SessionDiagnostic)] -#[error(attr::missing_issue, code = "E0547")] -pub(crate) struct MissingIssue { - #[primary_span] - pub span: Span, -} - -#[derive(SessionDiagnostic)] -#[error(attr::rustc_promotable_pairing, code = "E0717")] -pub(crate) struct RustcPromotablePairing { +#[error(attr::expected_one_cfg_pattern, code = "E0536")] +pub(crate) struct ExpectedOneCfgPattern { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::rustc_allowed_unstable_pairing, code = "E0789")] -pub(crate) struct RustcAllowedUnstablePairing { +#[error(attr::invalid_predicate, code = "E0537")] +pub(crate) struct InvalidPredicate { #[primary_span] pub span: Span, -} -#[derive(SessionDiagnostic)] -#[error(attr::soft_no_args)] -pub(crate) struct SoftNoArgs { - #[primary_span] - pub span: Span, + pub predicate: String, } #[derive(SessionDiagnostic)] -#[error(attr::expected_version_literal)] -pub(crate) struct ExpectedVersionLiteral { +#[error(attr::multiple_item, code = "E0538")] +pub(crate) struct MultipleItem { #[primary_span] pub span: Span, -} -#[derive(SessionDiagnostic)] -#[error(attr::expected_single_version_literal)] -pub(crate) struct ExpectedSingleVersionLiteral { - #[primary_span] - pub span: Span, + pub item: String, } #[derive(SessionDiagnostic)] -#[warning(attr::unknown_version_literal)] -pub(crate) struct UnknownVersionLiteral { +#[error(attr::incorrect_meta_item, code = "E0539")] +pub(crate) struct IncorrectMetaItem { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[error(attr::expected_one_cfg_pattern, code = "E0536")] -pub(crate) struct ExpectedOneCfgPattern { - #[primary_span] +// Error code: E0541 +pub(crate) struct UnknownMetaItem<'a> { pub span: Span, + pub item: String, + pub expected: &'a [&'a str], } -#[derive(SessionDiagnostic)] -#[error(attr::invalid_predicate, code = "E0537")] -pub(crate) struct InvalidPredicate { - #[primary_span] - pub span: Span, - - pub predicate: String, +// Manual implementation to be able to format `expected` items correctly. +impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> { + fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::>(); + let mut diag = sess.span_diagnostic.struct_span_err_with_code( + self.span, + fluent::attr::unknown_meta_item, + error_code!(E0541), + ); + diag.set_arg("item", self.item); + diag.set_arg("expected", expected.join(", ")); + diag.span_label(self.span, fluent::attr::label); + diag + } } #[derive(SessionDiagnostic)] -#[error(attr::cfg_predicate_identifier)] -pub(crate) struct CfgPredicateIdentifier { +#[error(attr::missing_since, code = "E0542")] +pub(crate) struct MissingSince { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::deprecated_item_suggestion)] -#[note] -pub(crate) struct DeprecatedItemSuggestion { +#[error(attr::missing_note, code = "E0543")] +pub(crate) struct MissingNote { #[primary_span] pub span: Span, - - #[help] - pub is_nightly: Option<()>, } #[derive(SessionDiagnostic)] -#[error(attr::missing_note, code = "E0543")] -pub(crate) struct MissingNote { +#[error(attr::multiple_stability_levels, code = "E0544")] +pub(crate) struct MultipleStabilityLevels { #[primary_span] pub span: Span, } @@ -199,28 +141,64 @@ impl InvalidIssueStringCause { } } -pub(crate) struct UnknownMetaItem<'a> { +#[derive(SessionDiagnostic)] +#[error(attr::missing_feature, code = "E0546")] +pub(crate) struct MissingFeature { + #[primary_span] pub span: Span, - pub item: String, - pub expected: &'a [&'a str], } -// Manual implementation to be able to format `expected` items correctly. -impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> { - fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::>(); - let mut diag = sess.span_diagnostic.struct_span_err_with_code( - self.span, - fluent::attr::unknown_meta_item, - error_code!(E0541), - ); - diag.set_arg("item", self.item); - diag.set_arg("expected", expected.join(", ")); - diag.span_label(self.span, fluent::attr::label); - diag - } +#[derive(SessionDiagnostic)] +#[error(attr::non_ident_feature, code = "E0546")] +pub(crate) struct NonIdentFeature { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::missing_issue, code = "E0547")] +pub(crate) struct MissingIssue { + #[primary_span] + pub span: Span, +} + +// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider +// changing this to `IncorrectMetaItem`. See #51489. +#[derive(SessionDiagnostic)] +#[error(attr::incorrect_meta_item, code = "E0551")] +pub(crate) struct IncorrectMetaItem2 { + #[primary_span] + pub span: Span, +} + +// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? +// It is more similar to `IncorrectReprFormatGeneric`. +#[derive(SessionDiagnostic)] +#[error(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")] +pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::invalid_repr_hint_no_paren, code = "E0552")] +pub(crate) struct InvalidReprHintNoParen { + #[primary_span] + pub span: Span, + + pub name: String, } +#[derive(SessionDiagnostic)] +#[error(attr::invalid_repr_hint_no_value, code = "E0552")] +pub(crate) struct InvalidReprHintNoValue { + #[primary_span] + pub span: Span, + + pub name: String, +} + +// Error code: E0565 pub(crate) struct UnsupportedLiteral { pub span: Span, pub reason: UnsupportedLiteralReason, @@ -256,3 +234,148 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral { diag } } +#[derive(SessionDiagnostic)] +#[error(attr::invalid_repr_align_need_arg, code = "E0589")] +pub(crate) struct InvalidReprAlignNeedArg { + #[primary_span] + #[suggestion(code = "align(...)", applicability = "has-placeholders")] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::invalid_repr_generic, code = "E0589")] +pub(crate) struct InvalidReprGeneric<'a> { + #[primary_span] + pub span: Span, + + pub repr_arg: String, + pub error_part: &'a str, +} + +#[derive(SessionDiagnostic)] +#[error(attr::incorrect_repr_format_align_one_arg, code = "E0693")] +pub(crate) struct IncorrectReprFormatAlignOneArg { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::incorrect_repr_format_generic, code = "E0693")] +pub(crate) struct IncorrectReprFormatGeneric<'a> { + #[primary_span] + pub span: Span, + + pub repr_arg: &'a str, + + #[subdiagnostic] + pub cause: Option>, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum IncorrectReprFormatGenericCause<'a> { + #[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")] + Int { + #[primary_span] + span: Span, + + #[skip_arg] + name: &'a str, + + #[skip_arg] + int: u128, + }, + + #[suggestion( + attr::suggestion, + code = "{name}({symbol})", + applicability = "machine-applicable" + )] + Symbol { + #[primary_span] + span: Span, + + #[skip_arg] + name: &'a str, + + #[skip_arg] + symbol: Symbol, + }, +} + +#[derive(SessionDiagnostic)] +#[error(attr::rustc_promotable_pairing, code = "E0717")] +pub(crate) struct RustcPromotablePairing { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::rustc_allowed_unstable_pairing, code = "E0789")] +pub(crate) struct RustcAllowedUnstablePairing { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::cfg_predicate_identifier)] +pub(crate) struct CfgPredicateIdentifier { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::deprecated_item_suggestion)] +#[note] +pub(crate) struct DeprecatedItemSuggestion { + #[primary_span] + pub span: Span, + + #[help] + pub is_nightly: Option<()>, +} + +#[derive(SessionDiagnostic)] +#[error(attr::expected_single_version_literal)] +pub(crate) struct ExpectedSingleVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::expected_version_literal)] +pub(crate) struct ExpectedVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(attr::expects_feature_list)] +pub(crate) struct ExpectsFeatureList { + #[primary_span] + pub span: Span, + + pub name: String, +} + +#[derive(SessionDiagnostic)] +#[error(attr::expects_features)] +pub(crate) struct ExpectsFeatures { + #[primary_span] + pub span: Span, + + pub name: String, +} + +#[derive(SessionDiagnostic)] +#[error(attr::soft_no_args)] +pub(crate) struct SoftNoArgs { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[warning(attr::unknown_version_literal)] +pub(crate) struct UnknownVersionLiteral { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_error_messages/locales/en-US/attr.ftl index ad4a70fac8c5f..a7f8c993d4225 100644 --- a/compiler/rustc_error_messages/locales/en-US/attr.ftl +++ b/compiler/rustc_error_messages/locales/en-US/attr.ftl @@ -1,6 +1,15 @@ +attr_expected_one_cfg_pattern = + expected 1 cfg-pattern + +attr_invalid_predicate = + invalid predicate `{$predicate}` + attr_multiple_item = multiple '{$item}' items +attr_incorrect_meta_item = + incorrect meta item + attr_unknown_meta_item = unknown meta item '{$item}' .label = expected one of {$expected} @@ -8,14 +17,37 @@ attr_unknown_meta_item = attr_missing_since = missing 'since' -attr_non_ident_feature = - 'feature' is not an identifier +attr_missing_note = + missing 'note' + +attr_multiple_stability_levels = + multiple stability levels + +attr_invalid_issue_string = + `issue` must be a non-zero numeric string or "none" + .must_not_be_zero = `issue` must not be "0", use "none" instead + .empty = cannot parse integer from empty string + .invalid_digit = invalid digit found in string + .pos_overflow = number too large to fit in target type + .neg_overflow = number too small to fit in target type attr_missing_feature = missing 'feature' -attr_multiple_stability_levels = - multiple stability levels +attr_non_ident_feature = + 'feature' is not an identifier + +attr_missing_issue = + missing 'issue' + +attr_incorrect_repr_format_packed_one_or_zero_arg = + incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all + +attr_invalid_repr_hint_no_paren = + invalid representation hint: `{$name}` does not take a parenthesized argument list + +attr_invalid_repr_hint_no_value = + invalid representation hint: `{$name}` does not take a value attr_unsupported_literal_generic = unsupported literal @@ -28,19 +60,19 @@ attr_unsupported_literal_deprecated_kv_pair = attr_unsupported_literal_suggestion = consider removing the prefix -attr_incorrect_meta_item = - incorrect meta item +attr_invalid_repr_align_need_arg = + invalid `repr(align)` attribute: `align` needs an argument + .suggestion = supply an argument here -attr_invalid_issue_string = - `issue` must be a non-zero numeric string or "none" - .must_not_be_zero = `issue` must not be "0", use "none" instead - .empty = cannot parse integer from empty string - .invalid_digit = invalid digit found in string - .pos_overflow = number too large to fit in target type - .neg_overflow = number too small to fit in target type +attr_invalid_repr_generic = + invalid `repr({$repr_arg})` attribute: {$error_part} -attr_missing_issue = - missing 'issue' +attr_incorrect_repr_format_align_one_arg = + incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + +attr_incorrect_repr_format_generic = + incorrect `repr({$repr_arg})` attribute format + .suggestion = use parentheses instead attr_rustc_promotable_pairing = `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute @@ -48,24 +80,6 @@ attr_rustc_promotable_pairing = attr_rustc_allowed_unstable_pairing = `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute -attr_soft_no_args = - `soft` should not have any arguments - -attr_expected_version_literal = - expected a version literal - -attr_expected_single_version_literal = - expected single version literal - -attr_unknown_version_literal = - unknown version literal format, assuming it refers to a future version - -attr_expected_one_cfg_pattern = - expected 1 cfg-pattern - -attr_invalid_predicate = - invalid predicate `{$predicate}` - attr_cfg_predicate_identifier = `cfg` predicate key must be an identifier @@ -74,34 +88,20 @@ attr_deprecated_item_suggestion = .help = add `#![feature(deprecated_suggestion)]` to the crate root .note = see #94785 for more details -attr_missing_note = - missing 'note' - -attr_invalid_repr_align_need_arg = - invalid `repr(align)` attribute: `align` needs an argument - .suggestion = supply an argument here - -attr_invalid_repr_generic = - invalid `repr({$repr_arg})` attribute: {$error_part} - -attr_invalid_repr_hint_no_paren = - invalid representation hint: `{$name}` does not take a parenthesized argument list - -attr_invalid_repr_hint_no_value = - invalid representation hint: `{$name}` does not take a value - -attr_incorrect_repr_format_generic = - incorrect `repr({$repr_arg})` attribute format - .suggestion = use parentheses instead - -attr_incorrect_repr_format_align_one_arg = - incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses +attr_expected_single_version_literal = + expected single version literal -attr_incorrect_repr_format_packed_one_or_zero_arg = - incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all +attr_expected_version_literal = + expected a version literal attr_expects_feature_list = `{$name}` expects a list of feature names attr_expects_features = `{$name}` expects feature names + +attr_soft_no_args = + `soft` should not have any arguments + +attr_unknown_version_literal = + unknown version literal format, assuming it refers to a future version From 944a3e22ef39cd9640995331e3ab6d373d1241c8 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 21:52:15 +0200 Subject: [PATCH 8/9] Change to `diag` attributes --- .../rustc_attr/src/session_diagnostics.rs | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index d0b1f02cf3c16..34e9815609109 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -8,14 +8,14 @@ use rustc_span::{Span, Symbol}; use crate::UnsupportedLiteralReason; #[derive(SessionDiagnostic)] -#[error(attr::expected_one_cfg_pattern, code = "E0536")] +#[diag(attr::expected_one_cfg_pattern, code = "E0536")] pub(crate) struct ExpectedOneCfgPattern { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::invalid_predicate, code = "E0537")] +#[diag(attr::invalid_predicate, code = "E0537")] pub(crate) struct InvalidPredicate { #[primary_span] pub span: Span, @@ -24,7 +24,7 @@ pub(crate) struct InvalidPredicate { } #[derive(SessionDiagnostic)] -#[error(attr::multiple_item, code = "E0538")] +#[diag(attr::multiple_item, code = "E0538")] pub(crate) struct MultipleItem { #[primary_span] pub span: Span, @@ -33,7 +33,7 @@ pub(crate) struct MultipleItem { } #[derive(SessionDiagnostic)] -#[error(attr::incorrect_meta_item, code = "E0539")] +#[diag(attr::incorrect_meta_item, code = "E0539")] pub(crate) struct IncorrectMetaItem { #[primary_span] pub span: Span, @@ -63,28 +63,28 @@ impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> { } #[derive(SessionDiagnostic)] -#[error(attr::missing_since, code = "E0542")] +#[diag(attr::missing_since, code = "E0542")] pub(crate) struct MissingSince { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::missing_note, code = "E0543")] +#[diag(attr::missing_note, code = "E0543")] pub(crate) struct MissingNote { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::multiple_stability_levels, code = "E0544")] +#[diag(attr::multiple_stability_levels, code = "E0544")] pub(crate) struct MultipleStabilityLevels { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::invalid_issue_string, code = "E0545")] +#[diag(attr::invalid_issue_string, code = "E0545")] pub(crate) struct InvalidIssueString { #[primary_span] pub span: Span, @@ -142,21 +142,21 @@ impl InvalidIssueStringCause { } #[derive(SessionDiagnostic)] -#[error(attr::missing_feature, code = "E0546")] +#[diag(attr::missing_feature, code = "E0546")] pub(crate) struct MissingFeature { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::non_ident_feature, code = "E0546")] +#[diag(attr::non_ident_feature, code = "E0546")] pub(crate) struct NonIdentFeature { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::missing_issue, code = "E0547")] +#[diag(attr::missing_issue, code = "E0547")] pub(crate) struct MissingIssue { #[primary_span] pub span: Span, @@ -165,7 +165,7 @@ pub(crate) struct MissingIssue { // FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider // changing this to `IncorrectMetaItem`. See #51489. #[derive(SessionDiagnostic)] -#[error(attr::incorrect_meta_item, code = "E0551")] +#[diag(attr::incorrect_meta_item, code = "E0551")] pub(crate) struct IncorrectMetaItem2 { #[primary_span] pub span: Span, @@ -174,14 +174,14 @@ pub(crate) struct IncorrectMetaItem2 { // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // It is more similar to `IncorrectReprFormatGeneric`. #[derive(SessionDiagnostic)] -#[error(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")] +#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")] pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::invalid_repr_hint_no_paren, code = "E0552")] +#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")] pub(crate) struct InvalidReprHintNoParen { #[primary_span] pub span: Span, @@ -190,7 +190,7 @@ pub(crate) struct InvalidReprHintNoParen { } #[derive(SessionDiagnostic)] -#[error(attr::invalid_repr_hint_no_value, code = "E0552")] +#[diag(attr::invalid_repr_hint_no_value, code = "E0552")] pub(crate) struct InvalidReprHintNoValue { #[primary_span] pub span: Span, @@ -234,8 +234,9 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral { diag } } + #[derive(SessionDiagnostic)] -#[error(attr::invalid_repr_align_need_arg, code = "E0589")] +#[diag(attr::invalid_repr_align_need_arg, code = "E0589")] pub(crate) struct InvalidReprAlignNeedArg { #[primary_span] #[suggestion(code = "align(...)", applicability = "has-placeholders")] @@ -243,7 +244,7 @@ pub(crate) struct InvalidReprAlignNeedArg { } #[derive(SessionDiagnostic)] -#[error(attr::invalid_repr_generic, code = "E0589")] +#[diag(attr::invalid_repr_generic, code = "E0589")] pub(crate) struct InvalidReprGeneric<'a> { #[primary_span] pub span: Span, @@ -253,14 +254,14 @@ pub(crate) struct InvalidReprGeneric<'a> { } #[derive(SessionDiagnostic)] -#[error(attr::incorrect_repr_format_align_one_arg, code = "E0693")] +#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")] pub(crate) struct IncorrectReprFormatAlignOneArg { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::incorrect_repr_format_generic, code = "E0693")] +#[diag(attr::incorrect_repr_format_generic, code = "E0693")] pub(crate) struct IncorrectReprFormatGeneric<'a> { #[primary_span] pub span: Span, @@ -303,28 +304,28 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { } #[derive(SessionDiagnostic)] -#[error(attr::rustc_promotable_pairing, code = "E0717")] +#[diag(attr::rustc_promotable_pairing, code = "E0717")] pub(crate) struct RustcPromotablePairing { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::rustc_allowed_unstable_pairing, code = "E0789")] +#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")] pub(crate) struct RustcAllowedUnstablePairing { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::cfg_predicate_identifier)] +#[diag(attr::cfg_predicate_identifier)] pub(crate) struct CfgPredicateIdentifier { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::deprecated_item_suggestion)] +#[diag(attr::deprecated_item_suggestion)] #[note] pub(crate) struct DeprecatedItemSuggestion { #[primary_span] @@ -335,21 +336,21 @@ pub(crate) struct DeprecatedItemSuggestion { } #[derive(SessionDiagnostic)] -#[error(attr::expected_single_version_literal)] +#[diag(attr::expected_single_version_literal)] pub(crate) struct ExpectedSingleVersionLiteral { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::expected_version_literal)] +#[diag(attr::expected_version_literal)] pub(crate) struct ExpectedVersionLiteral { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(attr::expects_feature_list)] +#[diag(attr::expects_feature_list)] pub(crate) struct ExpectsFeatureList { #[primary_span] pub span: Span, @@ -358,7 +359,7 @@ pub(crate) struct ExpectsFeatureList { } #[derive(SessionDiagnostic)] -#[error(attr::expects_features)] +#[diag(attr::expects_features)] pub(crate) struct ExpectsFeatures { #[primary_span] pub span: Span, @@ -367,14 +368,14 @@ pub(crate) struct ExpectsFeatures { } #[derive(SessionDiagnostic)] -#[error(attr::soft_no_args)] +#[diag(attr::soft_no_args)] pub(crate) struct SoftNoArgs { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[warning(attr::unknown_version_literal)] +#[diag(attr::unknown_version_literal)] pub(crate) struct UnknownVersionLiteral { #[primary_span] pub span: Span, From afd34765f6ef42bd3472040933f07dbb56621565 Mon Sep 17 00:00:00 2001 From: Hampus Lidin Date: Sun, 21 Aug 2022 22:11:41 +0200 Subject: [PATCH 9/9] Move `LitKind` logic to `session_diagnostics` module --- compiler/rustc_attr/src/builtin.rs | 23 +++++-------------- .../rustc_attr/src/session_diagnostics.rs | 17 +++++++++++++- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 17ea47082d446..65edab78ce74e 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -854,6 +854,7 @@ where sess.emit_err(session_diagnostics::DeprecatedItemSuggestion { span: mi.span, is_nightly: sess.is_nightly_build().then_some(()), + details: (), }); } @@ -1021,23 +1022,11 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric { span: item.span(), repr_arg: &name, - cause: match value.kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - Some(IncorrectReprFormatGenericCause::Int { - span: item.span(), - name: &name, - int, - }) - } - ast::LitKind::Str(symbol, _) => { - Some(IncorrectReprFormatGenericCause::Symbol { - span: item.span(), - name: &name, - symbol, - }) - } - _ => None, - }, + cause: IncorrectReprFormatGenericCause::from_lit_kind( + item.span(), + &value.kind, + &name, + ), }); } else { if matches!( diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 34e9815609109..a75e7409fba18 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -1,5 +1,6 @@ use std::num::IntErrorKind; +use rustc_ast as ast; use rustc_errors::{error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_macros::SessionDiagnostic; use rustc_session::{parse::ParseSess, SessionDiagnostic}; @@ -303,6 +304,18 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { }, } +impl<'a> IncorrectReprFormatGenericCause<'a> { + pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option { + match kind { + ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { + Some(Self::Int { span, name, int: *int }) + } + ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }), + _ => None, + } + } +} + #[derive(SessionDiagnostic)] #[diag(attr::rustc_promotable_pairing, code = "E0717")] pub(crate) struct RustcPromotablePairing { @@ -326,13 +339,15 @@ pub(crate) struct CfgPredicateIdentifier { #[derive(SessionDiagnostic)] #[diag(attr::deprecated_item_suggestion)] -#[note] pub(crate) struct DeprecatedItemSuggestion { #[primary_span] pub span: Span, #[help] pub is_nightly: Option<()>, + + #[note] + pub details: (), } #[derive(SessionDiagnostic)]