@@ -416,24 +416,73 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
416
416
}
417
417
}
418
418
419
- /// Extract args from an assert-like macro.
420
- /// Currently working with:
421
- /// - `assert!`, `assert_eq!` and `assert_ne!`
422
- /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
423
- /// For example:
424
- /// `assert!(expr)` will return `Some([expr])`
425
- /// `debug_assert_eq!(a, b)` will return `Some([a, b])`
426
- pub fn extract_assert_macro_args < ' tcx > ( e : & ' tcx Expr < ' tcx > ) -> Option < Vec < & ' tcx Expr < ' tcx > > > {
419
+ /// A parsed
420
+ /// assert!`, `assert_eq!` or `assert_ne!`,
421
+ /// debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
422
+ /// macro.
423
+ pub struct AssertExpn < ' tcx > {
424
+ /// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
425
+ pub first_assert_argument : & ' tcx Expr < ' tcx > ,
426
+ /// second argument of the asset for case `assert_eq!`,
427
+ /// `assert_ne!` etc ... Eg var_2 in `debug_assert_eq!(x, var_2,..)`
428
+ pub second_assert_argument : Option < & ' tcx Expr < ' tcx > > ,
429
+ /// The format argument passed at the end of the macro
430
+ pub format_arg : Option < FormatArgsExpn < ' tcx > > ,
431
+ }
432
+
433
+ impl < ' tcx > AssertExpn < ' tcx > {
434
+ /// Extract args from an assert-like macro.
435
+ /// Currently working with:
436
+ /// - `assert!`, `assert_eq!` and `assert_ne!`
437
+ /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
438
+ /// For example:
439
+ /// `assert!(expr)` will return `Some(AssertExpn { first_assert_argument: expr,
440
+ /// second_assert_argument: None, format_arg:None })` `debug_assert_eq!(a, b)` will return
441
+ /// `Some(AssertExpn { first_assert_argument: a, second_assert_argument: Some(b),
442
+ /// format_arg:None })`
443
+ pub fn parse ( e : & ' tcx Expr < ' tcx > ) -> Option < Self > {
444
+ if let ExprKind :: Block ( block, _) = e. kind {
445
+ if block. stmts . len ( ) == 1 {
446
+ if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
447
+ // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
448
+ if_chain ! {
449
+ if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
450
+ if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
451
+ then {
452
+ return Some ( Self {
453
+ first_assert_argument: condition,
454
+ second_assert_argument: None ,
455
+ format_arg: None , // FIXME actually parse the aguments
456
+ } ) ;
457
+ }
458
+ }
459
+
460
+ // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
461
+ if_chain ! {
462
+ if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
463
+ if let Some ( matchblock_expr) = matchblock. expr;
464
+ then {
465
+ return Self :: ast_matchblock( matchblock_expr) ;
466
+ }
467
+ }
468
+ }
469
+ } else if let Some ( matchblock_expr) = block. expr {
470
+ // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
471
+ return Self :: ast_matchblock ( matchblock_expr) ;
472
+ }
473
+ }
474
+ None
475
+ }
476
+
427
477
/// Try to match the AST for a pattern that contains a match, for example when two args are
428
478
/// compared
429
- fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Vec < & Expr < ' _ > > > {
479
+ fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Self > {
430
480
if_chain ! {
431
481
if let ExprKind :: Match ( headerexpr, arms, _) = & matchblock_expr. kind;
432
482
if let ExprKind :: Tup ( [ lhs, rhs] ) = & headerexpr. kind;
433
483
if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, lhs) = lhs. kind;
434
484
if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, rhs) = rhs. kind;
435
485
then {
436
- let mut vec_arg = vec![ lhs, rhs] ;
437
486
if_chain! {
438
487
if !arms. is_empty( ) ;
439
488
if let ExprKind :: Block ( Block { expr: Some ( if_expr) , ..} , _) = arms[ 0 ] . body. kind;
@@ -444,47 +493,43 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
444
493
| StmtKind :: Semi ( call_assert_failed) = stmts_if_block[ 1 ] . kind;
445
494
if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
446
495
if args_assert_failed. len( ) >= 4 ;
447
- if let ExprKind :: Call ( _, args) = args_assert_failed[ 3 ] . kind;
448
- if !args. is_empty( ) ;
449
- if let Some ( mut format_arg_expn) = FormatArgsExpn :: parse( & args[ 0 ] ) ;
496
+ if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 3 ] . kind;
497
+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( & arg) ;
450
498
then {
451
- vec_arg. push( format_arg_expn. format_string) ;
452
- vec_arg. append( & mut format_arg_expn. value_args) ;
499
+ return Some ( AssertExpn {
500
+ first_assert_argument: lhs,
501
+ second_assert_argument: Some ( rhs) ,
502
+ format_arg: Some ( format_arg_expn)
503
+ } ) ;
504
+ }
505
+ else {
506
+ return Some ( AssertExpn {
507
+ first_assert_argument: lhs,
508
+ second_assert_argument:
509
+ Some ( rhs) ,
510
+ format_arg: None
511
+ } ) ;
453
512
}
454
513
}
455
- return Some ( vec_arg) ;
456
514
}
457
515
}
458
516
None
459
517
}
460
518
461
- if let ExprKind :: Block ( block, _) = e. kind {
462
- if block. stmts . len ( ) == 1 {
463
- if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
464
- // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
465
- if_chain ! {
466
- if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
467
- if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
468
- then {
469
- return Some ( vec![ condition] ) ;
470
- }
471
- }
472
-
473
- // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
474
- if_chain ! {
475
- if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
476
- if let Some ( matchblock_expr) = matchblock. expr;
477
- then {
478
- return ast_matchblock( matchblock_expr) ;
479
- }
480
- }
519
+ /// Gives the argument as a vector
520
+ pub fn argument_vector ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
521
+ let mut expr_vec = vec ! [ self . first_assert_argument] ;
522
+ if let Some ( sec_agr) = self . second_assert_argument {
523
+ expr_vec. push ( sec_agr) ;
524
+ }
525
+ if let Some ( ref format_arg) = self . format_arg {
526
+ expr_vec. push ( format_arg. format_string ) ;
527
+ for arg in & format_arg. value_args {
528
+ expr_vec. push ( arg)
481
529
}
482
- } else if let Some ( matchblock_expr) = block. expr {
483
- // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
484
- return ast_matchblock ( matchblock_expr) ;
485
530
}
531
+ expr_vec
486
532
}
487
- None
488
533
}
489
534
490
535
/// A parsed `format!` expansion
0 commit comments