@@ -247,6 +247,15 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> StrBuf {
247
247
}
248
248
}
249
249
250
+ fn needs_parentheses ( expr : & ast:: Expr ) -> bool {
251
+ match expr. node {
252
+ ast:: ExprAssign ( ..) | ast:: ExprBinary ( ..) |
253
+ ast:: ExprFnBlock ( ..) | ast:: ExprProc ( ..) |
254
+ ast:: ExprAssignOp ( ..) | ast:: ExprCast ( ..) => true ,
255
+ _ => false ,
256
+ }
257
+ }
258
+
250
259
impl < ' a > State < ' a > {
251
260
pub fn ibox ( & mut self , u : uint ) -> IoResult < ( ) > {
252
261
self . boxes . push ( pp:: Inconsistent ) ;
@@ -1136,6 +1145,18 @@ impl<'a> State<'a> {
1136
1145
self . pclose ( )
1137
1146
}
1138
1147
1148
+ pub fn print_expr_maybe_paren ( & mut self , expr : & ast:: Expr ) -> IoResult < ( ) > {
1149
+ let needs_par = needs_parentheses ( expr) ;
1150
+ if needs_par {
1151
+ try!( self . popen ( ) ) ;
1152
+ }
1153
+ try!( self . print_expr ( expr) ) ;
1154
+ if needs_par {
1155
+ try!( self . pclose ( ) ) ;
1156
+ }
1157
+ Ok ( ( ) )
1158
+ }
1159
+
1139
1160
pub fn print_expr ( & mut self , expr : & ast:: Expr ) -> IoResult < ( ) > {
1140
1161
try!( self . maybe_print_comment ( expr. span . lo ) ) ;
1141
1162
try!( self . ibox ( indent_unit) ) ;
@@ -1209,7 +1230,7 @@ impl<'a> State<'a> {
1209
1230
try!( self . pclose ( ) ) ;
1210
1231
}
1211
1232
ast:: ExprCall ( func, ref args) => {
1212
- try!( self . print_expr ( func) ) ;
1233
+ try!( self . print_expr_maybe_paren ( func) ) ;
1213
1234
try!( self . print_call_post ( args. as_slice ( ) ) ) ;
1214
1235
}
1215
1236
ast:: ExprMethodCall ( ident, ref tys, ref args) => {
@@ -1233,17 +1254,38 @@ impl<'a> State<'a> {
1233
1254
}
1234
1255
ast:: ExprUnary ( op, expr) => {
1235
1256
try!( word ( & mut self . s , ast_util:: unop_to_str ( op) ) ) ;
1236
- try!( self . print_expr ( expr) ) ;
1257
+ try!( self . print_expr_maybe_paren ( expr) ) ;
1237
1258
}
1238
1259
ast:: ExprAddrOf ( m, expr) => {
1239
1260
try!( word ( & mut self . s , "&" ) ) ;
1261
+
1262
+ // `ExprAddrOf(ExprLit("str"))` should be `&&"str"` instead of `&"str"`
1263
+ // since `&"str"` is `ExprVstore(ExprLit("str"))` which has same meaning to
1264
+ // `"str"`.
1265
+ // In many cases adding parentheses (`&("str")`) would help, but it become invalid
1266
+ // if expr is in `PatLit()`.
1267
+ let needs_extra_amp = match expr. node {
1268
+ ast:: ExprLit ( lit) => {
1269
+ match lit. node {
1270
+ ast:: LitStr ( ..) => true ,
1271
+ _ => false ,
1272
+ }
1273
+ }
1274
+ ast:: ExprVec ( ..) => true ,
1275
+ _ => false ,
1276
+ } ;
1277
+ if needs_extra_amp {
1278
+ try!( word ( & mut self . s , "&" ) ) ;
1279
+ }
1280
+
1240
1281
try!( self . print_mutability ( m) ) ;
1241
1282
// Avoid `& &e` => `&&e`.
1242
1283
match ( m, & expr. node ) {
1243
1284
( ast:: MutImmutable , & ast:: ExprAddrOf ( ..) ) => try!( space ( & mut self . s ) ) ,
1244
1285
_ => { }
1245
1286
}
1246
- try!( self . print_expr ( expr) ) ;
1287
+
1288
+ try!( self . print_expr_maybe_paren ( expr) ) ;
1247
1289
}
1248
1290
ast:: ExprLit ( lit) => try!( self . print_literal ( lit) ) ,
1249
1291
ast:: ExprCast ( expr, ty) => {
0 commit comments