1+ mod context;
2+
13use crate :: edition_panic:: use_panic_2021;
24use rustc_ast:: ptr:: P ;
35use rustc_ast:: token;
46use rustc_ast:: tokenstream:: { DelimSpan , TokenStream } ;
5- use rustc_ast:: { self as ast , * } ;
7+ use rustc_ast:: { Expr , ExprKind , MacArgs , MacCall , MacDelimiter , Path , PathSegment , UnOp } ;
68use rustc_ast_pretty:: pprust;
79use rustc_errors:: { Applicability , PResult } ;
8- use rustc_expand:: base:: * ;
10+ use rustc_expand:: base:: { DummyResult , ExtCtxt , MacEager , MacResult } ;
911use rustc_parse:: parser:: Parser ;
1012use rustc_span:: symbol:: { sym, Ident , Symbol } ;
1113use rustc_span:: { Span , DUMMY_SP } ;
@@ -25,13 +27,13 @@ pub fn expand_assert<'cx>(
2527
2628 // `core::panic` and `std::panic` are different macros, so we use call-site
2729 // context to pick up whichever is currently in scope.
28- let sp = cx. with_call_site_ctxt ( span) ;
30+ let call_site_span = cx. with_call_site_ctxt ( span) ;
2931
30- let panic_call = if let Some ( tokens ) = custom_message {
31- let path = if use_panic_2021 ( span) {
32+ let panic_path = || {
33+ if use_panic_2021 ( span) {
3234 // On edition 2021, we always call `$crate::panic::panic_2021!()`.
3335 Path {
34- span : sp ,
36+ span : call_site_span ,
3537 segments : cx
3638 . std_path ( & [ sym:: panic, sym:: panic_2021] )
3739 . into_iter ( )
@@ -42,27 +44,40 @@ pub fn expand_assert<'cx>(
4244 } else {
4345 // Before edition 2021, we call `panic!()` unqualified,
4446 // such that it calls either `std::panic!()` or `core::panic!()`.
45- Path :: from_ident ( Ident :: new ( sym:: panic, sp) )
46- } ;
47- // Pass the custom message to panic!().
48- cx. expr (
49- sp,
47+ Path :: from_ident ( Ident :: new ( sym:: panic, call_site_span) )
48+ }
49+ } ;
50+
51+ // Simply uses the user provided message instead of generating custom outputs
52+ let expr = if let Some ( tokens) = custom_message {
53+ let then = cx. expr (
54+ call_site_span,
5055 ExprKind :: MacCall ( MacCall {
51- path,
56+ path : panic_path ( ) ,
5257 args : P ( MacArgs :: Delimited (
53- DelimSpan :: from_single ( sp ) ,
58+ DelimSpan :: from_single ( call_site_span ) ,
5459 MacDelimiter :: Parenthesis ,
5560 tokens,
5661 ) ) ,
5762 prior_type_ascription : None ,
5863 } ) ,
59- )
60- } else {
64+ ) ;
65+ expr_if_not ( cx, call_site_span, cond_expr, then, None )
66+ }
67+ // If `generic_assert` is enabled, generates rich captured outputs
68+ //
69+ // FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
70+ else if let Some ( features) = cx. ecfg . features && features. generic_assert {
71+ context:: Context :: new ( cx, call_site_span) . build ( cond_expr, panic_path ( ) )
72+ }
73+ // If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
74+ // string
75+ else {
6176 // Pass our own message directly to $crate::panicking::panic(),
6277 // because it might contain `{` and `}` that should always be
6378 // passed literally.
64- cx. expr_call_global (
65- sp ,
79+ let then = cx. expr_call_global (
80+ call_site_span ,
6681 cx. std_path ( & [ sym:: panicking, sym:: panic] ) ,
6782 vec ! [ cx. expr_str(
6883 DUMMY_SP ,
@@ -71,18 +86,29 @@ pub fn expand_assert<'cx>(
7186 pprust:: expr_to_string( & cond_expr) . escape_debug( )
7287 ) ) ,
7388 ) ] ,
74- )
89+ ) ;
90+ expr_if_not ( cx, call_site_span, cond_expr, then, None )
7591 } ;
76- let if_expr =
77- cx. expr_if ( sp, cx. expr ( sp, ExprKind :: Unary ( UnOp :: Not , cond_expr) ) , panic_call, None ) ;
78- MacEager :: expr ( if_expr)
92+
93+ MacEager :: expr ( expr)
7994}
8095
8196struct Assert {
82- cond_expr : P < ast :: Expr > ,
97+ cond_expr : P < Expr > ,
8398 custom_message : Option < TokenStream > ,
8499}
85100
101+ // if !{ ... } { ... } else { ... }
102+ fn expr_if_not (
103+ cx : & ExtCtxt < ' _ > ,
104+ span : Span ,
105+ cond : P < Expr > ,
106+ then : P < Expr > ,
107+ els : Option < P < Expr > > ,
108+ ) -> P < Expr > {
109+ cx. expr_if ( span, cx. expr ( span, ExprKind :: Unary ( UnOp :: Not , cond) ) , then, els)
110+ }
111+
86112fn parse_assert < ' a > ( cx : & mut ExtCtxt < ' a > , sp : Span , stream : TokenStream ) -> PResult < ' a , Assert > {
87113 let mut parser = cx. new_parser_from_tts ( stream) ;
88114
0 commit comments