@@ -421,18 +421,25 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
421
421
}
422
422
}
423
423
424
+ /// Kind of assert macros
425
+ pub enum AssertExpnKind < ' tcx > {
426
+ /// Boolean macro like `assert!` or `debug_assert!`
427
+ Bool ( & ' tcx Expr < ' tcx > ) ,
428
+ /// Comparaison maacro like `assert_eq!`, `assert_ne!`, `debug_assert_eq!` or `debug_assert_ne!`
429
+ Eq ( & ' tcx Expr < ' tcx > , & ' tcx Expr < ' tcx > ) ,
430
+ }
431
+
424
432
/// A parsed
425
433
/// `assert!`, `assert_eq!` or `assert_ne!`,
426
434
/// `debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
427
435
/// macro.
428
436
pub struct AssertExpn < ' tcx > {
429
- /// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
430
- pub first_assert_argument : & ' tcx Expr < ' tcx > ,
431
- /// second argument of the asset for case `assert_eq!`,
432
- /// `assert_ne!` etc ... Eg var_2 in `debug_assert_eq!(x, var_2,..)`
433
- pub second_assert_argument : Option < & ' tcx Expr < ' tcx > > ,
437
+ /// Kind of assert macro
438
+ pub kind : AssertExpnKind < ' tcx > ,
434
439
/// The format argument passed at the end of the macro
435
440
pub format_arg : Option < FormatArgsExpn < ' tcx > > ,
441
+ /// is a debug macro
442
+ pub is_debug : bool ,
436
443
}
437
444
438
445
impl < ' tcx > AssertExpn < ' tcx > {
@@ -445,39 +452,38 @@ impl<'tcx> AssertExpn<'tcx> {
445
452
/// second_assert_argument: None, format_arg:None })` `debug_assert_eq!(a, b)` will return
446
453
/// `Some(AssertExpn { first_assert_argument: a, second_assert_argument: Some(b),
447
454
/// format_arg:None })`
455
+ /// FIXME assert!
448
456
pub fn parse ( e : & ' tcx Expr < ' tcx > ) -> Option < Self > {
449
457
if let ExprKind :: Block ( block, _) = e. kind {
450
458
if block. stmts . len ( ) == 1 {
451
459
if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
452
- // macros with unique arg: `{debug_}assert !` (e.g., `debug_assert!(some_condition)`)
460
+ // debug macros with unique arg: `debug_assert !` (e.g., `debug_assert!(some_condition)`)
453
461
if_chain ! {
454
462
if let Some ( If { cond, then, .. } ) = If :: hir( matchexpr) ;
455
463
if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
456
464
then {
457
465
if_chain! {
458
466
if let ExprKind :: Block ( block, _) = then. kind;
459
- if let [ statement , .. ] = block. stmts ;
460
- if let StmtKind :: Expr ( call_assert_failed )
461
- | StmtKind :: Semi ( call_assert_failed ) = statement . kind ;
462
- if let ExprKind :: Call ( _, args_assert_failed ) = call_assert_failed . kind;
463
- if !args_assert_failed . is_empty( ) ;
464
- if let ExprKind :: Call ( _, [ arg , .. ] ) = args_assert_failed [ 0 ] . kind;
467
+ if let Some ( begin_panic_fmt_block ) = block. expr ;
468
+ if let ExprKind :: Block ( block , _ ) = begin_panic_fmt_block . kind ;
469
+ if let Some ( expr ) = block . expr ;
470
+ if let ExprKind :: Call ( _, args_begin_panic_fmt ) = expr . kind;
471
+ if !args_begin_panic_fmt . is_empty( ) ;
472
+ if let ExprKind :: AddrOf ( _, _ , arg ) = args_begin_panic_fmt [ 0 ] . kind;
465
473
if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
466
474
then {
467
475
return Some ( Self {
468
- first_assert_argument: condition,
469
- second_assert_argument: None ,
470
- format_arg: Some ( format_arg_expn) , // FIXME actually parse the aguments
471
- } ) ;
472
- }
473
- else{
474
- return Some ( Self {
475
- first_assert_argument: condition,
476
- second_assert_argument: None ,
477
- format_arg: None ,
476
+ kind: AssertExpnKind :: Bool ( condition) ,
477
+ format_arg: Some ( format_arg_expn) ,
478
+ is_debug: true ,
478
479
} ) ;
479
480
}
480
481
}
482
+ return Some ( Self {
483
+ kind: AssertExpnKind :: Bool ( condition) ,
484
+ format_arg: None ,
485
+ is_debug: true ,
486
+ } ) ;
481
487
}
482
488
}
483
489
@@ -486,21 +492,21 @@ impl<'tcx> AssertExpn<'tcx> {
486
492
if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
487
493
if let Some ( matchblock_expr) = matchblock. expr;
488
494
then {
489
- return Self :: ast_matchblock( matchblock_expr) ;
495
+ return Self :: ast_matchblock( matchblock_expr, true ) ;
490
496
}
491
497
}
492
498
}
493
499
} else if let Some ( matchblock_expr) = block. expr {
494
500
// macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
495
- return Self :: ast_matchblock ( matchblock_expr) ;
501
+ return Self :: ast_matchblock ( matchblock_expr, false ) ;
496
502
}
497
503
}
498
504
None
499
505
}
500
506
501
507
/// Try to match the AST for a pattern that contains a match, for example when two args are
502
508
/// compared
503
- fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Self > {
509
+ fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > , is_debug : bool ) -> Option < Self > {
504
510
if_chain ! {
505
511
if let ExprKind :: Match ( headerexpr, arms, _) = & matchblock_expr. kind;
506
512
if let ExprKind :: Tup ( [ lhs, rhs] ) = & headerexpr. kind;
@@ -521,32 +527,32 @@ impl<'tcx> AssertExpn<'tcx> {
521
527
if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
522
528
then {
523
529
return Some ( AssertExpn {
524
- first_assert_argument: lhs,
525
- second_assert_argument: Some ( rhs) ,
526
- format_arg: Some ( format_arg_expn)
527
- } ) ;
528
- }
529
- else {
530
- return Some ( AssertExpn {
531
- first_assert_argument: lhs,
532
- second_assert_argument:
533
- Some ( rhs) ,
534
- format_arg: None
530
+ kind: AssertExpnKind :: Eq ( lhs, rhs) ,
531
+ format_arg: Some ( format_arg_expn) ,
532
+ is_debug,
535
533
} ) ;
536
534
}
537
535
}
536
+ return Some ( AssertExpn {
537
+ kind: AssertExpnKind :: Eq ( lhs, rhs) ,
538
+ format_arg: None ,
539
+ is_debug,
540
+ } ) ;
538
541
}
539
542
}
540
543
None
541
544
}
542
545
543
546
/// Gives the argument in the comparaison as a vector leaving the format
544
547
pub fn assert_arguments ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
545
- let mut expr_vec = vec ! [ self . first_assert_argument] ;
546
- if let Some ( sec_agr) = self . second_assert_argument {
547
- expr_vec. push ( sec_agr) ;
548
+ match self . kind {
549
+ AssertExpnKind :: Bool ( expr) => {
550
+ vec ! [ expr]
551
+ } ,
552
+ AssertExpnKind :: Eq ( lhs, rhs) => {
553
+ vec ! [ lhs, rhs]
554
+ } ,
548
555
}
549
- expr_vec
550
556
}
551
557
552
558
/// Gives the argument passed to the macro as a string
@@ -555,14 +561,9 @@ impl<'tcx> AssertExpn<'tcx> {
555
561
cx : & LateContext < ' _ > ,
556
562
applicability : & mut Applicability ,
557
563
) -> Vec < Cow < ' static , str > > {
558
- let mut vec_arg = vec ! [ snippet_with_applicability(
559
- cx,
560
- self . first_assert_argument. span,
561
- ".." ,
562
- applicability,
563
- ) ] ;
564
- if let Some ( sec_agr) = self . second_assert_argument {
565
- vec_arg. push ( snippet_with_applicability ( cx, sec_agr. span , ".." , applicability) ) ;
564
+ let mut vec_arg = vec ! [ ] ;
565
+ for arg in self . assert_arguments ( ) {
566
+ vec_arg. push ( snippet_with_applicability ( cx, arg. span , ".." , applicability) ) ;
566
567
}
567
568
vec_arg. append ( & mut self . format_arguments ( cx, applicability) ) ;
568
569
vec_arg
0 commit comments