Skip to content

Commit

Permalink
Rollup merge of #45784 - harpocrates:fix/print-parens-cast-lt, r=kennytm
Browse files Browse the repository at this point in the history
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...
  • Loading branch information
kennytm committed Nov 7, 2017
2 parents 1683b83 + aa38a1e commit 0d53ecd
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,15 @@ impl<'a> State<'a> {
Fixity::None => (prec + 1, prec + 1),
};

let left_prec = match (&lhs.node, op.node) {
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
(&hir::ExprCast { .. }, hir::BinOp_::BiLt) |
(&hir::ExprCast { .. }, hir::BinOp_::BiShl) => parser::PREC_FORCE_PAREN,
_ => left_prec,
};

self.print_expr_maybe_paren(lhs, left_prec)?;
self.s.space()?;
self.word_space(op.node.as_str())?;
Expand Down
9 changes: 9 additions & 0 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1987,6 +1987,15 @@ impl<'a> State<'a> {
Fixity::None => (prec + 1, prec + 1),
};

let left_prec = match (&lhs.node, op.node) {
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
(&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt) |
(&ast::ExprKind::Cast { .. }, ast::BinOpKind::Shl) => parser::PREC_FORCE_PAREN,
_ => left_prec,
};

self.print_expr_maybe_paren(lhs, left_prec)?;
self.s.space()?;
self.word_space(op.node.to_string())?;
Expand Down
24 changes: 24 additions & 0 deletions src/test/pretty/cast-lt.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// pretty-compare-only
// pretty-mode:expanded
// pp-exact:cast-lt.pp

macro_rules! negative(( $ e : expr ) => { $ e < 0 });

fn main() { (1 as i32) < 0; }

22 changes: 22 additions & 0 deletions src/test/pretty/cast-lt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// pretty-compare-only
// pretty-mode:expanded
// pp-exact:cast-lt.pp

macro_rules! negative {
($e:expr) => { $e < 0 }
}

fn main() {
negative!(1 as i32);
}

0 comments on commit 0d53ecd

Please sign in to comment.