1
+ mod context;
2
+
1
3
use crate :: edition_panic:: use_panic_2021;
2
4
use rustc_ast:: ptr:: P ;
3
5
use rustc_ast:: token;
4
6
use rustc_ast:: tokenstream:: { DelimSpan , TokenStream } ;
5
- use rustc_ast:: { self as ast , * } ;
7
+ use rustc_ast:: { Expr , ExprKind , MacArgs , MacCall , MacDelimiter , Path , PathSegment , UnOp } ;
6
8
use rustc_ast_pretty:: pprust;
7
9
use rustc_errors:: { Applicability , PResult } ;
8
- use rustc_expand:: base:: * ;
10
+ use rustc_expand:: base:: { DummyResult , ExtCtxt , MacEager , MacResult } ;
9
11
use rustc_parse:: parser:: Parser ;
10
12
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
11
13
use rustc_span:: { Span , DUMMY_SP } ;
@@ -25,13 +27,13 @@ pub fn expand_assert<'cx>(
25
27
26
28
// `core::panic` and `std::panic` are different macros, so we use call-site
27
29
// 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) ;
29
31
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) {
32
34
// On edition 2021, we always call `$crate::panic::panic_2021!()`.
33
35
Path {
34
- span : sp ,
36
+ span : call_site_span ,
35
37
segments : cx
36
38
. std_path ( & [ sym:: panic, sym:: panic_2021] )
37
39
. into_iter ( )
@@ -42,27 +44,40 @@ pub fn expand_assert<'cx>(
42
44
} else {
43
45
// Before edition 2021, we call `panic!()` unqualified,
44
46
// 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,
50
55
ExprKind :: MacCall ( MacCall {
51
- path,
56
+ path : panic_path ( ) ,
52
57
args : P ( MacArgs :: Delimited (
53
- DelimSpan :: from_single ( sp ) ,
58
+ DelimSpan :: from_single ( call_site_span ) ,
54
59
MacDelimiter :: Parenthesis ,
55
60
tokens,
56
61
) ) ,
57
62
prior_type_ascription : None ,
58
63
} ) ,
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 {
61
76
// Pass our own message directly to $crate::panicking::panic(),
62
77
// because it might contain `{` and `}` that should always be
63
78
// passed literally.
64
- cx. expr_call_global (
65
- sp ,
79
+ let then = cx. expr_call_global (
80
+ call_site_span ,
66
81
cx. std_path ( & [ sym:: panicking, sym:: panic] ) ,
67
82
vec ! [ cx. expr_str(
68
83
DUMMY_SP ,
@@ -71,18 +86,29 @@ pub fn expand_assert<'cx>(
71
86
pprust:: expr_to_string( & cond_expr) . escape_debug( )
72
87
) ) ,
73
88
) ] ,
74
- )
89
+ ) ;
90
+ expr_if_not ( cx, call_site_span, cond_expr, then, None )
75
91
} ;
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)
79
94
}
80
95
81
96
struct Assert {
82
- cond_expr : P < ast :: Expr > ,
97
+ cond_expr : P < Expr > ,
83
98
custom_message : Option < TokenStream > ,
84
99
}
85
100
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
+
86
112
fn parse_assert < ' a > ( cx : & mut ExtCtxt < ' a > , sp : Span , stream : TokenStream ) -> PResult < ' a , Assert > {
87
113
let mut parser = cx. new_parser_from_tts ( stream) ;
88
114
0 commit comments