Skip to content

Commit 8579a18

Browse files
committed
Auto merge of #119212 - w-utter:pretty-print-const-expr, r=compiler-errors
Fix representation when printing abstract consts Previously, when printing a const generic expr, it would only display it as `{{const expr}}`. This allows for a more legible representation when printing these out. I also zipped the types with their constants for abstract consts that contain function calls when using type annotations, eg: `foo(S: usize, true: bool) -> usize` insteaad of `foo(S, true): fn(usize, bool) -> usize` for conciseness.
2 parents 91b87c4 + 7c4b07d commit 8579a18

File tree

4 files changed

+160
-12
lines changed

4 files changed

+160
-12
lines changed

Diff for: compiler/rustc_middle/src/ty/print/pretty.rs

+152-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::query::Providers;
44
use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing};
55
use crate::ty::GenericArgKind;
66
use crate::ty::{
7-
ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
7+
ConstInt, Expr, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
88
TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
99
};
1010
use rustc_apfloat::ieee::{Double, Single};
@@ -270,6 +270,31 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
270270
Ok(())
271271
}
272272

273+
/// Prints `(...)` around what `f` prints.
274+
fn parenthesized(
275+
&mut self,
276+
f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
277+
) -> Result<(), PrintError> {
278+
self.write_str("(")?;
279+
f(self)?;
280+
self.write_str(")")?;
281+
Ok(())
282+
}
283+
284+
/// Prints `(...)` around what `f` prints if `parenthesized` is true, otherwise just prints `f`.
285+
fn maybe_parenthesized(
286+
&mut self,
287+
f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
288+
parenthesized: bool,
289+
) -> Result<(), PrintError> {
290+
if parenthesized {
291+
self.parenthesized(f)?;
292+
} else {
293+
f(self)?;
294+
}
295+
Ok(())
296+
}
297+
273298
/// Prints `<...>` around what `f` prints.
274299
fn generic_delimiters(
275300
&mut self,
@@ -1490,12 +1515,137 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
14901515
ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
14911516
// FIXME(generic_const_exprs):
14921517
// write out some legible representation of an abstract const?
1493-
ty::ConstKind::Expr(_) => p!("{{const expr}}"),
1518+
ty::ConstKind::Expr(expr) => self.pretty_print_const_expr(expr, print_ty)?,
14941519
ty::ConstKind::Error(_) => p!("{{const error}}"),
14951520
};
14961521
Ok(())
14971522
}
14981523

