diff options
Diffstat (limited to 'compiler/rustc_expand/src/base.rs')
-rw-r--r-- | compiler/rustc_expand/src/base.rs | 133 |
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")) |