about summary refs log tree commit diff
path: root/compiler/rustc_session/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-09-08 00:58:43 +0000
committerbors <bors@rust-lang.org>2020-09-08 00:58:43 +0000
commit71569e420107ab034910a4687f382385975fa0b3 (patch)
treee98903281ee0502675b01212bded5148710b6d90 /compiler/rustc_session/src
parent0e2c1281e909ca38479b97962fc9248f75d66412 (diff)
parent5956254172ab2bb6fd7c98faf51509925341c321 (diff)
downloadrust-71569e420107ab034910a4687f382385975fa0b3.tar.gz
rust-71569e420107ab034910a4687f382385975fa0b3.zip
Auto merge of #75138 - jumbatm:session-diagnostic-derive, r=oli-obk
Add derive macro for specifying diagnostics using attributes.

Introduces `#[derive(SessionDiagnostic)]`, a derive macro for specifying structs that can be converted to Diagnostics using directions given by attributes on the struct and its fields. Currently, the following attributes have been implemented:
- `#[code = "..."]` -- this sets the Diagnostic's error code, and must be provided on the struct iself (ie, not on a field). Equivalent to calling `code`.
- `#[message = "..."]` -- this sets the Diagnostic's primary error message.
- `#[label = "..."]` -- this must be applied to fields of type `Span`, and is equivalent to `span_label`
- `#[suggestion(..)]` -- this allows a suggestion message to be supplied. This attribute must be applied to a field of type `Span` or `(Span, Applicability)`, and is equivalent to calling `span_suggestion`. Valid arguments are:
    - `message = "..."` -- this sets the suggestion message.
    - (Optional) `code = "..."` -- this suggests code for the suggestion. Defaults to empty.

`suggestion`also  comes with other variants: `#[suggestion_short(..)]`, `#[suggestion_hidden(..)]` and `#[suggestion_verbose(..)]` which all take the same keys.

Within the strings passed to each attribute, fields can be referenced without needing to be passed explicitly into the format string -- eg, `#[error = "{ident} already declared"] ` will set the error message to `format!("{} already declared", &self.ident)`. Any fields on the struct can be referenced in this way.

Additionally, for any of these attributes, Option fields can be used to only optionally apply the decoration -- for example:

```rust
#[derive(SessionDiagnostic)]
#[code = "E0123"]
struct SomeKindOfError {
    ...
    #[suggestion(message = "informative error message")]
    opt_sugg: Option<(Span, Applicability)>
    ...
}
```
will not emit a suggestion if `opt_sugg` is `None`.

We plan on iterating on this macro further; this PR is a start.

Closes #61132.

r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_session/src')
-rw-r--r--compiler/rustc_session/src/session.rs11
1 files changed, 11 insertions, 0 deletions
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index ff22b4ce4ad..974f4c31bb6 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -237,6 +237,14 @@ enum DiagnosticBuilderMethod {
                             // Add more variants as needed to support one-time diagnostics.
 }
 
+/// Trait implemented by error types. This should not be implemented manually. Instead, use
+/// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
+pub trait SessionDiagnostic<'a> {
+    /// Write out as a diagnostic out of `sess`.
+    #[must_use]
+    fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a>;
+}
+
 /// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid
 /// emitting the same message more than once.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -392,6 +400,9 @@ impl Session {
     pub fn err(&self, msg: &str) {
         self.diagnostic().err(msg)
     }
+    pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) {
+        err.into_diagnostic(self).emit()
+    }
     pub fn err_count(&self) -> usize {
         self.diagnostic().err_count()
     }