1524+
fn pretty_print_const_expr(
1525+
&mut self,
1526+
expr: Expr<'tcx>,
1527+
print_ty: bool,
1528+
) -> Result<(), PrintError> {
1529+
define_scoped_cx!(self);
1530+
match expr {
1531+
Expr::Binop(op, c1, c2) => {
1532+
let precedence = |binop: rustc_middle::mir::BinOp| {
1533+
use rustc_ast::util::parser::AssocOp;
1534+
AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
1535+
};
1536+
let op_precedence = precedence(op);
1537+
let formatted_op = op.to_hir_binop().as_str();
1538+
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
1539+
(
1540+
ty::ConstKind::Expr(Expr::Binop(lhs_op, _, _)),
1541+
ty::ConstKind::Expr(Expr::Binop(rhs_op, _, _)),
1542+
) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence),
1543+
(ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), ty::ConstKind::Expr(_)) => {
1544+
(precedence(lhs_op) < op_precedence, true)
1545+
}
1546+
(ty::ConstKind::Expr(_), ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
1547+
(true, precedence(rhs_op) < op_precedence)
1548+
}
1549+
(ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true),
1550+
(ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), _) => {
1551+
(precedence(lhs_op) < op_precedence, false)
1552+
}
1553+
(_, ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
1554+
(false, precedence(rhs_op) < op_precedence)
1555+
}
1556+
(ty::ConstKind::Expr(_), _) => (true, false),
1557+
(_, ty::ConstKind::Expr(_)) => (false, true),
1558+
_ => (false, false),
1559+
};
1560+
1561+
self.maybe_parenthesized(
1562+
|this| this.pretty_print_const(c1, print_ty),
1563+
lhs_parenthesized,
1564+
)?;
1565+
p!(write(" {formatted_op} "));
1566+
self.maybe_parenthesized(
1567+
|this| this.pretty_print_const(c2, print_ty),
1568+
rhs_parenthesized,
1569+
)?;
1570+
}
1571+
Expr::UnOp(op, ct) => {
1572+
use rustc_middle::mir::UnOp;
1573+
let formatted_op = match op {
1574+
UnOp::Not => "!",
1575+
UnOp::Neg => "-",
1576+
};
1577+
let parenthesized = match ct.kind() {
1578+
ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
1579+
ty::ConstKind::Expr(_) => true,
1580+
_ => false,
1581+
};
1582+
p!(write("{formatted_op}"));
1583+
self.maybe_parenthesized(
1584+
|this| this.pretty_print_const(ct, print_ty),
1585+
parenthesized,
1586+
)?
1587+
}
1588+
Expr::FunctionCall(fn_def, fn_args) => {
1589+
use ty::TyKind;
1590+
match fn_def.ty().kind() {
1591+
TyKind::FnDef(def_id, gen_args) => {
1592+
p!(print_value_path(*def_id, gen_args), "(");
1593+
if print_ty {
1594+
let tcx = self.tcx();
1595+
let sig = tcx.fn_sig(def_id).instantiate(tcx, gen_args).skip_binder();
1596+
1597+
let mut args_with_ty = fn_args.iter().map(|ct| (ct, ct.ty()));
1598+
let output_ty = sig.output();
1599+
1600+
if let Some((ct, ty)) = args_with_ty.next() {
1601+
self.typed_value(
1602+
|this| this.pretty_print_const(ct, print_ty),
1603+
|this| this.pretty_print_type(ty),
1604+
": ",
1605+
)?;
1606+
for (ct, ty) in args_with_ty {
1607+
p!(", ");
1608+
self.typed_value(
1609+
|this| this.pretty_print_const(ct, print_ty),
1610+
|this| this.pretty_print_type(ty),
1611+
": ",
1612+
)?;
1613+
}
1614+
}
1615+
p!(write(") -> {output_ty}"));
1616+
} else {
1617+
p!(comma_sep(fn_args.iter()), ")");
1618+
}
1619+
}
1620+
_ => bug!("unexpected type of fn def"),
1621+
}
1622+
}
1623+
Expr::Cast(kind, ct, ty) => {
1624+
use ty::abstract_const::CastKind;
1625+
if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) {
1626+
let parenthesized = match ct.kind() {
1627+
ty::ConstKind::Expr(Expr::Cast(_, _, _)) => false,
1628+
ty::ConstKind::Expr(_) => true,
1629+
_ => false,
1630+
};
1631+
self.maybe_parenthesized(
1632+
|this| {
1633+
this.typed_value(
1634+
|this| this.pretty_print_const(ct, print_ty),
1635+
|this| this.pretty_print_type(ty),
1636+
" as ",
1637+
)
1638+
},
1639+
parenthesized,
1640+
)?;
1641+
} else {
1642+
self.pretty_print_const(ct, print_ty)?
1643+
}
1644+
}
1645+
}
1646+
Ok(())
1647+
}
1648+
14991649
fn pretty_print_const_scalar(
15001650
&mut self,
15011651
scalar: Scalar,

Diff for: tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ where
1919
//~^^ ERROR: unconstrained generic constant
2020
//~^^^ ERROR: function takes 1 generic argument but 2 generic arguments were supplied
2121
//~^^^^ ERROR: unconstrained generic constant
22-
//~^^^^^ ERROR: unconstrained generic constant `{const expr}`
23-
//~^^^^^^ ERROR: unconstrained generic constant `{const expr}`
22+
//~^^^^^ ERROR: unconstrained generic constant `L + 1 + L`
23+
//~^^^^^^ ERROR: unconstrained generic constant `L + 1`
2424
}
2525

2626
fn main() {}

Diff for: tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,17 @@ LL | | }
5252
LL | | }],
5353
| |_____^ required by this bound in `foo`
5454

55-
error: unconstrained generic constant `{const expr}`
55+
error: unconstrained generic constant `L + 1 + L`
5656
--> $DIR/issue_114151.rs:17:5
5757
|
5858
LL | foo::<_, L>([(); L + 1 + L]);
5959
| ^^^^^^^^^^^
6060

61-
error: unconstrained generic constant `{const expr}`
61+
error: unconstrained generic constant `L + 1`
6262
--> $DIR/issue_114151.rs:17:5
6363
|
6464
LL | foo::<_, L>([(); L + 1 + L]);
6565
| ^^^^^^^^^^^
66-
|
67-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6866

6967
error: aborting due to 6 previous errors
7068

Diff for: tests/ui/const-generics/transmute-fail.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
44
LL | std::mem::transmute(v)
55
| ^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: source type: `[[u32; H+1]; W]` (generic size {const expr})
8-
= note: target type: `[[u32; W+1]; H]` (generic size {const expr})
7+
= note: source type: `[[u32; H+1]; W]` (generic size (H + 1) * 4 * W)
8+
= note: target type: `[[u32; W+1]; H]` (generic size (W + 1) * 4 * H)
99

1010
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
1111
--> $DIR/transmute-fail.rs:16:5
@@ -22,8 +22,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
2222
LL | std::mem::transmute(v)
2323
| ^^^^^^^^^^^^^^^^^^^
2424
|
25-
= note: source type: `[[u32; H]; W]` (generic size {const expr})
26-
= note: target type: `[u32; W * H * H]` (generic size {const expr})
25+
= note: source type: `[[u32; H]; W]` (generic size 4 * H * W)
26+
= note: target type: `[u32; W * H * H]` (generic size 4 * H * H * W)
2727

2828
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
2929
--> $DIR/transmute-fail.rs:30:5

0 commit comments

Comments
 (0)