Skip to content

Commit

Permalink
Auto merge of #106745 - m-ou-se:format-args-ast, r=oli-obk
Browse files Browse the repository at this point in the history
Move format_args!() into AST (and expand it during AST lowering)

Implements rust-lang/compiler-team#541

This moves FormatArgs from rustc_builtin_macros to rustc_ast_lowering. For now, the end result is the same. But this allows for future changes to do smarter things with format_args!(). It also allows Clippy to directly access the ast::FormatArgs, making things a lot easier.

This change turns the format args types into lang items. The builtin macro used to refer to them by their path. After this change, the path is no longer relevant, making it easier to make changes in `core`.

This updates clippy to use the new language items, but this doesn't yet make clippy use the ast::FormatArgs structure that's now available. That should be done after this is merged.
  • Loading branch information
bors committed Jan 26, 2023
2 parents 40fda7b + db731e4 commit 3e97763
Show file tree
Hide file tree
Showing 32 changed files with 750 additions and 449 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3729,6 +3729,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 @@ -1499,6 +1501,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 @@ -1425,6 +1438,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 @@ -896,6 +908,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

0 comments on commit 3e97763

Please sign in to comment.