macros: optional error codes
In an effort to make it easier to port diagnostics to `SessionDiagnostic` (for translation) and since translation slugs could replace error codes, make error codes optional in the `SessionDiagnostic` derive. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
70ee0c96fc
commit
72dec56028
3 changed files with 21 additions and 34 deletions
|
@ -229,38 +229,30 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||||
|
|
||||||
let span = ast.span().unwrap();
|
let span = ast.span().unwrap();
|
||||||
let (diag, sess) = (&builder.diag, &builder.sess);
|
let (diag, sess) = (&builder.diag, &builder.sess);
|
||||||
let init = match (builder.kind, builder.slug, builder.code) {
|
let init = match (builder.kind, builder.slug) {
|
||||||
(None, _, _) => {
|
(None, _) => {
|
||||||
span_err(span, "diagnostic kind not specified")
|
span_err(span, "diagnostic kind not specified")
|
||||||
.help("use the `#[error(...)]` attribute to create an error")
|
.help("use the `#[error(...)]` attribute to create an error")
|
||||||
.emit();
|
.emit();
|
||||||
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
}
|
}
|
||||||
(Some((kind, _)), None, _) => {
|
(Some((kind, _)), None) => {
|
||||||
span_err(span, "`slug` not specified")
|
span_err(span, "`slug` not specified")
|
||||||
.help(&format!("use the `#[{}(slug = \"...\")]` attribute to set this diagnostic's slug", kind.descr()))
|
.help(&format!("use the `#[{}(slug = \"...\")]` attribute to set this diagnostic's slug", kind.descr()))
|
||||||
.emit();
|
.emit();
|
||||||
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
}
|
}
|
||||||
(Some((kind, _)), _, None) => {
|
(Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => {
|
||||||
span_err(span, "`code` not specified")
|
|
||||||
.help(&format!("use the `#[{}(code = \"...\")]` attribute to set this diagnostic's error code", kind.descr()))
|
|
||||||
.emit();
|
|
||||||
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
|
||||||
}
|
|
||||||
(Some((SessionDiagnosticKind::Error, _)), Some((slug, _)), Some((code, _))) => {
|
|
||||||
quote! {
|
quote! {
|
||||||
let mut #diag = #sess.struct_err_with_code(
|
let mut #diag = #sess.struct_err(
|
||||||
rustc_errors::DiagnosticMessage::fluent(#slug),
|
rustc_errors::DiagnosticMessage::fluent(#slug),
|
||||||
rustc_errors::DiagnosticId::Error(#code.to_string())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Some((SessionDiagnosticKind::Warn, _)), Some((slug, _)), Some((code, _))) => {
|
(Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => {
|
||||||
quote! {
|
quote! {
|
||||||
let mut #diag = #sess.struct_warn_with_code(
|
let mut #diag = #sess.struct_warn(
|
||||||
rustc_errors::DiagnosticMessage::fluent(#slug),
|
rustc_errors::DiagnosticMessage::fluent(#slug),
|
||||||
rustc_errors::DiagnosticId::Error(#code.to_string())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,9 +355,9 @@ struct SessionDiagnosticDeriveBuilder<'a> {
|
||||||
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
||||||
/// has the actual diagnostic message.
|
/// has the actual diagnostic message.
|
||||||
slug: Option<(String, proc_macro::Span)>,
|
slug: Option<(String, proc_macro::Span)>,
|
||||||
/// Error codes are a mandatory part of the struct attribute. Slugs may replace error codes
|
/// Error codes are a optional part of the struct attribute - this is only set to detect
|
||||||
/// in future but it is desirable to mandate error codes until such a time.
|
/// multiple specifications.
|
||||||
code: Option<(String, proc_macro::Span)>,
|
code: Option<proc_macro::Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
|
@ -403,6 +395,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
};
|
};
|
||||||
self.set_kind_once(kind, span)?;
|
self.set_kind_once(kind, span)?;
|
||||||
|
|
||||||
|
let mut tokens = Vec::new();
|
||||||
for attr in nested {
|
for attr in nested {
|
||||||
let span = attr.span().unwrap();
|
let span = attr.span().unwrap();
|
||||||
let meta = match attr {
|
let meta = match attr {
|
||||||
|
@ -427,7 +420,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
self.set_slug_once(s.value(), s.span().unwrap());
|
self.set_slug_once(s.value(), s.span().unwrap());
|
||||||
}
|
}
|
||||||
"code" => {
|
"code" => {
|
||||||
self.set_code_once(s.value(), s.span().unwrap());
|
tokens.push(self.set_code_once(s.value(), s.span().unwrap()));
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
let diag = span_err(
|
let diag = span_err(
|
||||||
|
@ -475,7 +468,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(quote! {})
|
Ok(tokens.drain(..).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -504,17 +497,20 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_code_once(&mut self, code: String, span: proc_macro::Span) {
|
fn set_code_once(&mut self, code: String, span: proc_macro::Span) -> proc_macro2::TokenStream {
|
||||||
match self.code {
|
match self.code {
|
||||||
None => {
|
None => {
|
||||||
self.code = Some((code, span));
|
self.code = Some(span);
|
||||||
}
|
}
|
||||||
Some((_, prev_span)) => {
|
Some(prev_span) => {
|
||||||
span_err(span, "`code` specified multiple times")
|
span_err(span, "`code` specified multiple times")
|
||||||
.span_note(prev_span, "previously specified here")
|
.span_note(prev_span, "previously specified here")
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let diag = &self.diag;
|
||||||
|
quote! { #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_slug_once(&mut self, slug: String, span: proc_macro::Span) {
|
fn set_slug_once(&mut self, slug: String, span: proc_macro::Span) {
|
||||||
|
|
|
@ -115,7 +115,7 @@ struct KindNotProvided {} //~ ERROR diagnostic kind not specified
|
||||||
struct SlugNotProvided {}
|
struct SlugNotProvided {}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(slug = "foo")] //~ ERROR `code` not specified
|
#[error(slug = "foo")]
|
||||||
struct CodeNotProvided {}
|
struct CodeNotProvided {}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
|
|
|
@ -147,15 +147,6 @@ LL | | struct SlugNotProvided {}
|
||||||
|
|
|
|
||||||
= help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
|
= help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
|
||||||
|
|
||||||
error: `code` not specified
|
|
||||||
--> $DIR/session-derive-errors.rs:118:1
|
|
||||||
|
|
|
||||||
LL | / #[error(slug = "foo")]
|
|
||||||
LL | | struct CodeNotProvided {}
|
|
||||||
| |_________________________^
|
|
||||||
|
|
|
||||||
= help: use the `#[error(code = "...")]` attribute to set this diagnostic's error code
|
|
||||||
|
|
||||||
error: the `#[primary_span]` attribute can only be applied to fields of type `Span`
|
error: the `#[primary_span]` attribute can only be applied to fields of type `Span`
|
||||||
--> $DIR/session-derive-errors.rs:124:5
|
--> $DIR/session-derive-errors.rs:124:5
|
||||||
|
|
|
|
||||||
|
@ -285,6 +276,6 @@ LL | #[derive(SessionDiagnostic)]
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 35 previous errors
|
error: aborting due to 34 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0599`.
|
For more information about this error, try `rustc --explain E0599`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue