Skip to content

Commit 19a4295

Browse files
authored
Merge pull request #21057 from A4-Tacks/hir-debug-precedence
Implement precedence for print_hir
2 parents c125735 + c3b8385 commit 19a4295

File tree

4 files changed

+147
-42
lines changed

4 files changed

+147
-42
lines changed

crates/hir-def/src/expr_store/lower.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2409,6 +2409,7 @@ impl ExprCollector<'_> {
24092409
};
24102410
let start = range_part_lower(p.start());
24112411
let end = range_part_lower(p.end());
2412+
// FIXME: Exclusive ended pattern range is stabilised
24122413
Pat::Range { start, end }
24132414
}
24142415
};

crates/hir-def/src/expr_store/pretty.rs

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,22 @@ impl Printer<'_> {
510510
}
511511

512512
fn print_expr(&mut self, expr: ExprId) {
513+
self.print_expr_in(None, expr);
514+
}
515+
516+
fn print_expr_in(&mut self, prec: Option<ast::prec::ExprPrecedence>, expr: ExprId) {
513517
let expr = &self.store[expr];
518+
let needs_parens = match (prec, expr.precedence()) {
519+
(Some(ast::prec::ExprPrecedence::LOr), ast::prec::ExprPrecedence::LOr) => false,
520+
(Some(ast::prec::ExprPrecedence::LAnd), ast::prec::ExprPrecedence::LAnd) => false,
521+
(Some(parent), prec) => prec.needs_parentheses_in(parent),
522+
(None, _) => false,
523+
};
524+
let prec = Some(expr.precedence());
525+
526+
if needs_parens {
527+
w!(self, "(");
528+
}
514529

515530
match expr {
516531
Expr::Missing => w!(self, "�"),
@@ -544,7 +559,7 @@ impl Printer<'_> {
544559
w!(self, "let ");
545560
self.print_pat(*pat);
546561
w!(self, " = ");
547-
self.print_expr(*expr);
562+
self.print_expr_in(prec, *expr);
548563
}
549564
Expr::Loop { body, label } => {
550565
if let Some(lbl) = label {
@@ -554,7 +569,7 @@ impl Printer<'_> {
554569
self.print_expr(*body);
555570
}
556571
Expr::Call { callee, args } => {
557-
self.print_expr(*callee);
572+
self.print_expr_in(prec, *callee);
558573
w!(self, "(");
559574
if !args.is_empty() {
560575
self.indented(|p| {
@@ -567,7 +582,7 @@ impl Printer<'_> {
567582
w!(self, ")");
568583
}
569584
Expr::MethodCall { receiver, method_name, args, generic_args } => {
570-
self.print_expr(*receiver);
585+
self.print_expr_in(prec, *receiver);
571586
w!(self, ".{}", method_name.display(self.db, self.edition));
572587
if let Some(args) = generic_args {
573588
w!(self, "::<");
@@ -616,26 +631,26 @@ impl Printer<'_> {
616631
}
617632
if let Some(expr) = expr {
618633
self.whitespace();
619-
self.print_expr(*expr);
634+
self.print_expr_in(prec, *expr);
620635
}
621636
}
622637
Expr::Return { expr } => {
623638
w!(self, "return");
624639
if let Some(expr) = expr {
625640
self.whitespace();
626-
self.print_expr(*expr);
641+
self.print_expr_in(prec, *expr);
627642
}
628643
}
629644
Expr::Become { expr } => {
630645
w!(self, "become");
631646
self.whitespace();
632-
self.print_expr(*expr);
647+
self.print_expr_in(prec, *expr);
633648
}
634649
Expr::Yield { expr } => {
635650
w!(self, "yield");
636651
if let Some(expr) = expr {
637652
self.whitespace();
638-
self.print_expr(*expr);
653+
self.print_expr_in(prec, *expr);
639654
}
640655
}
641656
Expr::Yeet { expr } => {
@@ -644,7 +659,7 @@ impl Printer<'_> {
644659
w!(self, "yeet");
645660
if let Some(expr) = expr {
646661
self.whitespace();
647-
self.print_expr(*expr);
662+
self.print_expr_in(prec, *expr);
648663
}
649664
}
650665
Expr::RecordLit { path, fields, spread } => {
@@ -670,15 +685,15 @@ impl Printer<'_> {
670685
w!(self, "}}");
671686
}
672687
Expr::Field { expr, name } => {
673-
self.print_expr(*expr);
688+
self.print_expr_in(prec, *expr);
674689
w!(self, ".{}", name.display(self.db, self.edition));
675690
}
676691
Expr::Await { expr } => {
677-
self.print_expr(*expr);
692+
self.print_expr_in(prec, *expr);
678693
w!(self, ".await");
679694
}
680695
Expr::Cast { expr, type_ref } => {
681-
self.print_expr(*expr);
696+
self.print_expr_in(prec, *expr);
682697
w!(self, " as ");
683698
self.print_type_ref(*type_ref);
684699
}
@@ -690,11 +705,11 @@ impl Printer<'_> {
690705
if mutability.is_mut() {
691706
w!(self, "mut ");
692707
}
693-
self.print_expr(*expr);
708+
self.print_expr_in(prec, *expr);
694709
}
695710
Expr::Box { expr } => {
696711
w!(self, "box ");
697-
self.print_expr(*expr);
712+
self.print_expr_in(prec, *expr);
698713
}
699714
Expr::UnaryOp { expr, op } => {
700715
let op = match op {
@@ -703,43 +718,32 @@ impl Printer<'_> {
703718
ast::UnaryOp::Neg => "-",
704719
};
705720
w!(self, "{}", op);
706-
self.print_expr(*expr);
721+
self.print_expr_in(prec, *expr);
707722
}
708723
Expr::BinaryOp { lhs, rhs, op } => {
709-
let (bra, ket) = match op {
710-
None | Some(ast::BinaryOp::Assignment { .. }) => ("", ""),
711-
_ => ("(", ")"),
712-
};
713-
w!(self, "{}", bra);
714-
self.print_expr(*lhs);
715-
w!(self, "{} ", ket);
724+
self.print_expr_in(prec, *lhs);
725+
self.whitespace();
716726
match op {
717727
Some(op) => w!(self, "{}", op),
718728
None => w!(self, "�"), // :)
719729
}
720-
w!(self, " {}", bra);
721-
self.print_expr(*rhs);
722-
w!(self, "{}", ket);
730+
self.whitespace();
731+
self.print_expr_in(prec, *rhs);
723732
}
724733
Expr::Range { lhs, rhs, range_type } => {
725734
if let Some(lhs) = lhs {
726-
w!(self, "(");
727-
self.print_expr(*lhs);
728-
w!(self, ") ");
735+
self.print_expr_in(prec, *lhs);
729736
}
730-
let range = match range_type {
731-
ast::RangeOp::Exclusive => "..",
732-
ast::RangeOp::Inclusive => "..=",
737+
match range_type {
738+
ast::RangeOp::Exclusive => w!(self, ".."),
739+
ast::RangeOp::Inclusive => w!(self, "..="),
733740
};
734-
w!(self, "{}", range);
735741
if let Some(rhs) = rhs {
736-
w!(self, "(");
737-
self.print_expr(*rhs);
738-
w!(self, ") ");
742+
self.print_expr_in(prec, *rhs);
739743
}
740744
}
741745
Expr::Index { base, index } => {
742-
self.print_expr(*base);
746+
self.print_expr_in(prec, *base);
743747
w!(self, "[");
744748
self.print_expr(*index);
745749
w!(self, "]");
@@ -826,9 +830,13 @@ impl Printer<'_> {
826830
&Expr::Assignment { target, value } => {
827831
self.print_pat(target);
828832
w!(self, " = ");
829-
self.print_expr(value);
833+
self.print_expr_in(prec, value);
830834
}
831835
}
836+
837+
if needs_parens {
838+
w!(self, ")");
839+
}
832840
}
833841

834842
fn print_block(
@@ -857,6 +865,7 @@ impl Printer<'_> {
857865
}
858866

859867
fn print_pat(&mut self, pat: PatId) {
868+
let prec = Some(ast::prec::ExprPrecedence::Shift);
860869
let pat = &self.store[pat];
861870

862871
match pat {
@@ -930,11 +939,11 @@ impl Printer<'_> {
930939
}
931940
Pat::Range { start, end } => {
932941
if let Some(start) = start {
933-
self.print_expr(*start);
942+
self.print_expr_in(prec, *start);
934943
}
935944
w!(self, "..=");
936945
if let Some(end) = end {
937-
self.print_expr(*end);
946+
self.print_expr_in(prec, *end);
938947
}
939948
}
940949
Pat::Slice { prefix, slice, suffix } => {
@@ -954,7 +963,7 @@ impl Printer<'_> {
954963
w!(self, "]");
955964
}
956965
Pat::Path(path) => self.print_path(path),
957-
Pat::Lit(expr) => self.print_expr(*expr),
966+
Pat::Lit(expr) => self.print_expr_in(prec, *expr),
958967
Pat::Bind { id, subpat } => {
959968
self.print_binding(*id);
960969
if let Some(pat) = subpat {
@@ -996,7 +1005,7 @@ impl Printer<'_> {
9961005
self.print_expr(*c);
9971006
}
9981007
Pat::Expr(expr) => {
999-
self.print_expr(*expr);
1008+
self.print_expr_in(prec, *expr);
10001009
}
10011010
}
10021011
}
@@ -1181,7 +1190,9 @@ impl Printer<'_> {
11811190
pub(crate) fn print_generic_arg(&mut self, arg: &GenericArg) {
11821191
match arg {
11831192
GenericArg::Type(ty) => self.print_type_ref(*ty),
1184-
GenericArg::Const(ConstRef { expr }) => self.print_expr(*expr),
1193+
GenericArg::Const(ConstRef { expr }) => {
1194+
self.print_expr_in(Some(ast::prec::ExprPrecedence::Unambiguous), *expr)
1195+
}
11851196
GenericArg::Lifetime(lt) => self.print_lifetime_ref(*lt),
11861197
}
11871198
}

crates/hir-def/src/expr_store/tests/body.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ fn main() {
159159
expect![[r#"
160160
fn main() {
161161
match builtin#lang(into_iter)(
162-
(0) ..(10) ,
162+
0..10,
163163
) {
164164
mut <ra@gennew>11 => loop {
165165
match builtin#lang(next)(
@@ -590,3 +590,30 @@ const fn f(x: i32) -> i32 {
590590
_ => {}
591591
}
592592
}
593+
594+
#[test]
595+
fn print_hir_precedences() {
596+
let (db, body, def) = lower(
597+
r#"
598+
fn main() {
599+
_ = &(1 - (2 - 3) + 4 * 5 * (6 + 7));
600+
_ = 1 + 2 < 3 && true && 4 < 5 && (a || b || c) || d && e;
601+
if let _ = 2 && true && let _ = 3 {}
602+
break a && b || (return) || (return 2);
603+
let r = &2;
604+
let _ = &mut (*r as i32)
605+
}
606+
"#,
607+
);
608+
609+
expect![[r#"
610+
fn main() {
611+
_ = &((1 - (2 - 3)) + (4 * 5) * (6 + 7));
612+
_ = 1 + 2 < 3 && true && 4 < 5 && (a || b || c) || d && e;
613+
if let _ = 2 && true && let _ = 3 {}
614+
break a && b || (return) || (return 2);
615+
let r = &2;
616+
let _ = &mut (*r as i32);
617+
}"#]]
618+
.assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
619+
}

crates/hir-def/src/hir.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,72 @@ pub enum Expr {
322322
InlineAsm(InlineAsm),
323323
}
324324

325+
impl Expr {
326+
pub fn precedence(&self) -> ast::prec::ExprPrecedence {
327+
use ast::prec::ExprPrecedence;
328+
329+
match self {
330+
Expr::Array(_)
331+
| Expr::InlineAsm(_)
332+
| Expr::Block { .. }
333+
| Expr::Unsafe { .. }
334+
| Expr::Const(_)
335+
| Expr::Async { .. }
336+
| Expr::If { .. }
337+
| Expr::Literal(_)
338+
| Expr::Loop { .. }
339+
| Expr::Match { .. }
340+
| Expr::Missing
341+
| Expr::Path(_)
342+
| Expr::RecordLit { .. }
343+
| Expr::Tuple { .. }
344+
| Expr::OffsetOf(_)
345+
| Expr::Underscore => ExprPrecedence::Unambiguous,
346+
347+
Expr::Await { .. }
348+
| Expr::Call { .. }
349+
| Expr::Field { .. }
350+
| Expr::Index { .. }
351+
| Expr::MethodCall { .. } => ExprPrecedence::Postfix,
352+
353+
Expr::Box { .. } | Expr::Let { .. } | Expr::UnaryOp { .. } | Expr::Ref { .. } => {
354+
ExprPrecedence::Prefix
355+
}
356+
357+
Expr::Cast { .. } => ExprPrecedence::Cast,
358+
359+
Expr::BinaryOp { op, .. } => match op {
360+
None => ExprPrecedence::Unambiguous,
361+
Some(BinaryOp::LogicOp(LogicOp::Or)) => ExprPrecedence::LOr,
362+
Some(BinaryOp::LogicOp(LogicOp::And)) => ExprPrecedence::LAnd,
363+
Some(BinaryOp::CmpOp(_)) => ExprPrecedence::Compare,
364+
Some(BinaryOp::Assignment { .. }) => ExprPrecedence::Assign,
365+
Some(BinaryOp::ArithOp(arith_op)) => match arith_op {
366+
ArithOp::Add | ArithOp::Sub => ExprPrecedence::Sum,
367+
ArithOp::Mul | ArithOp::Div | ArithOp::Rem => ExprPrecedence::Product,
368+
ArithOp::Shl | ArithOp::Shr => ExprPrecedence::Shift,
369+
ArithOp::BitXor => ExprPrecedence::BitXor,
370+
ArithOp::BitOr => ExprPrecedence::BitOr,
371+
ArithOp::BitAnd => ExprPrecedence::BitAnd,
372+
},
373+
},
374+
375+
Expr::Assignment { .. } => ExprPrecedence::Assign,
376+
377+
Expr::Become { .. }
378+
| Expr::Break { .. }
379+
| Expr::Closure { .. }
380+
| Expr::Return { .. }
381+
| Expr::Yeet { .. }
382+
| Expr::Yield { .. } => ExprPrecedence::Jump,
383+
384+
Expr::Continue { .. } => ExprPrecedence::Unambiguous,
385+
386+
Expr::Range { .. } => ExprPrecedence::Range,
387+
}
388+
}
389+
}
390+
325391
#[derive(Debug, Clone, PartialEq, Eq)]
326392
pub struct OffsetOf {
327393
pub container: TypeRefId,

0 commit comments

Comments
 (0)