@@ -893,7 +893,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
893893 let lt = parse ! ( self , integer_62) ;
894894 self . print_lifetime_from_index ( lt)
895895 } else if self . eat ( b'K' ) {
896- self . print_const ( )
896+ self . print_const ( false )
897897 } else {
898898 self . print_type ( )
899899 }
@@ -939,7 +939,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
939939 self . print_type ( ) ?;
940940 if tag == b'A' {
941941 self . print ( "; " ) ?;
942- self . print_const ( ) ?;
942+ self . print_const ( true ) ?;
943943 }
944944 self . print ( "]" ) ?;
945945 }
@@ -1079,7 +1079,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
10791079 Ok ( ( ) )
10801080 }
10811081
1082- fn print_const ( & mut self ) -> fmt:: Result {
1082+ fn print_const ( & mut self , in_value : bool ) -> fmt:: Result {
10831083 let tag = parse ! ( self , next) ;
10841084
10851085 parse ! ( self , push_depth) ;
@@ -1091,7 +1091,12 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
10911091 // used (especially any special-casing), every case that needs braces
10921092 // has to call `open_brace(self)?` (and the closing brace is automatic).
10931093 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+
10951100 opened_brace = true ;
10961101 this. print ( "{" )
10971102 } ;
@@ -1127,17 +1132,28 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
11271132 // NOTE(eddyb) a string literal `"..."` has type `&str`, so
11281133 // to get back the type `str`, `*"..."` syntax is needed
11291134 // (even if that may not be valid in Rust itself).
1130- open_brace ( self ) ?;
1135+ open_brace_if_outside_expr ( self ) ?;
11311136 self . print ( "*" ) ?;
11321137
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 ( ) ?;
11371139 }
11381140
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+ }
11391155 b'B' => {
1140- self . print_backref ( Self :: print_const) ?;
1156+ self . print_backref ( |this| this . print_const ( in_value ) ) ?;
11411157 }
11421158 _ => invalid ! ( self ) ,
11431159 }
@@ -1172,6 +1188,13 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
11721188
11731189 Ok ( ( ) )
11741190 }
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+ }
11751198}
11761199
11771200#[ cfg( test) ]
@@ -1288,6 +1311,37 @@ mod tests {
12881311 ) ;
12891312 }
12901313
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+
12911345 #[ test]
12921346 fn demangle_exponential_explosion ( ) {
12931347 // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is
0 commit comments