1
1
#![ allow( clippy:: similar_names) ] // `expr` and `expn`
2
2
3
- use crate :: is_path_diagnostic_item;
4
3
use crate :: source:: snippet_opt;
5
4
use crate :: visitors:: { for_each_expr, Descend } ;
6
5
7
6
use arrayvec:: ArrayVec ;
8
7
use itertools:: { izip, Either , Itertools } ;
9
8
use rustc_ast:: ast:: LitKind ;
10
9
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 } ;
12
11
use rustc_lexer:: unescape:: unescape_literal;
13
12
use rustc_lexer:: { tokenize, unescape, LiteralKind , TokenKind } ;
14
13
use rustc_lint:: LateContext ;
@@ -439,8 +438,7 @@ impl<'tcx> FormatArgsValues<'tcx> {
439
438
// ArgumentV1::from_usize(<val>)
440
439
if let ExprKind :: Call ( callee, [ val] ) = expr. kind
441
440
&& 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
444
442
{
445
443
let val_idx = if val. span . ctxt ( ) == expr. span . ctxt ( )
446
444
&& let ExprKind :: Field ( _, field) = val. kind
@@ -486,20 +484,6 @@ struct ParamPosition {
486
484
487
485
impl < ' tcx > Visitor < ' tcx > for ParamPosition {
488
486
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
-
503
487
match field. ident . name {
504
488
sym:: position => {
505
489
if let ExprKind :: Lit ( lit) = & field. expr . kind
@@ -519,15 +503,41 @@ impl<'tcx> Visitor<'tcx> for ParamPosition {
519
503
}
520
504
}
521
505
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
+
522
520
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
523
521
fn parse_rt_fmt < ' tcx > ( fmt_arg : & ' tcx Expr < ' tcx > ) -> Option < impl Iterator < Item = ParamPosition > + ' tcx > {
524
522
if let ExprKind :: AddrOf ( .., array) = fmt_arg. kind
525
523
&& let ExprKind :: Array ( specs) = array. kind
526
524
{
527
525
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
+ }
531
541
} ) )
532
542
} else {
533
543
None
@@ -890,7 +900,7 @@ impl<'tcx> FormatArgsExpn<'tcx> {
890
900
// ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
891
901
if let ExprKind :: Call ( callee, [ pieces, args, rest @ ..] ) = expr. kind
892
902
&& 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
894
904
&& matches ! ( seg. ident. as_str( ) , "new_v1" | "new_v1_formatted" )
895
905
{
896
906
let format_string = FormatString :: new ( cx, pieces) ?;
0 commit comments