mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Refactor diagnostics in handle_errors
function
This commit is contained in:
parent
e0dc8d7801
commit
0005f628f0
@ -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::<Vec<_>>();
|
||||
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,
|
||||
),
|
||||
);
|
||||
|
@ -10,6 +10,7 @@
|
||||
extern crate rustc_macros;
|
||||
|
||||
mod builtin;
|
||||
mod session_diagnostics;
|
||||
|
||||
pub use builtin::*;
|
||||
pub use IntType::*;
|
||||
|
196
compiler/rustc_attr/src/session_diagnostics.rs
Normal file
196
compiler/rustc_attr/src/session_diagnostics.rs
Normal file
@ -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<InvalidIssueStringCause>,
|
||||
}
|
||||
|
||||
// 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<Self> {
|
||||
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::<Vec<_>>();
|
||||
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
|
||||
}
|
||||
}
|
29
compiler/rustc_error_messages/locales/en-US/attr.ftl
Normal file
29
compiler/rustc_error_messages/locales/en-US/attr.ftl
Normal file
@ -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
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user