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