about summary refs log tree commit diff
diff options
context:
space:
mode:
authorwill <104373134+w-utter@users.noreply.github.com>2024-03-17 01:38:45 +1100
committerwill <104373134+w-utter@users.noreply.github.com>2024-03-17 01:38:45 +1100
commit7c4b07d5e838268293d2d5c94e0a2454fdd54c6c (patch)
tree713b4b2a8fc0e7ca728448ec4c5050a6818ee6b1
parent9023f908cfbe7a475f369717a61cb8eb865cfd25 (diff)
downloadrust-7c4b07d5e838268293d2d5c94e0a2454fdd54c6c.tar.gz
rust-7c4b07d5e838268293d2d5c94e0a2454fdd54c6c.zip
added pretty_print_const_expr
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs154
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr6
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr8
4 files changed, 160 insertions, 12 deletions
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 802953867ac..995b439d10a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -4,7 +4,7 @@ use crate::query::Providers;
 use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing};
 use crate::ty::GenericArgKind;
 use crate::ty::{
-    ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
+    ConstInt, Expr, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
     TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
 use rustc_apfloat::ieee::{Double, Single};
@@ -270,6 +270,31 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         Ok(())
     }
 
+    /// Prints `(...)` around what `f` prints.
+    fn parenthesized(
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+    ) -> Result<(), PrintError> {
+        self.write_str("(")?;
+        f(self)?;
+        self.write_str(")")?;
+        Ok(())
+    }
+
+    /// Prints `(...)` around what `f` prints if `parenthesized` is true, otherwise just prints `f`.
+    fn maybe_parenthesized(
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+        parenthesized: bool,
+    ) -> Result<(), PrintError> {
+        if parenthesized {
+            self.parenthesized(f)?;
+        } else {
+            f(self)?;
+        }
+        Ok(())
+    }
+
     /// Prints `<...>` around what `f` prints.
     fn generic_delimiters(
         &mut self,
@@ -1490,12 +1515,137 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
             // FIXME(generic_const_exprs):
             // write out some legible representation of an abstract const?
-            ty::ConstKind::Expr(_) => p!("{{const expr}}"),
+            ty::ConstKind::Expr(expr) => self.pretty_print_const_expr(expr, print_ty)?,
             ty::ConstKind::Error(_) => p!("{{const error}}"),
         };
         Ok(())
     }
 
