11#![ allow( clippy:: similar_names) ] // `expr` and `expn`
22
3- use crate :: is_path_diagnostic_item;
43use crate :: source:: snippet_opt;
54use crate :: visitors:: { for_each_expr, Descend } ;
65
76use arrayvec:: ArrayVec ;
87use itertools:: { izip, Either , Itertools } ;
98use rustc_ast:: ast:: LitKind ;
109use 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 } ;
1211use rustc_lexer:: unescape:: unescape_literal;
1312use rustc_lexer:: { tokenize, unescape, LiteralKind , TokenKind } ;
1413use 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
487485impl < ' 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, _)`
523521fn 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) ?;
0 commit comments