Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21057 from A4-Tacks/hir-debug-precedence
Implement precedence for print_hir
Lukas Wirth 5 months ago
parent c125735 · parent c3b8385 · commit 19a4295
-rw-r--r--crates/hir-def/src/expr_store/lower.rs1
-rw-r--r--crates/hir-def/src/expr_store/pretty.rs93
-rw-r--r--crates/hir-def/src/expr_store/tests/body.rs29
-rw-r--r--crates/hir-def/src/hir.rs66
4 files changed, 147 insertions, 42 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 3794cb18e9..c13a7e92cc 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -2409,6 +2409,7 @@ impl ExprCollector<'_> {
};
let start = range_part_lower(p.start());
let end = range_part_lower(p.end());
+ // FIXME: Exclusive ended pattern range is stabilised
Pat::Range { start, end }
}
};
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 5b9da3c5e6..3b3188398e 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -510,7 +510,22 @@ impl Printer<'_> {
}
fn print_expr(&mut self, expr: ExprId) {
+ self.print_expr_in(None, expr);
+ }
+
+ fn print_expr_in(&mut self, prec: Option<ast::prec::ExprPrecedence>, expr: ExprId) {
let expr = &self.store[expr];
+ let needs_parens = match (prec, expr.precedence()) {
+ (Some(ast::prec::ExprPrecedence::LOr), ast::prec::ExprPrecedence::LOr) => false,
+ (Some(ast::prec::ExprPrecedence::LAnd), ast::prec::ExprPrecedence::LAnd) => false,
+ (Some(parent), prec) => prec.needs_parentheses_in(parent),
+ (None, _) => false,
+ };
+ let prec = Some(expr.precedence());
+
+ if needs_parens {
+ w!(self, "(");
+ }
match expr {
Expr::Missing => w!(self, "�"),
@@ -544,7 +559,7 @@ impl Printer<'_> {
w!(self, "let ");
self.print_pat(*pat);
w!(self, " = ");
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
Expr::Loop { body, label } => {
if let Some(lbl) = label {
@@ -554,7 +569,7 @@ impl Printer<'_> {
self.print_expr(*body);
}
Expr::Call { callee, args } => {
- self.print_expr(*callee);
+ self.print_expr_in(prec, *callee);
w!(self, "(");
if !args.is_empty() {
self.indented(|p| {
@@ -567,7 +582,7 @@ impl Printer<'_> {
w!(self, ")");
}
Expr::MethodCall { receiver, method_name, args, generic_args } => {
- self.print_expr(*receiver);
+ self.print_expr_in(prec, *receiver);
w!(self, ".{}", method_name.display(self.db, self.edition));
if let Some(args) = generic_args {
w!(self, "::<");
@@ -616,26 +631,26 @@ impl Printer<'_> {
}
if let Some(expr) = expr {
self.whitespace();
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
}
Expr::Return { expr } => {
w!(self, "return");
if let Some(expr) = expr {
self.whitespace();
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
}
Expr::Become { expr } => {
w!(self, "become");
self.whitespace();
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
Expr::Yield { expr } => {
w!(self, "yield");
if let Some(expr) = expr {
self.whitespace();
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
}
Expr::Yeet { expr } => {
@@ -644,7 +659,7 @@ impl Printer<'_> {
w!(self, "yeet");
if let Some(expr) = expr {
self.whitespace();
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
}
Expr::RecordLit { path, fields, spread } => {
@@ -670,15 +685,15 @@ impl Printer<'_> {
w!(self, "}}");
}
Expr::Field { expr, name } => {
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
w!(self, ".{}", name.display(self.db, self.edition));
}
Expr::Await { expr } => {
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
w!(self, ".await");
}
Expr::Cast { expr, type_ref } => {
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
w!(self, " as ");
self.print_type_ref(*type_ref);
}
@@ -690,11 +705,11 @@ impl Printer<'_> {
if mutability.is_mut() {
w!(self, "mut ");
}
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
Expr::Box { expr } => {
w!(self, "box ");
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
Expr::UnaryOp { expr, op } => {
let op = match op {
@@ -703,43 +718,32 @@ impl Printer<'_> {
ast::UnaryOp::Neg => "-",
};
w!(self, "{}", op);
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
Expr::BinaryOp { lhs, rhs, op } => {
- let (bra, ket) = match op {
- None | Some(ast::BinaryOp::Assignment { .. }) => ("", ""),
- _ => ("(", ")"),
- };
- w!(self, "{}", bra);
- self.print_expr(*lhs);
- w!(self, "{} ", ket);
+ self.print_expr_in(prec, *lhs);
+ self.whitespace();
match op {
Some(op) => w!(self, "{}", op),
None => w!(self, "�"), // :)
}
- w!(self, " {}", bra);
- self.print_expr(*rhs);
- w!(self, "{}", ket);
+ self.whitespace();
+ self.print_expr_in(prec, *rhs);
}
Expr::Range { lhs, rhs, range_type } => {
if let Some(lhs) = lhs {
- w!(self, "(");
- self.print_expr(*lhs);
- w!(self, ") ");
+ self.print_expr_in(prec, *lhs);
}
- let range = match range_type {
- ast::RangeOp::Exclusive => "..",
- ast::RangeOp::Inclusive => "..=",
+ match range_type {
+ ast::RangeOp::Exclusive => w!(self, ".."),
+ ast::RangeOp::Inclusive => w!(self, "..="),
};
- w!(self, "{}", range);
if let Some(rhs) = rhs {
- w!(self, "(");
- self.print_expr(*rhs);
- w!(self, ") ");
+ self.print_expr_in(prec, *rhs);
}
}
Expr::Index { base, index } => {
- self.print_expr(*base);
+ self.print_expr_in(prec, *base);
w!(self, "[");
self.print_expr(*index);
w!(self, "]");
@@ -826,9 +830,13 @@ impl Printer<'_> {
&Expr::Assignment { target, value } => {
self.print_pat(target);
w!(self, " = ");
- self.print_expr(value);
+ self.print_expr_in(prec, value);
}
}
+
+ if needs_parens {
+ w!(self, ")");
+ }
}
fn print_block(
@@ -857,6 +865,7 @@ impl Printer<'_> {
}
fn print_pat(&mut self, pat: PatId) {
+ let prec = Some(ast::prec::ExprPrecedence::Shift);
let pat = &self.store[pat];
match pat {
@@ -930,11 +939,11 @@ impl Printer<'_> {
}
Pat::Range { start, end } => {
if let Some(start) = start {
- self.print_expr(*start);
+ self.print_expr_in(prec, *start);
}
w!(self, "..=");
if let Some(end) = end {
- self.print_expr(*end);
+ self.print_expr_in(prec, *end);
}
}
Pat::Slice { prefix, slice, suffix } => {
@@ -954,7 +963,7 @@ impl Printer<'_> {
w!(self, "]");
}
Pat::Path(path) => self.print_path(path),
- Pat::Lit(expr) => self.print_expr(*expr),
+ Pat::Lit(expr) => self.print_expr_in(prec, *expr),
Pat::Bind { id, subpat } => {
self.print_binding(*id);
if let Some(pat) = subpat {
@@ -996,7 +1005,7 @@ impl Printer<'_> {
self.print_expr(*c);
}
Pat::Expr(expr) => {
- self.print_expr(*expr);
+ self.print_expr_in(prec, *expr);
}
}
}
@@ -1181,7 +1190,9 @@ impl Printer<'_> {
pub(crate) fn print_generic_arg(&mut self, arg: &GenericArg) {
match arg {
GenericArg::Type(ty) => self.print_type_ref(*ty),
- GenericArg::Const(ConstRef { expr }) => self.print_expr(*expr),
+ GenericArg::Const(ConstRef { expr }) => {
+ self.print_expr_in(Some(ast::prec::ExprPrecedence::Unambiguous), *expr)
+ }
GenericArg::Lifetime(lt) => self.print_lifetime_ref(*lt),
}
}
diff --git a/crates/hir-def/src/expr_store/tests/body.rs b/crates/hir-def/src/expr_store/tests/body.rs
index c31428be28..0a982b9e39 100644
--- a/crates/hir-def/src/expr_store/tests/body.rs
+++ b/crates/hir-def/src/expr_store/tests/body.rs
@@ -159,7 +159,7 @@ fn main() {
expect![[r#"
fn main() {
match builtin#lang(into_iter)(
- (0) ..(10) ,
+ 0..10,
) {
mut <ra@gennew>11 => loop {
match builtin#lang(next)(
@@ -590,3 +590,30 @@ const fn f(x: i32) -> i32 {
_ => {}
}
}
+
+#[test]
+fn print_hir_precedences() {
+ let (db, body, def) = lower(
+ r#"
+fn main() {
+ _ = &(1 - (2 - 3) + 4 * 5 * (6 + 7));
+ _ = 1 + 2 < 3 && true && 4 < 5 && (a || b || c) || d && e;
+ if let _ = 2 && true && let _ = 3 {}
+ break a && b || (return) || (return 2);
+ let r = &2;
+ let _ = &mut (*r as i32)
+}
+"#,
+ );
+
+ expect![[r#"
+ fn main() {
+ _ = &((1 - (2 - 3)) + (4 * 5) * (6 + 7));
+ _ = 1 + 2 < 3 && true && 4 < 5 && (a || b || c) || d && e;
+ if let _ = 2 && true && let _ = 3 {}
+ break a && b || (return) || (return 2);
+ let r = &2;
+ let _ = &mut (*r as i32);
+ }"#]]
+ .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+}
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index e70cd2cd6c..8ca8308512 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -322,6 +322,72 @@ pub enum Expr {
InlineAsm(InlineAsm),
}
+impl Expr {
+ pub fn precedence(&self) -> ast::prec::ExprPrecedence {
+ use ast::prec::ExprPrecedence;
+
+ match self {
+ Expr::Array(_)
+ | Expr::InlineAsm(_)
+ | Expr::Block { .. }
+ | Expr::Unsafe { .. }
+ | Expr::Const(_)
+ | Expr::Async { .. }
+ | Expr::If { .. }
+ | Expr::Literal(_)
+ | Expr::Loop { .. }
+ | Expr::Match { .. }
+ | Expr::Missing
+ | Expr::Path(_)
+ | Expr::RecordLit { .. }
+ | Expr::Tuple { .. }
+ | Expr::OffsetOf(_)
+ | Expr::Underscore => ExprPrecedence::Unambiguous,
+
+ Expr::Await { .. }
+ | Expr::Call { .. }
+ | Expr::Field { .. }
+ | Expr::Index { .. }
+ | Expr::MethodCall { .. } => ExprPrecedence::Postfix,
+
+ Expr::Box { .. } | Expr::Let { .. } | Expr::UnaryOp { .. } | Expr::Ref { .. } => {
+ ExprPrecedence::Prefix
+ }
+
+ Expr::Cast { .. } => ExprPrecedence::Cast,
+
+ Expr::BinaryOp { op, .. } => match op {
+ None => ExprPrecedence::Unambiguous,
+ Some(BinaryOp::LogicOp(LogicOp::Or)) => ExprPrecedence::LOr,
+ Some(BinaryOp::LogicOp(LogicOp::And)) => ExprPrecedence::LAnd,
+ Some(BinaryOp::CmpOp(_)) => ExprPrecedence::Compare,
+ Some(BinaryOp::Assignment { .. }) => ExprPrecedence::Assign,
+ Some(BinaryOp::ArithOp(arith_op)) => match arith_op {
+ ArithOp::Add | ArithOp::Sub => ExprPrecedence::Sum,
+ ArithOp::Mul | ArithOp::Div | ArithOp::Rem => ExprPrecedence::Product,
+ ArithOp::Shl | ArithOp::Shr => ExprPrecedence::Shift,
+ ArithOp::BitXor => ExprPrecedence::BitXor,
+ ArithOp::BitOr => ExprPrecedence::BitOr,
+ ArithOp::BitAnd => ExprPrecedence::BitAnd,
+ },
+ },
+
+ Expr::Assignment { .. } => ExprPrecedence::Assign,
+
+ Expr::Become { .. }
+ | Expr::Break { .. }
+ | Expr::Closure { .. }
+ | Expr::Return { .. }
+ | Expr::Yeet { .. }
+ | Expr::Yield { .. } => ExprPrecedence::Jump,
+
+ Expr::Continue { .. } => ExprPrecedence::Unambiguous,
+
+ Expr::Range { .. } => ExprPrecedence::Range,
+ }
+ }
+}
+
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OffsetOf {
pub container: TypeRefId,