@@ -893,7 +893,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
893
893
let lt = parse ! ( self , integer_62) ;
894
894
self . print_lifetime_from_index ( lt)
895
895
} else if self . eat ( b'K' ) {
896
- self . print_const ( )
896
+ self . print_const ( false )
897
897
} else {
898
898
self . print_type ( )
899
899
}
@@ -939,7 +939,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
939
939
self . print_type ( ) ?;
940
940
if tag == b'A' {
941
941
self . print ( "; " ) ?;
942
- self . print_const ( ) ?;
942
+ self . print_const ( true ) ?;
943
943
}
944
944
self . print ( "]" ) ?;
945
945
}
@@ -1079,7 +1079,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
1079
1079
Ok ( ( ) )
1080
1080
}
1081
1081
1082
- fn print_const ( & mut self ) -> fmt:: Result {
1082
+ fn print_const ( & mut self , in_value : bool ) -> fmt:: Result {
1083
1083
let tag = parse ! ( self , next) ;
1084
1084
1085
1085
parse ! ( self , push_depth) ;
@@ -1091,7 +1091,12 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
1091
1091
// used (especially any special-casing), every case that needs braces
1092
1092
// has to call `open_brace(self)?` (and the closing brace is automatic).
1093
1093
let mut opened_brace = false ;
1094
- let mut open_brace = |this : & mut Self | {
1094
+ let mut open_brace_if_outside_expr = |this : & mut Self | {
1095
+ // If this expression is nested in another, braces aren't required.
1096
+ if in_value {
1097
+ return Ok ( ( ) ) ;
1098
+ }
1099
+
1095
1100
opened_brace = true ;
1096
1101
this. print ( "{" )
1097
1102
} ;
@@ -1127,17 +1132,28 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
1127
1132
// NOTE(eddyb) a string literal `"..."` has type `&str`, so
1128
1133
// to get back the type `str`, `*"..."` syntax is needed
1129
1134
// (even if that may not be valid in Rust itself).
1130
- open_brace ( self ) ?;
1135
+ open_brace_if_outside_expr ( self ) ?;
1131
1136
self . print ( "*" ) ?;
1132
1137
1133
- match parse ! ( self , hex_nibbles) . try_parse_str_chars ( ) {
1134
- Some ( chars) => self . print_quoted_escaped_chars ( '"' , chars) ?,
1135
- None => invalid ! ( self ) ,
1136
- }
1138
+ self . print_const_str_literal ( ) ?;
1137
1139
}
1138
1140
1141
+ b'R' | b'Q' => {
1142
+ // NOTE(eddyb) this prints `"..."` instead of `&*"..."`, which
1143
+ // is what `Re..._` would imply (see comment for `str` above).
1144
+ if tag == b'R' && self . eat ( b'e' ) {
1145
+ self . print_const_str_literal ( ) ?;
1146
+ } else {
1147
+ open_brace_if_outside_expr ( self ) ?;
1148
+ self . print ( "&" ) ?;
1149
+ if tag != b'R' {
1150
+ self . print ( "mut " ) ?;
1151
+ }
1152
+ self . print_const ( true ) ?;
1153
+ }
1154
+ }
1139
1155
b'B' => {
1140
- self . print_backref ( Self :: print_const) ?;
1156
+ self . print_backref ( |this| this . print_const ( in_value ) ) ?;
1141
1157
}
1142
1158
_ => invalid ! ( self ) ,
1143
1159
}
@@ -1172,6 +1188,13 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
1172
1188
1173
1189
Ok ( ( ) )
1174
1190
}
1191
+
1192
+ fn print_const_str_literal ( & mut self ) -> fmt:: Result {
1193
+ match parse ! ( self , hex_nibbles) . try_parse_str_chars ( ) {
1194
+ Some ( chars) => self . print_quoted_escaped_chars ( '"' , chars) ,
1195
+ None => invalid ! ( self ) ,
1196
+ }
1197
+ }
1175
1198
}
1176
1199
1177
1200
#[ cfg( test) ]
@@ -1288,6 +1311,37 @@ mod tests {
1288
1311
) ;
1289
1312
}
1290
1313
1314
+ // NOTE(eddyb) this uses the same strings as `demangle_const_str` and should
1315
+ // be kept in sync with it - while a macro could be used to generate both
1316
+ // `str` and `&str` tests, from a single list of strings, this seems clearer.
1317
+ #[ test]
1318
+ fn demangle_const_ref_str ( ) {
1319
+ t_const ! ( "Re616263_" , "\" abc\" " ) ;
1320
+ t_const ! ( "Re27_" , r#""'""# ) ;
1321
+ t_const ! ( "Re090a_" , "\" \\ t\\ n\" " ) ;
1322
+ t_const ! ( "Ree28882c3bc_" , "\" ∂ü\" " ) ;
1323
+ t_const ! (
1324
+ "Ree183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839b\
1325
+ e183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_",
1326
+ "\" საჭმელად_გემრიელი_სადილი\" "
1327
+ ) ;
1328
+ t_const ! (
1329
+ "Ref09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e298\
1330
+ 95f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_",
1331
+ "\" 🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜\" "
1332
+ ) ;
1333
+ }
1334
+
1335
+ #[ test]
1336
+ fn demangle_const_ref ( ) {
1337
+ t_const ! ( "Rp" , "{&_}" ) ;
1338
+ t_const ! ( "Rh7b_" , "{&123}" ) ;
1339
+ t_const ! ( "Rb0_" , "{&false}" ) ;
1340
+ t_const ! ( "Rc58_" , "{&'X'}" ) ;
1341
+ t_const ! ( "RRRh0_" , "{&&&0}" ) ;
1342
+ t_const ! ( "RRRe_" , "{&&\" \" }" ) ;
1343
+ }
1344
+
1291
1345
#[ test]
1292
1346
fn demangle_exponential_explosion ( ) {
1293
1347
// NOTE(eddyb) because of the prefix added by `t_nohash_type!` is
0 commit comments