+    fn pretty_print_const_expr(
+        &mut self,
+        expr: Expr<'tcx>,
+        print_ty: bool,
+    ) -> Result<(), PrintError> {
+        define_scoped_cx!(self);
+        match expr {
+            Expr::Binop(op, c1, c2) => {
+                let precedence = |binop: rustc_middle::mir::BinOp| {
+                    use rustc_ast::util::parser::AssocOp;
+                    AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
+                };
+                let op_precedence = precedence(op);
+                let formatted_op = op.to_hir_binop().as_str();
+                let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
+                    (
+                        ty::ConstKind::Expr(Expr::Binop(lhs_op, _, _)),
+                        ty::ConstKind::Expr(Expr::Binop(rhs_op, _, _)),
+                    ) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence),
+                    (ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), ty::ConstKind::Expr(_)) => {
+                        (precedence(lhs_op) < op_precedence, true)
+                    }
+                    (ty::ConstKind::Expr(_), ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
+                        (true, precedence(rhs_op) < op_precedence)
+                    }
+                    (ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true),
+                    (ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), _) => {
+                        (precedence(lhs_op) < op_precedence, false)
+                    }
+                    (_, ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
+                        (false, precedence(rhs_op) < op_precedence)
+                    }
+                    (ty::ConstKind::Expr(_), _) => (true, false),
+                    (_, ty::ConstKind::Expr(_)) => (false, true),
+                    _ => (false, false),
+                };
+
+                self.maybe_parenthesized(
+                    |this| this.pretty_print_const(c1, print_ty),
+                    lhs_parenthesized,
+                )?;
+                p!(write(" {formatted_op} "));
+                self.maybe_parenthesized(
+                    |this| this.pretty_print_const(c2, print_ty),
+                    rhs_parenthesized,
+                )?;
+            }
+            Expr::UnOp(op, ct) => {
+                use rustc_middle::mir::UnOp;
+                let formatted_op = match op {
+                    UnOp::Not => "!",
+                    UnOp::Neg => "-",
+                };
+                let parenthesized = match ct.kind() {
+                    ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
+                    ty::ConstKind::Expr(_) => true,
+                    _ => false,
+                };
+                p!(write("{formatted_op}"));
+                self.maybe_parenthesized(
+                    |this| this.pretty_print_const(ct, print_ty),
+                    parenthesized,
+                )?
+            }
+            Expr::FunctionCall(fn_def, fn_args) => {
+                use ty::TyKind;
+                match fn_def.ty().kind() {
+                    TyKind::FnDef(def_id, gen_args) => {
+                        p!(print_value_path(*def_id, gen_args), "(");
+                        if print_ty {
+                            let tcx = self.tcx();
+                            let sig = tcx.fn_sig(def_id).instantiate(tcx, gen_args).skip_binder();
+
+                            let mut args_with_ty = fn_args.iter().map(|ct| (ct, ct.ty()));
+                            let output_ty = sig.output();
+
+                            if let Some((ct, ty)) = args_with_ty.next() {
+                                self.typed_value(
+                                    |this| this.pretty_print_const(ct, print_ty),
+                                    |this| this.pretty_print_type(ty),
+                                    ": ",
+                                )?;
+                                for (ct, ty) in args_with_ty {
+                                    p!(", ");
+                                    self.typed_value(
+                                        |this| this.pretty_print_const(ct, print_ty),
+                                        |this| this.pretty_print_type(ty),
+                                        ": ",
+                                    )?;
+                                }
+                            }
+                            p!(write(") -> {output_ty}"));
+                        } else {
+                            p!(comma_sep(fn_args.iter()), ")");
+                        }
+                    }
+                    _ => bug!("unexpected type of fn def"),
+                }
+            }
+            Expr::Cast(kind, ct, ty) => {
+                use ty::abstract_const::CastKind;
+                if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) {
+                    let parenthesized = match ct.kind() {
+                        ty::ConstKind::Expr(Expr::Cast(_, _, _)) => false,
+                        ty::ConstKind::Expr(_) => true,
+                        _ => false,
+                    };
+                    self.maybe_parenthesized(
+                        |this| {
+                            this.typed_value(
+                                |this| this.pretty_print_const(ct, print_ty),
+                                |this| this.pretty_print_type(ty),
+                                " as ",
+                            )
+                        },
+                        parenthesized,
+                    )?;
+                } else {
+                    self.pretty_print_const(ct, print_ty)?
+                }
+            }
+        }
+        Ok(())
+    }
+
     fn pretty_print_const_scalar(
         &mut self,
         scalar: Scalar,
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
index 9cdb4158d2b..e575d0dc9b4 100644
--- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
@@ -19,8 +19,8 @@ where
     //~^^ ERROR: unconstrained generic constant
     //~^^^ ERROR: function takes 1 generic argument but 2 generic arguments were supplied
     //~^^^^ ERROR: unconstrained generic constant
-    //~^^^^^ ERROR: unconstrained generic constant `{const expr}`
-    //~^^^^^^ ERROR: unconstrained generic constant `{const expr}`
+    //~^^^^^ ERROR: unconstrained generic constant `L + 1 + L`
+    //~^^^^^^ ERROR: unconstrained generic constant `L + 1`
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr
index 14c58f8d0da..9a8aa222dc1 100644
--- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr
@@ -52,19 +52,17 @@ LL | |         }
 LL | |     }],
    | |_____^ required by this bound in `foo`
 
-error: unconstrained generic constant `{const expr}`
+error: unconstrained generic constant `L + 1 + L`
   --> $DIR/issue_114151.rs:17:5
    |
 LL |     foo::<_, L>([(); L + 1 + L]);
    |     ^^^^^^^^^^^
 
-error: unconstrained generic constant `{const expr}`
+error: unconstrained generic constant `L + 1`
   --> $DIR/issue_114151.rs:17:5
    |
 LL |     foo::<_, L>([(); L + 1 + L]);
    |     ^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 12644b9f36d..397e3be768a 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H+1]; W]` (generic size {const expr})
-   = note: target type: `[[u32; W+1]; H]` (generic size {const expr})
+   = note: source type: `[[u32; H+1]; W]` (generic size (H + 1) * 4 * W)
+   = note: target type: `[[u32; W+1]; H]` (generic size (W + 1) * 4 * H)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:16:5
@@ -22,8 +22,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H]; W]` (generic size {const expr})
-   = note: target type: `[u32; W * H * H]` (generic size {const expr})
+   = note: source type: `[[u32; H]; W]` (generic size 4 * H * W)
+   = note: target type: `[u32; W * H * H]` (generic size 4 * H * H * W)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:30:5