Migrate parts of rustc_expand
to session diagnostics
This migrates everything but the `mbe` and `proc_macro` modules. It also contains a few cleanups and drive-by/accidental diagnostic improvements which can be seen in the diff for the UI tests.
This commit is contained in:
parent
a000811405
commit
2f9f097cb8
19 changed files with 640 additions and 236 deletions
|
@ -1,3 +1,11 @@
|
|||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use crate::errors::{
|
||||
ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
|
||||
AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
|
||||
MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
|
||||
ResolveRelativePath, TakesNoArguments,
|
||||
};
|
||||
use crate::expand::{self, AstFragment, Invocation};
|
||||
use crate::module::DirOwnership;
|
||||
|
||||
|
@ -789,26 +797,16 @@ impl SyntaxExtension {
|
|||
.unwrap_or_else(|| (None, helper_attrs));
|
||||
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
|
||||
if let Some((_, sp)) = const_stability {
|
||||
sess.parse_sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(sp, "macros cannot have const stability attributes")
|
||||
.span_label(sp, "invalid const stability attribute")
|
||||
.span_label(
|
||||
sess.source_map().guess_head_span(span),
|
||||
"const stability attribute affects this macro",
|
||||
)
|
||||
.emit();
|
||||
sess.emit_err(MacroConstStability {
|
||||
span: sp,
|
||||
head_span: sess.source_map().guess_head_span(span),
|
||||
});
|
||||
}
|
||||
if let Some((_, sp)) = body_stability {
|
||||
sess.parse_sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(sp, "macros cannot have body stability attributes")
|
||||
.span_label(sp, "invalid body stability attribute")
|
||||
.span_label(
|
||||
sess.source_map().guess_head_span(span),
|
||||
"body stability attribute affects this macro",
|
||||
)
|
||||
.emit();
|
||||
sess.emit_err(MacroBodyStability {
|
||||
span: sp,
|
||||
head_span: sess.source_map().guess_head_span(span),
|
||||
});
|
||||
}
|
||||
|
||||
SyntaxExtension {
|
||||
|
@ -1200,13 +1198,11 @@ pub fn resolve_path(
|
|||
.expect("attempting to resolve a file path in an external file"),
|
||||
FileName::DocTest(path, _) => path,
|
||||
other => {
|
||||
return Err(parse_sess.span_diagnostic.struct_span_err(
|
||||
return Err(ResolveRelativePath {
|
||||
span,
|
||||
&format!(
|
||||
"cannot resolve relative path in non-file source `{}`",
|
||||
parse_sess.source_map().filename_for_diagnostics(&other)
|
||||
),
|
||||
));
|
||||
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
|
||||
}
|
||||
.into_diagnostic(&parse_sess.span_diagnostic));
|
||||
}
|
||||
};
|
||||
result.pop();
|
||||
|
@ -1222,6 +1218,8 @@ pub fn resolve_path(
|
|||
/// The returned bool indicates whether an applicable suggestion has already been
|
||||
/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
|
||||
/// indicates that an ast error was encountered.
|
||||
// FIXME(Nilstrieb) Make this function setup translatable
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub fn expr_to_spanned_string<'a>(
|
||||
cx: &'a mut ExtCtxt<'_>,
|
||||
expr: P<ast::Expr>,
|
||||
|
@ -1280,9 +1278,9 @@ pub fn expr_to_string(
|
|||
/// compilation should call
|
||||
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
|
||||
/// done as rarely as possible).
|
||||
pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) {
|
||||
pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
|
||||
if !tts.is_empty() {
|
||||
cx.span_err(sp, &format!("{} takes no arguments", name));
|
||||
cx.emit_err(TakesNoArguments { span, name });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1304,31 +1302,27 @@ pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
|
|||
/// expect exactly one string literal, or emit an error and return `None`.
|
||||
pub fn get_single_str_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
span: Span,
|
||||
tts: TokenStream,
|
||||
name: &str,
|
||||
) -> Option<Symbol> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
if p.token == token::Eof {
|
||||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
||||
cx.emit_err(OnlyOneArgument { span, name });
|
||||
return None;
|
||||
}
|
||||
let ret = parse_expr(&mut p)?;
|
||||
let _ = p.eat(&token::Comma);
|
||||
|
||||
if p.token != token::Eof {
|
||||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
||||
cx.emit_err(OnlyOneArgument { span, name });
|
||||
}
|
||||
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
|
||||
}
|
||||
|
||||
/// Extracts comma-separated expressions from `tts`.
|
||||
/// On error, emit it, and return `None`.
|
||||
pub fn get_exprs_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> Option<Vec<P<ast::Expr>>> {
|
||||
pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<P<ast::Expr>>> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
let mut es = Vec::new();
|
||||
while p.token != token::Eof {
|
||||
|
@ -1343,7 +1337,7 @@ pub fn get_exprs_from_tts(
|
|||
continue;
|
||||
}
|
||||
if p.token != token::Eof {
|
||||
cx.span_err(sp, "expected token: `,`");
|
||||
cx.emit_err(ExpectedCommaInList { span: p.token.span });
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -1353,64 +1347,58 @@ pub fn get_exprs_from_tts(
|
|||
pub fn parse_macro_name_and_helper_attrs(
|
||||
diag: &rustc_errors::Handler,
|
||||
attr: &Attribute,
|
||||
descr: &str,
|
||||
macro_type: &str,
|
||||
) -> Option<(Symbol, Vec<Symbol>)> {
|
||||
// Once we've located the `#[proc_macro_derive]` attribute, verify
|
||||
// that it's of the form `#[proc_macro_derive(Foo)]` or
|
||||
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
|
||||
let list = attr.meta_item_list()?;
|
||||
if list.len() != 1 && list.len() != 2 {
|
||||
diag.span_err(attr.span, "attribute must have either one or two arguments");
|
||||
diag.emit_err(AttrNoArguments { span: attr.span });
|
||||
return None;
|
||||
}
|
||||
let Some(trait_attr) = list[0].meta_item() else {
|
||||
diag.span_err(list[0].span(), "not a meta item");
|
||||
diag.emit_err(NotAMetaItem {span: list[0].span()});
|
||||
return None;
|
||||
};
|
||||
let trait_ident = match trait_attr.ident() {
|
||||
Some(trait_ident) if trait_attr.is_word() => trait_ident,
|
||||
_ => {
|
||||
diag.span_err(trait_attr.span, "must only be one word");
|
||||
diag.emit_err(OnlyOneWord { span: trait_attr.span });
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
if !trait_ident.name.can_be_raw() {
|
||||
diag.span_err(
|
||||
trait_attr.span,
|
||||
&format!("`{}` cannot be a name of {} macro", trait_ident, descr),
|
||||
);
|
||||
diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
|
||||
}
|
||||
|
||||
let attributes_attr = list.get(1);
|
||||
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
|
||||
if !attr.has_name(sym::attributes) {
|
||||
diag.span_err(attr.span(), "second argument must be `attributes`");
|
||||
diag.emit_err(ArgumentNotAttributes { span: attr.span() });
|
||||
}
|
||||
attr.meta_item_list()
|
||||
.unwrap_or_else(|| {
|
||||
diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
|
||||
diag.emit_err(AttributesWrongForm { span: attr.span() });
|
||||
&[]
|
||||
})
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
let Some(attr) = attr.meta_item() else {
|
||||
diag.span_err(attr.span(), "not a meta item");
|
||||
diag.emit_err(AttributeMetaItem { span: attr.span() });
|
||||
return None;
|
||||
};
|
||||
|
||||
let ident = match attr.ident() {
|
||||
Some(ident) if attr.is_word() => ident,
|
||||
_ => {
|
||||
diag.span_err(attr.span, "must only be one word");
|
||||
diag.emit_err(AttributeSingleWord { span: attr.span });
|
||||
return None;
|
||||
}
|
||||
};
|
||||
if !ident.name.can_be_raw() {
|
||||
diag.span_err(
|
||||
attr.span,
|
||||
&format!("`{}` cannot be a name of derive helper attribute", ident),
|
||||
);
|
||||
diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
|
||||
}
|
||||
|
||||
Some(ident.name)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue