@@ -421,18 +421,25 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
421421 }
422422}
423423
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+
424432/// A parsed
425433/// `assert!`, `assert_eq!` or `assert_ne!`,
426434/// `debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
427435/// macro.
428436pub 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 > ,
434439 /// The format argument passed at the end of the macro
435440 pub format_arg : Option < FormatArgsExpn < ' tcx > > ,
441+ /// is a debug macro
442+ pub is_debug : bool ,
436443}
437444
438445impl < ' tcx > AssertExpn < ' tcx > {
@@ -445,39 +452,38 @@ impl<'tcx> AssertExpn<'tcx> {
445452 /// second_assert_argument: None, format_arg:None })` `debug_assert_eq!(a, b)` will return
446453 /// `Some(AssertExpn { first_assert_argument: a, second_assert_argument: Some(b),
447454 /// format_arg:None })`
455+ /// FIXME assert!
448456 pub fn parse ( e : & ' tcx Expr < ' tcx > ) -> Option < Self > {
449457 if let ExprKind :: Block ( block, _) = e. kind {
450458 if block. stmts . len ( ) == 1 {
451459 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)`)
453461 if_chain ! {
454462 if let Some ( If { cond, then, .. } ) = If :: hir( matchexpr) ;
455463 if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
456464 then {
457465 if_chain! {
458466 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;
465473 if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
466474 then {
467475 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 ,
478479 } ) ;
479480 }
480481 }
482+ return Some ( Self {
483+ kind: AssertExpnKind :: Bool ( condition) ,
484+ format_arg: None ,
485+ is_debug: true ,
486+ } ) ;
481487 }
482488 }
483489
@@ -486,21 +492,21 @@ impl<'tcx> AssertExpn<'tcx> {
486492 if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
487493 if let Some ( matchblock_expr) = matchblock. expr;
488494 then {
489- return Self :: ast_matchblock( matchblock_expr) ;
495+ return Self :: ast_matchblock( matchblock_expr, true ) ;
490496 }
491497 }
492498 }
493499 } else if let Some ( matchblock_expr) = block. expr {
494500 // 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 ) ;
496502 }
497503 }
498504 None
499505 }
500506
501507 /// Try to match the AST for a pattern that contains a match, for example when two args are
502508 /// 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 > {
504510 if_chain ! {
505511 if let ExprKind :: Match ( headerexpr, arms, _) = & matchblock_expr. kind;
506512 if let ExprKind :: Tup ( [ lhs, rhs] ) = & headerexpr. kind;
@@ -521,32 +527,32 @@ impl<'tcx> AssertExpn<'tcx> {
521527 if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
522528 then {
523529 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,
535533 } ) ;
536534 }
537535 }
536+ return Some ( AssertExpn {
537+ kind: AssertExpnKind :: Eq ( lhs, rhs) ,
538+ format_arg: None ,
539+ is_debug,
540+ } ) ;
538541 }
539542 }
540543 None
541544 }
542545
543546 /// Gives the argument in the comparaison as a vector leaving the format
544547 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+ } ,
548555 }
549- expr_vec
550556 }
551557
552558 /// Gives the argument passed to the macro as a string
@@ -555,14 +561,9 @@ impl<'tcx> AssertExpn<'tcx> {
555561 cx : & LateContext < ' _ > ,
556562 applicability : & mut Applicability ,
557563 ) -> 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) ) ;
566567 }
567568 vec_arg. append ( & mut self . format_arguments ( cx, applicability) ) ;
568569 vec_arg
0 commit comments