summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_expand/src/base.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_expand/src/base.rs')
-rw-r--r--compiler/rustc_expand/src/base.rs133
1 files changed, 61 insertions, 72 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 9d6a4f9a1..951d59246 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -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;
@@ -23,12 +31,11 @@ use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
+use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-use std::default::Default;
use std::iter;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::rc::Rc;
pub(crate) use rustc_span::hygiene::MacroKind;
@@ -56,21 +63,21 @@ pub enum Annotatable {
impl Annotatable {
pub fn span(&self) -> Span {
- match *self {
- Annotatable::Item(ref item) => item.span,
- Annotatable::TraitItem(ref trait_item) => trait_item.span,
- Annotatable::ImplItem(ref impl_item) => impl_item.span,
- Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
- Annotatable::Stmt(ref stmt) => stmt.span,
- Annotatable::Expr(ref expr) => expr.span,
- Annotatable::Arm(ref arm) => arm.span,
- Annotatable::ExprField(ref field) => field.span,
- Annotatable::PatField(ref fp) => fp.pat.span,
- Annotatable::GenericParam(ref gp) => gp.ident.span,
- Annotatable::Param(ref p) => p.span,
- Annotatable::FieldDef(ref sf) => sf.span,
- Annotatable::Variant(ref v) => v.span,
- Annotatable::Crate(ref c) => c.spans.inner_span,
+ match self {
+ Annotatable::Item(item) => item.span,
+ Annotatable::TraitItem(trait_item) => trait_item.span,
+ Annotatable::ImplItem(impl_item) => impl_item.span,
+ Annotatable::ForeignItem(foreign_item) => foreign_item.span,
+ Annotatable::Stmt(stmt) => stmt.span,
+ Annotatable::Expr(expr) => expr.span,
+ Annotatable::Arm(arm) => arm.span,
+ Annotatable::ExprField(field) => field.span,
+ Annotatable::PatField(fp) => fp.pat.span,
+ Annotatable::GenericParam(gp) => gp.ident.span,
+ Annotatable::Param(p) => p.span,
+ Annotatable::FieldDef(sf) => sf.span,
+ Annotatable::Variant(v) => v.span,
+ Annotatable::Crate(c) => c.spans.inner_span,
}
}
@@ -789,26 +796,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 +1197,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 +1217,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>,
@@ -1234,7 +1231,7 @@ pub fn expr_to_spanned_string<'a>(
Err(match expr.kind {
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)),
- Ok(ast::LitKind::ByteStr(_)) => {
+ Ok(ast::LitKind::ByteStr(..)) => {
let mut err = cx.struct_span_err(expr.span, err_msg);
let span = expr.span.shrink_to_lo();
err.span_suggestion(
@@ -1280,9 +1277,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 +1301,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 +1336,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 +1346,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)
@@ -1436,8 +1423,10 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
if let [variant] = &*enum_def.variants {
if variant.ident.name == sym::Input {
let filename = sess.source_map().span_to_filename(item.ident.span);
- if let FileName::Real(RealFileName::LocalPath(path)) = filename {
- if let Some(c) = path
+ if let FileName::Real(real) = filename {
+ if let Some(c) = real
+ .local_path()
+ .unwrap_or(Path::new(""))
.components()
.flat_map(|c| c.as_os_str().to_str())
.find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))