Skip to content

Commit a64940f

Browse files
committed
Auto merge of rust-lang#106745 - m-ou-se:format-args-ast, r=oli-obk
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.
2 parents 2d8ede2 + 2bcd697 commit a64940f

File tree

3 files changed

+36
-25
lines changed

3 files changed

+36
-25
lines changed

clippy_lints/src/format_args.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ use clippy_utils::macros::{
77
};
88
use clippy_utils::msrvs::{self, Msrv};
99
use clippy_utils::source::snippet_opt;
10-
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
10+
use clippy_utils::ty::{implements_trait, is_type_lang_item};
1111
use if_chain::if_chain;
1212
use itertools::Itertools;
1313
use rustc_errors::{
1414
Applicability,
1515
SuggestionStyle::{CompletelyHidden, ShowCode},
1616
};
17-
use rustc_hir::{Expr, ExprKind, HirId, QPath};
17+
use rustc_hir::{Expr, ExprKind, HirId, LangItem, QPath};
1818
use rustc_lint::{LateContext, LateLintPass, LintContext};
1919
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
2020
use rustc_middle::ty::Ty;
@@ -237,7 +237,7 @@ fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) {
237237
);
238238
}
239239

240-
if is_type_diagnostic_item(cx, param_ty, sym::Arguments) && !arg.format.is_default_for_trait() {
240+
if is_type_lang_item(cx, param_ty, LangItem::FormatArguments) && !arg.format.is_default_for_trait() {
241241
span_lint_and_then(
242242
cx,
243243
UNUSED_FORMAT_SPECS,

clippy_utils/src/macros.rs

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#![allow(clippy::similar_names)] // `expr` and `expn`
22

3-
use crate::is_path_diagnostic_item;
43
use crate::source::snippet_opt;
54
use crate::visitors::{for_each_expr, Descend};
65

76
use arrayvec::ArrayVec;
87
use itertools::{izip, Either, Itertools};
98
use rustc_ast::ast::LitKind;
109
use rustc_hir::intravisit::{walk_expr, Visitor};
11-
use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, Node, QPath};
10+
use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, LangItem, Node, QPath, TyKind};
1211
use rustc_lexer::unescape::unescape_literal;
1312
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
1413
use rustc_lint::LateContext;
@@ -439,8 +438,7 @@ impl<'tcx> FormatArgsValues<'tcx> {
439438
// ArgumentV1::from_usize(<val>)
440439
if let ExprKind::Call(callee, [val]) = expr.kind
441440
&& let ExprKind::Path(QPath::TypeRelative(ty, _)) = callee.kind
442-
&& let hir::TyKind::Path(QPath::Resolved(_, path)) = ty.kind
443-
&& path.segments.last().unwrap().ident.name == sym::ArgumentV1
441+
&& let TyKind::Path(QPath::LangItem(LangItem::FormatArgument, _, _)) = ty.kind
444442
{
445443
let val_idx = if val.span.ctxt() == expr.span.ctxt()
446444
&& let ExprKind::Field(_, field) = val.kind
@@ -486,20 +484,6 @@ struct ParamPosition {
486484

487485
impl<'tcx> Visitor<'tcx> for ParamPosition {
488486
fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) {
489-
fn parse_count(expr: &Expr<'_>) -> Option<usize> {
490-
// ::core::fmt::rt::v1::Count::Param(1usize),
491-
if let ExprKind::Call(ctor, [val]) = expr.kind
492-
&& let ExprKind::Path(QPath::Resolved(_, path)) = ctor.kind
493-
&& path.segments.last()?.ident.name == sym::Param
494-
&& let ExprKind::Lit(lit) = &val.kind
495-
&& let LitKind::Int(pos, _) = lit.node
496-
{
497-
Some(pos as usize)
498-
} else {
499-
None
500-
}
501-
}
502-
503487
match field.ident.name {
504488
sym::position => {
505489
if let ExprKind::Lit(lit) = &field.expr.kind
@@ -519,15 +503,41 @@ impl<'tcx> Visitor<'tcx> for ParamPosition {
519503
}
520504
}
521505

506+
fn parse_count(expr: &Expr<'_>) -> Option<usize> {
507+
// <::core::fmt::rt::v1::Count>::Param(1usize),
508+
if let ExprKind::Call(ctor, [val]) = expr.kind
509+
&& let ExprKind::Path(QPath::TypeRelative(_, path)) = ctor.kind
510+
&& path.ident.name == sym::Param
511+
&& let ExprKind::Lit(lit) = &val.kind
512+
&& let LitKind::Int(pos, _) = lit.node
513+
{
514+
Some(pos as usize)
515+
} else {
516+
None
517+
}
518+
}
519+
522520
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
523521
fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
524522
if let ExprKind::AddrOf(.., array) = fmt_arg.kind
525523
&& let ExprKind::Array(specs) = array.kind
526524
{
527525
Some(specs.iter().map(|spec| {
528-
let mut position = ParamPosition::default();
529-
position.visit_expr(spec);
530-
position
526+
if let ExprKind::Call(f, args) = spec.kind
527+
&& let ExprKind::Path(QPath::TypeRelative(ty, f)) = f.kind
528+
&& let TyKind::Path(QPath::LangItem(LangItem::FormatPlaceholder, _, _)) = ty.kind
529+
&& f.ident.name == sym::new
530+
&& let [position, _fill, _align, _flags, precision, width] = args
531+
&& let ExprKind::Lit(position) = &position.kind
532+
&& let LitKind::Int(position, _) = position.node {
533+
ParamPosition {
534+
value: position as usize,
535+
width: parse_count(width),
536+
precision: parse_count(precision),
537+
}
538+
} else {
539+
ParamPosition::default()
540+
}
531541
}))
532542
} else {
533543
None
@@ -890,7 +900,7 @@ impl<'tcx> FormatArgsExpn<'tcx> {
890900
// ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
891901
if let ExprKind::Call(callee, [pieces, args, rest @ ..]) = expr.kind
892902
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
893-
&& is_path_diagnostic_item(cx, ty, sym::Arguments)
903+
&& let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
894904
&& matches!(seg.ident.as_str(), "new_v1" | "new_v1_formatted")
895905
{
896906
let format_string = FormatString::new(cx, pieces)?;

clippy_utils/src/sugg.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ impl<'a> Sugg<'a> {
219219
| ast::ExprKind::Repeat(..)
220220
| ast::ExprKind::Ret(..)
221221
| ast::ExprKind::Yeet(..)
222+
| ast::ExprKind::FormatArgs(..)
222223
| ast::ExprKind::Struct(..)
223224
| ast::ExprKind::Try(..)
224225
| ast::ExprKind::TryBlock(..)

0 commit comments

Comments
 (0)