Move some functions from rustc_expand
to rustc_builtin_macros
.
These functions are only used in `rustc_builtin_macros`, so it makes sense for them to live there. This allows them to be changed from `pub` to `pub(crate)`.
This commit is contained in:
parent
e2d2b1c698
commit
8dc84fa7d1
14 changed files with 234 additions and 237 deletions
|
@ -1,3 +1,5 @@
|
|||
use crate::errors;
|
||||
use crate::util::expr_to_spanned_string;
|
||||
use ast::token::IdentIsRaw;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -16,8 +18,6 @@ use rustc_span::{ErrorGuaranteed, InnerSpan, Span};
|
|||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
pub struct AsmArgs {
|
||||
pub templates: Vec<P<ast::Expr>>,
|
||||
pub operands: Vec<(ast::InlineAsmOperand, Span)>,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// The compiler code necessary to support the compile_error! extension.
|
||||
|
||||
use crate::util::get_single_str_from_tts;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_expand::base::get_single_str_from_tts;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use crate::errors;
|
||||
use crate::util::get_exprs_from_tts;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{ExprKind, LitKind, UnOp};
|
||||
use rustc_expand::base::get_exprs_from_tts;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
pub fn expand_concat(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: rustc_span::Span,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use crate::errors;
|
||||
use crate::util::get_exprs_from_tts;
|
||||
use rustc_ast::{ptr::P, token, tokenstream::TokenStream, ExprKind, LitIntType, LitKind, UintTy};
|
||||
use rustc_expand::base::get_exprs_from_tts;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
/// Emits errors for literal expressions that are invalid inside and outside of an array.
|
||||
fn invalid_type_err(
|
||||
cx: &ExtCtxt<'_>,
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
// interface.
|
||||
//
|
||||
|
||||
use crate::errors;
|
||||
use crate::util::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts};
|
||||
use rustc_ast::token::{self, LitKind};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability};
|
||||
use rustc_expand::base::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
@ -14,8 +15,6 @@ use std::env;
|
|||
use std::env::VarError;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Result<Symbol, VarError> {
|
||||
let var = var.as_str();
|
||||
if let Some(value) = cx.sess.opts.logical_env.get(var) {
|
||||
|
|
|
@ -842,3 +842,26 @@ pub(crate) struct ExpectedRegisterClassOrExplicitRegister {
|
|||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_expected_comma_in_list)]
|
||||
pub(crate) struct ExpectedCommaInList {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_only_one_argument)]
|
||||
pub(crate) struct OnlyOneArgument<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_takes_no_arguments)]
|
||||
pub(crate) struct TakesNoArguments<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::errors;
|
||||
use crate::util::expr_to_spanned_string;
|
||||
use parse::Position::ArgumentNamed;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
|
@ -10,14 +12,13 @@ use rustc_ast::{
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans};
|
||||
use rustc_expand::base::*;
|
||||
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
|
||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId};
|
||||
use rustc_parse::parser::Recovered;
|
||||
use rustc_parse_format as parse;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span};
|
||||
|
||||
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
|
||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId};
|
||||
|
||||
// The format_args!() macro is expanded in three steps:
|
||||
// 1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax,
|
||||
// but doesn't parse the template (the literal) itself.
|
||||
|
@ -38,8 +39,6 @@ enum PositionUsedAs {
|
|||
}
|
||||
use PositionUsedAs::*;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MacroInput {
|
||||
fmtstr: P<Expr>,
|
||||
|
|
|
@ -50,13 +50,13 @@ mod pattern_type;
|
|||
mod source_util;
|
||||
mod test;
|
||||
mod trace_macros;
|
||||
mod util;
|
||||
|
||||
pub mod asm;
|
||||
pub mod cmdline_attrs;
|
||||
pub mod proc_macro_harness;
|
||||
pub mod standard_library_imports;
|
||||
pub mod test_harness;
|
||||
pub mod util;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use crate::util::{
|
||||
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
|
||||
};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
|
@ -5,11 +8,8 @@ use rustc_ast::tokenstream::TokenStream;
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_expand::base::{
|
||||
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
|
||||
resolve_path,
|
||||
resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult,
|
||||
};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt};
|
||||
use rustc_expand::base::{MacEager, MacResult, MacroExpanderResult};
|
||||
use rustc_expand::module::DirOwnership;
|
||||
use rustc_parse::new_parser_from_file;
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
use rustc_ast::{attr, AttrStyle, Attribute, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use crate::errors;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{self as ast, attr, ptr::P, token, AttrStyle, Attribute, MetaItem};
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
|
||||
use rustc_expand::expand::AstFragment;
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_parse::{parser, validate_attr};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
|
||||
pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
|
||||
// All the built-in macro attributes are "words" at the moment.
|
||||
|
@ -46,3 +51,178 @@ pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `Ok` represents successfully retrieving the string literal at the correct
|
||||
/// position, e.g., `println("abc")`.
|
||||
type ExprToSpannedStringResult<'a> = Result<(Symbol, ast::StrStyle, Span), UnexpectedExprKind<'a>>;
|
||||
|
||||
/// - `Ok` is returned when the conversion to a string literal is unsuccessful,
|
||||
/// but another type of expression is obtained instead.
|
||||
/// - `Err` is returned when the conversion process fails.
|
||||
type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>;
|
||||
|
||||
/// Extracts a string literal from the macro expanded version of `expr`,
|
||||
/// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
|
||||
/// The returned bool indicates whether an applicable suggestion has already been
|
||||
/// added to the diagnostic to avoid emitting multiple suggestions. `Err(Err(ErrorGuaranteed))`
|
||||
/// indicates that an ast error was encountered.
|
||||
// FIXME(Nilstrieb) Make this function setup translatable
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(crate) fn expr_to_spanned_string<'a>(
|
||||
cx: &'a mut ExtCtxt<'_>,
|
||||
expr: P<ast::Expr>,
|
||||
err_msg: &'static str,
|
||||
) -> ExpandResult<ExprToSpannedStringResult<'a>, ()> {
|
||||
if !cx.force_mode
|
||||
&& let ast::ExprKind::MacCall(m) = &expr.kind
|
||||
&& cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err()
|
||||
{
|
||||
return ExpandResult::Retry(());
|
||||
}
|
||||
|
||||
// Perform eager expansion on the expression.
|
||||
// We want to be able to handle e.g., `concat!("foo", "bar")`.
|
||||
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
|
||||
|
||||
ExpandResult::Ready(Err(match expr.kind {
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Str(s, style)) => {
|
||||
return ExpandResult::Ready(Ok((s, style, expr.span)));
|
||||
}
|
||||
Ok(ast::LitKind::ByteStr(..)) => {
|
||||
let mut err = cx.dcx().struct_span_err(expr.span, err_msg);
|
||||
let span = expr.span.shrink_to_lo();
|
||||
err.span_suggestion(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the leading `b`",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
Ok((err, true))
|
||||
}
|
||||
Ok(ast::LitKind::Err(guar)) => Err(guar),
|
||||
Err(err) => Err(report_lit_error(&cx.sess.psess, err, token_lit, expr.span)),
|
||||
_ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)),
|
||||
},
|
||||
ast::ExprKind::Err(guar) => Err(guar),
|
||||
ast::ExprKind::Dummy => {
|
||||
cx.dcx().span_bug(expr.span, "tried to get a string literal from `ExprKind::Dummy`")
|
||||
}
|
||||
_ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Extracts a string literal from the macro expanded version of `expr`,
|
||||
/// emitting `err_msg` if `expr` is not a string literal. This does not stop
|
||||
/// compilation on error, merely emits a non-fatal error and returns `Err`.
|
||||
pub(crate) fn expr_to_string(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
expr: P<ast::Expr>,
|
||||
err_msg: &'static str,
|
||||
) -> ExpandResult<Result<(Symbol, ast::StrStyle), ErrorGuaranteed>, ()> {
|
||||
expr_to_spanned_string(cx, expr, err_msg).map(|res| {
|
||||
res.map_err(|err| match err {
|
||||
Ok((err, _)) => err.emit(),
|
||||
Err(guar) => guar,
|
||||
})
|
||||
.map(|(symbol, style, _)| (symbol, style))
|
||||
})
|
||||
}
|
||||
|
||||
/// Non-fatally assert that `tts` is empty. Note that this function
|
||||
/// returns even when `tts` is non-empty, macros that *need* to stop
|
||||
/// compilation should call `cx.diagnostic().abort_if_errors()`
|
||||
/// (this should be done as rarely as possible).
|
||||
pub(crate) fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
|
||||
if !tts.is_empty() {
|
||||
cx.dcx().emit_err(errors::TakesNoArguments { span, name });
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an expression. On error, emit it, advancing to `Eof`, and return `Err`.
|
||||
pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result<P<ast::Expr>, ErrorGuaranteed> {
|
||||
let guar = match p.parse_expr() {
|
||||
Ok(expr) => return Ok(expr),
|
||||
Err(err) => err.emit(),
|
||||
};
|
||||
while p.token != token::Eof {
|
||||
p.bump();
|
||||
}
|
||||
Err(guar)
|
||||
}
|
||||
|
||||
/// Interpreting `tts` as a comma-separated sequence of expressions,
|
||||
/// expect exactly one string literal, or emit an error and return `Err`.
|
||||
pub(crate) fn get_single_str_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
tts: TokenStream,
|
||||
name: &str,
|
||||
) -> ExpandResult<Result<Symbol, ErrorGuaranteed>, ()> {
|
||||
get_single_str_spanned_from_tts(cx, span, tts, name).map(|res| res.map(|(s, _)| s))
|
||||
}
|
||||
|
||||
pub(crate) fn get_single_str_spanned_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
tts: TokenStream,
|
||||
name: &str,
|
||||
) -> ExpandResult<Result<(Symbol, Span), ErrorGuaranteed>, ()> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
if p.token == token::Eof {
|
||||
let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
|
||||
return ExpandResult::Ready(Err(guar));
|
||||
}
|
||||
let ret = match parse_expr(&mut p) {
|
||||
Ok(ret) => ret,
|
||||
Err(guar) => return ExpandResult::Ready(Err(guar)),
|
||||
};
|
||||
let _ = p.eat(&token::Comma);
|
||||
|
||||
if p.token != token::Eof {
|
||||
cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
|
||||
}
|
||||
expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| {
|
||||
res.map_err(|err| match err {
|
||||
Ok((err, _)) => err.emit(),
|
||||
Err(guar) => guar,
|
||||
})
|
||||
.map(|(symbol, _style, span)| (symbol, span))
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts comma-separated expressions from `tts`.
|
||||
/// On error, emit it, and return `Err`.
|
||||
pub(crate) fn get_exprs_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
tts: TokenStream,
|
||||
) -> ExpandResult<Result<Vec<P<ast::Expr>>, ErrorGuaranteed>, ()> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
let mut es = Vec::new();
|
||||
while p.token != token::Eof {
|
||||
let expr = match parse_expr(&mut p) {
|
||||
Ok(expr) => expr,
|
||||
Err(guar) => return ExpandResult::Ready(Err(guar)),
|
||||
};
|
||||
if !cx.force_mode
|
||||
&& let ast::ExprKind::MacCall(m) = &expr.kind
|
||||
&& cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err()
|
||||
{
|
||||
return ExpandResult::Retry(());
|
||||
}
|
||||
|
||||
// Perform eager expansion on the expression.
|
||||
// We want to be able to handle e.g., `concat!("foo", "bar")`.
|
||||
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
|
||||
|
||||
es.push(expr);
|
||||
if p.eat(&token::Comma) {
|
||||
continue;
|
||||
}
|
||||
if p.token != token::Eof {
|
||||
let guar = cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span });
|
||||
return ExpandResult::Ready(Err(guar));
|
||||
}
|
||||
}
|
||||
ExpandResult::Ready(Ok(es))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue