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

Move format_args!() into AST (and expand it during AST lowering) #106745

Merged
merged 20 commits into from
Jan 26, 2023
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3699,6 +3699,7 @@ name = "rustc_ast_pretty"
version = "0.0.0"
dependencies = [
"rustc_ast",
"rustc_parse_format",
"rustc_span",
]

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//! - [`Attribute`]: Metadata associated with item.
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.

pub use crate::format::*;
pub use crate::util::parser::ExprPrecedence;
pub use GenericArgs::*;
pub use UnsafeSource::*;
Expand Down Expand Up @@ -1269,6 +1270,7 @@ impl Expr {
ExprKind::Try(..) => ExprPrecedence::Try,
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Yeet(..) => ExprPrecedence::Yeet,
ExprKind::FormatArgs(..) => ExprPrecedence::FormatArgs,
ExprKind::Err => ExprPrecedence::Err,
}
}
Expand Down Expand Up @@ -1498,6 +1500,9 @@ pub enum ExprKind {
/// with a `ByteStr` literal.
IncludedBytes(Lrc<[u8]>),

/// A `format_args!()` expression.
FormatArgs(P<FormatArgs>),

/// Placeholder for an expression that wasn't syntactically well formed in some way.
Err,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_ast::ptr::P;
use rustc_ast::Expr;
use crate::ptr::P;
use crate::Expr;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
Expand Down Expand Up @@ -39,7 +39,7 @@ use rustc_span::Span;
/// Basically the "AST" for a complete `format_args!()`.
///
/// E.g., `format_args!("hello {name}");`.
#[derive(Clone, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FormatArgs {
pub span: Span,
pub template: Vec<FormatArgsPiece>,
Expand All @@ -49,7 +49,7 @@ pub struct FormatArgs {
/// A piece of a format template string.
///
/// E.g. "hello" or "{name}".
#[derive(Clone, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FormatArgsPiece {
Literal(Symbol),
Placeholder(FormatPlaceholder),
Expand All @@ -59,14 +59,20 @@ pub enum FormatArgsPiece {
///
/// E.g. `1, 2, name="ferris", n=3`,
/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
#[derive(Clone, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FormatArguments {
arguments: Vec<FormatArgument>,
num_unnamed_args: usize,
num_explicit_args: usize,
names: FxHashMap<Symbol, usize>,
}

// FIXME: Rustdoc has trouble proving Send/Sync for this. See #106930.
#[cfg(parallel_compiler)]
unsafe impl Sync for FormatArguments {}
#[cfg(parallel_compiler)]
unsafe impl Send for FormatArguments {}

impl FormatArguments {
pub fn new() -> Self {
Self {
Expand Down Expand Up @@ -121,18 +127,22 @@ impl FormatArguments {
&self.arguments[..self.num_explicit_args]
}

pub fn into_vec(self) -> Vec<FormatArgument> {
self.arguments
pub fn all_args(&self) -> &[FormatArgument] {
&self.arguments[..]
}

pub fn all_args_mut(&mut self) -> &mut [FormatArgument] {
&mut self.arguments[..]
}
}

#[derive(Clone, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FormatArgument {
pub kind: FormatArgumentKind,
pub expr: P<Expr>,
}

#[derive(Clone, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FormatArgumentKind {
/// `format_args(…, arg)`
Normal,
Expand All @@ -152,7 +162,7 @@ impl FormatArgumentKind {
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub struct FormatPlaceholder {
/// Index into [`FormatArgs::arguments`].
pub argument: FormatArgPosition,
Expand All @@ -164,7 +174,7 @@ pub struct FormatPlaceholder {
pub format_options: FormatOptions,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub struct FormatArgPosition {
/// Which argument this position refers to (Ok),
/// or would've referred to if it existed (Err).
Expand All @@ -175,7 +185,7 @@ pub struct FormatArgPosition {
pub span: Option<Span>,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatArgPositionKind {
/// `{}` or `{:.*}`
Implicit,
Expand All @@ -185,7 +195,7 @@ pub enum FormatArgPositionKind {
Named,
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq, Hash)]
pub enum FormatTrait {
/// `{}`
Display,
Expand All @@ -207,7 +217,7 @@ pub enum FormatTrait {
UpperHex,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[derive(Clone, Encodable, Decodable, Default, Debug, PartialEq, Eq)]
pub struct FormatOptions {
/// The width. E.g. `{:5}` or `{:width$}`.
pub width: Option<FormatCount>,
Expand All @@ -221,7 +231,7 @@ pub struct FormatOptions {
pub flags: u32,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatAlignment {
/// `{:<}`
Left,
Expand All @@ -231,7 +241,7 @@ pub enum FormatAlignment {
Center,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatCount {
/// `{:5}` or `{:.5}`
Literal(usize),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub mod ast_traits;
pub mod attr;
pub mod entry;
pub mod expand;
pub mod format;
pub mod mut_visit;
pub mod node_id;
pub mod ptr;
Expand All @@ -51,6 +52,7 @@ pub mod visit;

pub use self::ast::*;
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasSpan, HasTokens};
pub use self::format::*;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ pub trait MutVisitor: Sized {
fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
noop_visit_inline_asm_sym(sym, self)
}

fn visit_format_args(&mut self, fmt: &mut FormatArgs) {
noop_visit_format_args(fmt, self)
}
}

/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
Expand Down Expand Up @@ -1284,6 +1288,15 @@ pub fn noop_visit_inline_asm_sym<T: MutVisitor>(
vis.visit_path(path);
}

pub fn noop_visit_format_args<T: MutVisitor>(fmt: &mut FormatArgs, vis: &mut T) {
for arg in fmt.arguments.all_args_mut() {
if let FormatArgumentKind::Named(name) = &mut arg.kind {
vis.visit_ident(name);
}
vis.visit_expr(&mut arg.expr);
}
}

pub fn noop_visit_expr<T: MutVisitor>(
Expr { kind, id, span, attrs, tokens }: &mut Expr,
vis: &mut T,
Expand Down Expand Up @@ -1423,6 +1436,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
visit_opt(expr, |expr| vis.visit_expr(expr));
}
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(se) => {
let StructExpr { qself, path, fields, rest } = se.deref_mut();
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_ast/src/util/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ pub enum ExprPrecedence {
Try,
InlineAsm,
Mac,
FormatArgs,

Array,
Repeat,
Expand Down Expand Up @@ -335,7 +336,8 @@ impl ExprPrecedence {
| ExprPrecedence::Index
| ExprPrecedence::Try
| ExprPrecedence::InlineAsm
| ExprPrecedence::Mac => PREC_POSTFIX,
| ExprPrecedence::Mac
| ExprPrecedence::FormatArgs => PREC_POSTFIX,

// Never need parens
ExprPrecedence::Array
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
walk_inline_asm(self, asm)
}
fn visit_format_args(&mut self, fmt: &'ast FormatArgs) {
walk_format_args(self, fmt)
}
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
walk_inline_asm_sym(self, sym)
}
Expand Down Expand Up @@ -756,6 +759,15 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineA
visitor.visit_path(&sym.path, sym.id);
}

pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) {
for arg in fmt.arguments.all_args() {
if let FormatArgumentKind::Named(name) = arg.kind {
visitor.visit_ident(name);
}
visitor.visit_expr(&arg.expr);
}
}

pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
walk_list!(visitor, visit_attribute, expression.attrs.iter());

Expand Down Expand Up @@ -895,6 +907,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::MacCall(mac) => visitor.visit_mac_call(mac),
ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
ExprKind::FormatArgs(f) => visitor.visit_format_args(f),
ExprKind::Yield(optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
Expand Down
Loading