@@ -418,24 +418,73 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
418418 }
419419}
420420
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+
429479 /// Try to match the AST for a pattern that contains a match, for example when two args are
430480 /// compared
431- fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Vec < & Expr < ' _ > > > {
481+ fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Self > {
432482 if_chain ! {
433483 if let ExprKind :: Match ( headerexpr, arms, _) = & matchblock_expr. kind;
434484 if let ExprKind :: Tup ( [ lhs, rhs] ) = & headerexpr. kind;
435485 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, lhs) = lhs. kind;
436486 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, rhs) = rhs. kind;
437487 then {
438- let mut vec_arg = vec![ lhs, rhs] ;
439488 if_chain! {
440489 if !arms. is_empty( ) ;
441490 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
446495 | StmtKind :: Semi ( call_assert_failed) = stmts_if_block[ 1 ] . kind;
447496 if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
448497 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) ;
452500 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+ } ) ;
455514 }
456515 }
457- return Some ( vec_arg) ;
458516 }
459517 }
460518 None
461519 }
462520
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)
483531 }
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) ;
487532 }
533+ expr_vec
488534 }
489- None
490535}
491536
492537/// A parsed `format!` expansion
0 commit comments