Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new proc macro diagnostics API #83363

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ dependencies = [
"cargo-test-macro",
"cargo-test-support",
"cargo-util",
"clap 3.1.1",
"clap 3.1.6",
"crates-io",
"crossbeam-utils",
"curl",
Expand Down Expand Up @@ -599,17 +599,17 @@ dependencies = [

[[package]]
name = "clap"
version = "3.1.1"
version = "3.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7"
checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123"
dependencies = [
"atty",
"bitflags",
"indexmap",
"os_str_bytes",
"strsim 0.10.0",
"termcolor",
"textwrap 0.14.2",
"textwrap 0.15.0",
]

[[package]]
Expand Down Expand Up @@ -5025,9 +5025,9 @@ dependencies = [

[[package]]
name = "textwrap"
version = "0.14.2"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"

[[package]]
name = "thiserror"
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_expand/src/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ impl ToInternal<rustc_errors::Level> for Level {
fn to_internal(self) -> rustc_errors::Level {
match self {
Level::Error => rustc_errors::Level::Error { lint: false },
Level::Warning => rustc_errors::Level::Warning,
Level::Note => rustc_errors::Level::Note,
Level::Help => rustc_errors::Level::Help,
_ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
Expand Down Expand Up @@ -396,7 +395,7 @@ impl server::Types for Rustc<'_, '_> {
type Ident = Ident;
type Literal = Literal;
type SourceFile = Lrc<SourceFile>;
type MultiSpan = Vec<Span>;
type MultiSpan = MultiSpan;
type Diagnostic = Diagnostic;
type Span = Span;
}
Expand Down Expand Up @@ -749,17 +748,20 @@ impl server::SourceFile for Rustc<'_, '_> {

impl server::MultiSpan for Rustc<'_, '_> {
fn new(&mut self) -> Self::MultiSpan {
vec![]
MultiSpan::new()
}
fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
spans.push(span)
fn push_primary_span(&mut self, multispan: &mut Self::MultiSpan, span: Self::Span) {
multispan.push_primary_span(span)
}
fn push_span_label(&mut self, spans: &mut Self::MultiSpan, span: Self::Span, label: String) {
spans.push_span_label(span, label)
}
}

impl server::Diagnostic for Rustc<'_, '_> {
fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
let mut diag = Diagnostic::new(level.to_internal(), msg);
diag.set_span(MultiSpan::from_spans(spans));
diag.set_span(spans);
diag
}
fn sub(
Expand All @@ -769,7 +771,7 @@ impl server::Diagnostic for Rustc<'_, '_> {
msg: &str,
spans: Self::MultiSpan,
) {
diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
diag.sub(level.to_internal(), msg, spans, None);
}
fn emit(&mut self, diag: Self::Diagnostic) {
self.sess().span_diagnostic.emit_diagnostic(&diag);
Expand Down
63 changes: 36 additions & 27 deletions compiler/rustc_macros/src/session_diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![deny(unused_must_use)]
use proc_macro::Diagnostic;
use quote::{format_ident, quote};
use syn::spanned::Spanned;

Expand Down Expand Up @@ -105,8 +104,17 @@ impl SessionDiagnosticDeriveError {
}
}

fn span_err(span: impl proc_macro::MultiSpan, msg: &str) -> proc_macro::Diagnostic {
Diagnostic::spanned(span, proc_macro::Level::Error, msg)
macro_rules! with_help {
($diag:expr, $msg:expr) => {{
#[cfg(bootstrap)]
{
$diag.help($msg)
}
#[cfg(not(bootstrap))]
{
$diag.with_help($msg)
}
}};
}

/// For methods that return a Result<_, SessionDiagnosticDeriveError>: emit a diagnostic on
Expand All @@ -122,11 +130,11 @@ macro_rules! throw_span_err {
/// When possible, prefer using throw_span_err! over using this function directly. This only exists
/// as a function to constrain `f` to an impl FnOnce.
fn _throw_span_err(
span: impl proc_macro::MultiSpan,
span: proc_macro::Span,
msg: &str,
f: impl FnOnce(proc_macro::Diagnostic) -> proc_macro::Diagnostic,
) -> SessionDiagnosticDeriveError {
let diag = span_err(span, msg);
let diag = span.error(msg);
f(diag).emit();
SessionDiagnosticDeriveError::ErrorHandled
}
Expand Down Expand Up @@ -194,8 +202,10 @@ impl<'a> SessionDiagnosticDerive<'a> {
// Finally, putting it altogether.
match builder.kind {
None => {
span_err(ast.span().unwrap(), "`code` not specified")
.help("use the [code = \"...\"] attribute to set this diagnostic's error code ")
with_help!(
ast.span().unwrap().error("`code` not specified"),
"use the [code = \"...\"] attribute to set this diagnostic's error code"
)
.emit();
SessionDiagnosticDeriveError::ErrorHandled.to_compile_error()
}
Expand All @@ -215,11 +225,10 @@ impl<'a> SessionDiagnosticDerive<'a> {
},
}
} else {
span_err(
ast.span().unwrap(),
"`#[derive(SessionDiagnostic)]` can only be used on structs",
)
.emit();
ast.span()
.unwrap()
.error("`#[derive(SessionDiagnostic)]` can only be used on structs")
.emit();
SessionDiagnosticDeriveError::ErrorHandled.to_compile_error()
}
};
Expand Down Expand Up @@ -481,17 +490,19 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
throw_span_err!(
info.span.unwrap(),
"wrong types for suggestion",
|diag| {
diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)")
}
|diag| with_help!(
diag,
"#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)"
)
);
}
_ => throw_span_err!(
info.span.unwrap(),
"wrong field type for suggestion",
|diag| {
diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)")
}
|diag| with_help!(
diag,
"#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)"
)
),
})()?;
// Now read the key-value pairs.
Expand Down Expand Up @@ -537,9 +548,10 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
throw_span_err!(
list.span().unwrap(),
"missing suggestion message",
|diag| {
diag.help("provide a suggestion message using #[suggestion(message = \"...\")]")
}
|diag| with_help!(
diag,
"provide a suggestion message using #[suggestion(message = \"...\")]"
)
);
};
let code = code.unwrap_or_else(|| quote! { String::new() });
Expand Down Expand Up @@ -626,12 +638,9 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
}
} else {
// This field doesn't exist. Emit a diagnostic.
Diagnostic::spanned(
span.unwrap(),
proc_macro::Level::Error,
format!("`{}` doesn't refer to a field on this type", field),
)
.emit();
span.unwrap()
.error(&format!("`{}` doesn't refer to a field on this type", field))
.emit();
quote! {
"{#field}"
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,10 @@ impl MultiSpan {
MultiSpan { primary_spans: vec, span_labels: vec![] }
}

pub fn push_primary_span(&mut self, span: Span) {
self.primary_spans.push(span);
}

pub fn push_span_label(&mut self, span: Span, label: String) {
self.span_labels.push((span, label));
}
Expand Down
4 changes: 2 additions & 2 deletions library/proc_macro/src/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ macro_rules! with_api {
MultiSpan {
fn drop($self: $S::MultiSpan);
fn new() -> $S::MultiSpan;
fn push($self: &mut $S::MultiSpan, span: $S::Span);
fn push_primary_span($self: &mut $S::MultiSpan, span: $S::Span);
fn push_span_label($self: &mut $S::MultiSpan, span: $S::Span, label: String);
},
Diagnostic {
fn drop($self: $S::Diagnostic);
Expand Down Expand Up @@ -378,7 +379,6 @@ rpc_encode_decode!(
rpc_encode_decode!(
enum Level {
Error,
Warning,
Note,
Help,
}
Expand Down
Loading