@@ -20,6 +20,7 @@ use syntax::print::pp::Breaks::{Consistent, Inconsistent};
2020use syntax:: print:: pprust:: PrintState ;
2121use syntax:: ptr:: P ;
2222use syntax:: symbol:: keywords;
23+ use syntax:: util:: parser:: { self , AssocOp , Fixity } ;
2324use syntax_pos:: { self , BytePos } ;
2425
2526use hir;
@@ -210,18 +211,6 @@ pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String {
210211 } )
211212}
212213
213- fn needs_parentheses ( expr : & hir:: Expr ) -> bool {
214- match expr. node {
215- hir:: ExprAssign ( ..) |
216- hir:: ExprBinary ( ..) |
217- hir:: ExprClosure ( ..) |
218- hir:: ExprAssignOp ( ..) |
219- hir:: ExprCast ( ..) |
220- hir:: ExprType ( ..) => true ,
221- _ => false ,
222- }
223- }
224-
225214impl < ' a > State < ' a > {
226215 pub fn cbox ( & mut self , u : usize ) -> io:: Result < ( ) > {
227216 self . boxes . push ( pp:: Breaks :: Consistent ) ;
@@ -1047,7 +1036,7 @@ impl<'a> State<'a> {
10471036 self . cbox ( indent_unit - 1 ) ?;
10481037 self . ibox ( 0 ) ?;
10491038 self . s . word ( " else if " ) ?;
1050- self . print_expr ( & i) ?;
1039+ self . print_expr_as_cond ( & i) ?;
10511040 self . s . space ( ) ?;
10521041 self . print_expr ( & then) ?;
10531042 self . print_else ( e. as_ref ( ) . map ( |e| & * * e) )
@@ -1075,7 +1064,7 @@ impl<'a> State<'a> {
10751064 elseopt : Option < & hir:: Expr > )
10761065 -> io:: Result < ( ) > {
10771066 self . head ( "if" ) ?;
1078- self . print_expr ( test) ?;
1067+ self . print_expr_as_cond ( test) ?;
10791068 self . s . space ( ) ?;
10801069 self . print_expr ( blk) ?;
10811070 self . print_else ( elseopt)
@@ -1091,7 +1080,7 @@ impl<'a> State<'a> {
10911080 self . print_pat ( pat) ?;
10921081 self . s . space ( ) ?;
10931082 self . word_space ( "=" ) ?;
1094- self . print_expr ( expr) ?;
1083+ self . print_expr_as_cond ( expr) ?;
10951084 self . s . space ( ) ?;
10961085 self . print_block ( blk) ?;
10971086 self . print_else ( elseopt)
@@ -1104,8 +1093,31 @@ impl<'a> State<'a> {
11041093 self . pclose ( )
11051094 }
11061095
1107- pub fn print_expr_maybe_paren ( & mut self , expr : & hir:: Expr ) -> io:: Result < ( ) > {
1108- let needs_par = needs_parentheses ( expr) ;
1096+ pub fn print_expr_maybe_paren ( & mut self , expr : & hir:: Expr , prec : i8 ) -> io:: Result < ( ) > {
1097+ let needs_par = expr_precedence ( expr) < prec;
1098+ if needs_par {
1099+ self . popen ( ) ?;
1100+ }
1101+ self . print_expr ( expr) ?;
1102+ if needs_par {
1103+ self . pclose ( ) ?;
1104+ }
1105+ Ok ( ( ) )
1106+ }
1107+
1108+ /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
1109+ /// `if cond { ... }`.
1110+ pub fn print_expr_as_cond ( & mut self , expr : & hir:: Expr ) -> io:: Result < ( ) > {
1111+ let needs_par = match expr. node {
1112+ // These cases need parens due to the parse error observed in #26461: `if return {}`
1113+ // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1114+ hir:: ExprClosure ( ..) |
1115+ hir:: ExprRet ( ..) |
1116+ hir:: ExprBreak ( ..) => true ,
1117+
1118+ _ => contains_exterior_struct_lit ( expr) ,
1119+ } ;
1120+
11091121 if needs_par {
11101122 self . popen ( ) ?;
11111123 }
@@ -1182,7 +1194,14 @@ impl<'a> State<'a> {
11821194 }
11831195
11841196 fn print_expr_call ( & mut self , func : & hir:: Expr , args : & [ hir:: Expr ] ) -> io:: Result < ( ) > {
1185- self . print_expr_maybe_paren ( func) ?;
1197+ let prec =
1198+ match func. node {
1199+ hir:: ExprField ( ..) |
1200+ hir:: ExprTupField ( ..) => parser:: PREC_FORCE_PAREN ,
1201+ _ => parser:: PREC_POSTFIX ,
1202+ } ;
1203+
1204+ self . print_expr_maybe_paren ( func, prec) ?;
11861205 self . print_call_post ( args)
11871206 }
11881207
@@ -1191,7 +1210,7 @@ impl<'a> State<'a> {
11911210 args : & [ hir:: Expr ] )
11921211 -> io:: Result < ( ) > {
11931212 let base_args = & args[ 1 ..] ;
1194- self . print_expr ( & args[ 0 ] ) ?;
1213+ self . print_expr_maybe_paren ( & args[ 0 ] , parser :: PREC_POSTFIX ) ?;
11951214 self . s . word ( "." ) ?;
11961215 self . print_name ( segment. name ) ?;
11971216 if !segment. parameters . lifetimes . is_empty ( ) ||
@@ -1207,15 +1226,25 @@ impl<'a> State<'a> {
12071226 lhs : & hir:: Expr ,
12081227 rhs : & hir:: Expr )
12091228 -> io:: Result < ( ) > {
1210- self . print_expr ( lhs) ?;
1229+ let assoc_op = bin_op_to_assoc_op ( op. node ) ;
1230+ let prec = assoc_op. precedence ( ) as i8 ;
1231+ let fixity = assoc_op. fixity ( ) ;
1232+
1233+ let ( left_prec, right_prec) = match fixity {
1234+ Fixity :: Left => ( prec, prec + 1 ) ,
1235+ Fixity :: Right => ( prec + 1 , prec) ,
1236+ Fixity :: None => ( prec + 1 , prec + 1 ) ,
1237+ } ;
1238+
1239+ self . print_expr_maybe_paren ( lhs, left_prec) ?;
12111240 self . s . space ( ) ?;
12121241 self . word_space ( op. node . as_str ( ) ) ?;
1213- self . print_expr ( rhs)
1242+ self . print_expr_maybe_paren ( rhs, right_prec )
12141243 }
12151244
12161245 fn print_expr_unary ( & mut self , op : hir:: UnOp , expr : & hir:: Expr ) -> io:: Result < ( ) > {
12171246 self . s . word ( op. as_str ( ) ) ?;
1218- self . print_expr_maybe_paren ( expr)
1247+ self . print_expr_maybe_paren ( expr, parser :: PREC_PREFIX )
12191248 }
12201249
12211250 fn print_expr_addr_of ( & mut self ,
@@ -1224,7 +1253,7 @@ impl<'a> State<'a> {
12241253 -> io:: Result < ( ) > {
12251254 self . s . word ( "&" ) ?;
12261255 self . print_mutability ( mutability) ?;
1227- self . print_expr_maybe_paren ( expr)
1256+ self . print_expr_maybe_paren ( expr, parser :: PREC_PREFIX )
12281257 }
12291258
12301259 pub fn print_expr ( & mut self , expr : & hir:: Expr ) -> io:: Result < ( ) > {
@@ -1235,7 +1264,7 @@ impl<'a> State<'a> {
12351264 match expr. node {
12361265 hir:: ExprBox ( ref expr) => {
12371266 self . word_space ( "box" ) ?;
1238- self . print_expr ( expr) ?;
1267+ self . print_expr_maybe_paren ( expr, parser :: PREC_PREFIX ) ?;
12391268 }
12401269 hir:: ExprArray ( ref exprs) => {
12411270 self . print_expr_vec ( exprs) ?;
@@ -1268,13 +1297,15 @@ impl<'a> State<'a> {
12681297 self . print_literal ( & lit) ?;
12691298 }
12701299 hir:: ExprCast ( ref expr, ref ty) => {
1271- self . print_expr ( & expr) ?;
1300+ let prec = AssocOp :: As . precedence ( ) as i8 ;
1301+ self . print_expr_maybe_paren ( & expr, prec) ?;
12721302 self . s . space ( ) ?;
12731303 self . word_space ( "as" ) ?;
12741304 self . print_type ( & ty) ?;
12751305 }
12761306 hir:: ExprType ( ref expr, ref ty) => {
1277- self . print_expr ( & expr) ?;
1307+ let prec = AssocOp :: Colon . precedence ( ) as i8 ;
1308+ self . print_expr_maybe_paren ( & expr, prec) ?;
12781309 self . word_space ( ":" ) ?;
12791310 self . print_type ( & ty) ?;
12801311 }
@@ -1287,7 +1318,7 @@ impl<'a> State<'a> {
12871318 self . word_space ( ":" ) ?;
12881319 }
12891320 self . head ( "while" ) ?;
1290- self . print_expr ( & test) ?;
1321+ self . print_expr_as_cond ( & test) ?;
12911322 self . s . space ( ) ?;
12921323 self . print_block ( & blk) ?;
12931324 }
@@ -1304,7 +1335,7 @@ impl<'a> State<'a> {
13041335 self . cbox ( indent_unit) ?;
13051336 self . ibox ( 4 ) ?;
13061337 self . word_nbsp ( "match" ) ?;
1307- self . print_expr ( & expr) ?;
1338+ self . print_expr_as_cond ( & expr) ?;
13081339 self . s . space ( ) ?;
13091340 self . bopen ( ) ?;
13101341 for arm in arms {
@@ -1335,30 +1366,32 @@ impl<'a> State<'a> {
13351366 self . print_block ( & blk) ?;
13361367 }
13371368 hir:: ExprAssign ( ref lhs, ref rhs) => {
1338- self . print_expr ( & lhs) ?;
1369+ let prec = AssocOp :: Assign . precedence ( ) as i8 ;
1370+ self . print_expr_maybe_paren ( & lhs, prec + 1 ) ?;
13391371 self . s . space ( ) ?;
13401372 self . word_space ( "=" ) ?;
1341- self . print_expr ( & rhs) ?;
1373+ self . print_expr_maybe_paren ( & rhs, prec ) ?;
13421374 }
13431375 hir:: ExprAssignOp ( op, ref lhs, ref rhs) => {
1344- self . print_expr ( & lhs) ?;
1376+ let prec = AssocOp :: Assign . precedence ( ) as i8 ;
1377+ self . print_expr_maybe_paren ( & lhs, prec + 1 ) ?;
13451378 self . s . space ( ) ?;
13461379 self . s . word ( op. node . as_str ( ) ) ?;
13471380 self . word_space ( "=" ) ?;
1348- self . print_expr ( & rhs) ?;
1381+ self . print_expr_maybe_paren ( & rhs, prec ) ?;
13491382 }
13501383 hir:: ExprField ( ref expr, name) => {
1351- self . print_expr ( & expr) ?;
1384+ self . print_expr_maybe_paren ( expr, parser :: PREC_POSTFIX ) ?;
13521385 self . s . word ( "." ) ?;
13531386 self . print_name ( name. node ) ?;
13541387 }
13551388 hir:: ExprTupField ( ref expr, id) => {
1356- self . print_expr ( & expr) ?;
1389+ self . print_expr_maybe_paren ( & expr, parser :: PREC_POSTFIX ) ?;
13571390 self . s . word ( "." ) ?;
13581391 self . print_usize ( id. node ) ?;
13591392 }
13601393 hir:: ExprIndex ( ref expr, ref index) => {
1361- self . print_expr ( & expr) ?;
1394+ self . print_expr_maybe_paren ( & expr, parser :: PREC_POSTFIX ) ?;
13621395 self . s . word ( "[" ) ?;
13631396 self . print_expr ( & index) ?;
13641397 self . s . word ( "]" ) ?;
@@ -1374,7 +1407,7 @@ impl<'a> State<'a> {
13741407 self . s . space ( ) ?;
13751408 }
13761409 if let Some ( ref expr) = * opt_expr {
1377- self . print_expr ( expr) ?;
1410+ self . print_expr_maybe_paren ( expr, parser :: PREC_JUMP ) ?;
13781411 self . s . space ( ) ?;
13791412 }
13801413 }
@@ -1391,7 +1424,7 @@ impl<'a> State<'a> {
13911424 match * result {
13921425 Some ( ref expr) => {
13931426 self . s . word ( " " ) ?;
1394- self . print_expr ( & expr) ?;
1427+ self . print_expr_maybe_paren ( & expr, parser :: PREC_JUMP ) ?;
13951428 }
13961429 _ => ( ) ,
13971430 }
@@ -1463,7 +1496,7 @@ impl<'a> State<'a> {
14631496 }
14641497 hir:: ExprYield ( ref expr) => {
14651498 self . s . word ( "yield" ) ?;
1466- self . print_expr ( & expr) ?;
1499+ self . print_expr_maybe_paren ( & expr, parser :: PREC_JUMP ) ?;
14671500 }
14681501 }
14691502 self . ann . post ( self , NodeExpr ( expr) ) ?;
@@ -2246,3 +2279,111 @@ fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
22462279 }
22472280 }
22482281}
2282+
2283+
2284+ fn expr_precedence ( expr : & hir:: Expr ) -> i8 {
2285+ use syntax:: util:: parser:: * ;
2286+
2287+ match expr. node {
2288+ hir:: ExprClosure ( ..) => PREC_CLOSURE ,
2289+
2290+ hir:: ExprBreak ( ..) |
2291+ hir:: ExprAgain ( ..) |
2292+ hir:: ExprRet ( ..) |
2293+ hir:: ExprYield ( ..) => PREC_JUMP ,
2294+
2295+ // Binop-like expr kinds, handled by `AssocOp`.
2296+ hir:: ExprBinary ( op, _, _) => bin_op_to_assoc_op ( op. node ) . precedence ( ) as i8 ,
2297+
2298+ hir:: ExprCast ( ..) => AssocOp :: As . precedence ( ) as i8 ,
2299+ hir:: ExprType ( ..) => AssocOp :: Colon . precedence ( ) as i8 ,
2300+
2301+ hir:: ExprAssign ( ..) |
2302+ hir:: ExprAssignOp ( ..) => AssocOp :: Assign . precedence ( ) as i8 ,
2303+
2304+ // Unary, prefix
2305+ hir:: ExprBox ( ..) |
2306+ hir:: ExprAddrOf ( ..) |
2307+ hir:: ExprUnary ( ..) => PREC_PREFIX ,
2308+
2309+ // Unary, postfix
2310+ hir:: ExprCall ( ..) |
2311+ hir:: ExprMethodCall ( ..) |
2312+ hir:: ExprField ( ..) |
2313+ hir:: ExprTupField ( ..) |
2314+ hir:: ExprIndex ( ..) |
2315+ hir:: ExprInlineAsm ( ..) => PREC_POSTFIX ,
2316+
2317+ // Never need parens
2318+ hir:: ExprArray ( ..) |
2319+ hir:: ExprRepeat ( ..) |
2320+ hir:: ExprTup ( ..) |
2321+ hir:: ExprLit ( ..) |
2322+ hir:: ExprPath ( ..) |
2323+ hir:: ExprIf ( ..) |
2324+ hir:: ExprWhile ( ..) |
2325+ hir:: ExprLoop ( ..) |
2326+ hir:: ExprMatch ( ..) |
2327+ hir:: ExprBlock ( ..) |
2328+ hir:: ExprStruct ( ..) => PREC_PAREN ,
2329+ }
2330+ }
2331+
2332+ fn bin_op_to_assoc_op ( op : hir:: BinOp_ ) -> AssocOp {
2333+ use hir:: BinOp_ :: * ;
2334+ match op {
2335+ BiAdd => AssocOp :: Add ,
2336+ BiSub => AssocOp :: Subtract ,
2337+ BiMul => AssocOp :: Multiply ,
2338+ BiDiv => AssocOp :: Divide ,
2339+ BiRem => AssocOp :: Modulus ,
2340+
2341+ BiAnd => AssocOp :: LAnd ,
2342+ BiOr => AssocOp :: LOr ,
2343+
2344+ BiBitXor => AssocOp :: BitXor ,
2345+ BiBitAnd => AssocOp :: BitAnd ,
2346+ BiBitOr => AssocOp :: BitOr ,
2347+ BiShl => AssocOp :: ShiftLeft ,
2348+ BiShr => AssocOp :: ShiftRight ,
2349+
2350+ BiEq => AssocOp :: Equal ,
2351+ BiLt => AssocOp :: Less ,
2352+ BiLe => AssocOp :: LessEqual ,
2353+ BiNe => AssocOp :: NotEqual ,
2354+ BiGe => AssocOp :: GreaterEqual ,
2355+ BiGt => AssocOp :: Greater ,
2356+ }
2357+ }
2358+
2359+ /// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any
2360+ /// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
2361+ /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
2362+ fn contains_exterior_struct_lit ( value : & hir:: Expr ) -> bool {
2363+ match value. node {
2364+ hir:: ExprStruct ( ..) => true ,
2365+
2366+ hir:: ExprAssign ( ref lhs, ref rhs) |
2367+ hir:: ExprAssignOp ( _, ref lhs, ref rhs) |
2368+ hir:: ExprBinary ( _, ref lhs, ref rhs) => {
2369+ // X { y: 1 } + X { y: 2 }
2370+ contains_exterior_struct_lit ( & lhs) || contains_exterior_struct_lit ( & rhs)
2371+ }
2372+ hir:: ExprUnary ( _, ref x) |
2373+ hir:: ExprCast ( ref x, _) |
2374+ hir:: ExprType ( ref x, _) |
2375+ hir:: ExprField ( ref x, _) |
2376+ hir:: ExprTupField ( ref x, _) |
2377+ hir:: ExprIndex ( ref x, _) => {
2378+ // &X { y: 1 }, X { y: 1 }.y
2379+ contains_exterior_struct_lit ( & x)
2380+ }
2381+
2382+ hir:: ExprMethodCall ( .., ref exprs) => {
2383+ // X { y: 1 }.bar(...)
2384+ contains_exterior_struct_lit ( & exprs[ 0 ] )
2385+ }
2386+
2387+ _ => false ,
2388+ }
2389+ }
0 commit comments