Skip to content

Commit 0d53ecd

Browse files
committed
Rollup merge of #45784 - harpocrates:fix/print-parens-cast-lt, r=kennytm
Pretty print parens around casts on the LHS of `<`/`<<` When pretty printing a cast expression occuring on the LHS of a `<` or `<<` expression, we should add parens around the cast. Otherwise, the `<`/`<<` gets interpreted as the beginning of the generics for the type on the RHS of the cast. Consider: $ cat parens_cast.rs macro_rules! negative { ($e:expr) => { $e < 0 } } fn main() { negative!(1 as i32); } Before this PR, the output of the following is not valid Rust: $ rustc -Z unstable-options --pretty=expanded parens_cast.rs #![feature(prelude_import)] #![no_std] #[prelude_import] use std::prelude::v1::*; #[macro_use] extern crate std as std; macro_rules! negative(( $ e : expr ) => { $ e < 0 }); fn main() { 1 as i32 < 0; } After this PR, the output of the following is valid Rust: $ rustc -Z unstable-options --pretty=expanded parens_cast.rs #![feature(prelude_import)] #![no_std] #[prelude_import] use std::prelude::v1::*; #[macro_use] extern crate std as std; macro_rules! negative(( $ e : expr ) => { $ e < 0 }); fn main() { (1 as i32) < 0; } I've gone through several README/wiki style documents but I'm still not sure where to test this though. I'm not even sure if this sort of thing is tested...
2 parents 1683b83 + aa38a1e commit 0d53ecd

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

src/librustc/hir/print.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,15 @@ impl<'a> State<'a> {
12541254
Fixity::None => (prec + 1, prec + 1),
12551255
};
12561256

1257+
let left_prec = match (&lhs.node, op.node) {
1258+
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1259+
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1260+
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
1261+
(&hir::ExprCast { .. }, hir::BinOp_::BiLt) |
1262+
(&hir::ExprCast { .. }, hir::BinOp_::BiShl) => parser::PREC_FORCE_PAREN,
1263+
_ => left_prec,
1264+
};
1265+
12571266
self.print_expr_maybe_paren(lhs, left_prec)?;
12581267
self.s.space()?;
12591268
self.word_space(op.node.as_str())?;

src/libsyntax/print/pprust.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,15 @@ impl<'a> State<'a> {
19871987
Fixity::None => (prec + 1, prec + 1),
19881988
};
19891989

1990+
let left_prec = match (&lhs.node, op.node) {
1991+
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1992+
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1993+
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
1994+
(&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt) |
1995+
(&ast::ExprKind::Cast { .. }, ast::BinOpKind::Shl) => parser::PREC_FORCE_PAREN,
1996+
_ => left_prec,
1997+
};
1998+
19901999
self.print_expr_maybe_paren(lhs, left_prec)?;
19912000
self.s.space()?;
19922001
self.word_space(op.node.to_string())?;

src/test/pretty/cast-lt.pp

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(prelude_import)]
2+
#![no_std]
3+
#[prelude_import]
4+
use std::prelude::v1::*;
5+
#[macro_use]
6+
extern crate std as std;
7+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
8+
// file at the top-level directory of this distribution and at
9+
// http://rust-lang.org/COPYRIGHT.
10+
//
11+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
12+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
13+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
14+
// option. This file may not be copied, modified, or distributed
15+
// except according to those terms.
16+
17+
// pretty-compare-only
18+
// pretty-mode:expanded
19+
// pp-exact:cast-lt.pp
20+
21+
macro_rules! negative(( $ e : expr ) => { $ e < 0 });
22+
23+
fn main() { (1 as i32) < 0; }
24+

src/test/pretty/cast-lt.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// pretty-compare-only
12+
// pretty-mode:expanded
13+
// pp-exact:cast-lt.pp
14+
15+
macro_rules! negative {
16+
($e:expr) => { $e < 0 }
17+
}
18+
19+
fn main() {
20+
negative!(1 as i32);
21+
}
22+

0 commit comments

Comments
 (0)