Skip to content

Commit

Permalink
Rollup merge of #137423 - Urgau:imprv-pretty-hir, r=compiler-errors
Browse files Browse the repository at this point in the history
Improve a bit HIR pretty printer

This PR improve (a bit) the HIR pretty printer.

It does so by:
 - Not printing elided lifetimes (those are not expressible in surface Rust anyway)
 - And by rendering implicit self with the shorthand syntax

I also tried fixing some indentation and other things but gave up for now.

Best reviewed commit by commit.
  • Loading branch information
jhpratt authored Feb 23, 2025
2 parents 553fde4 + d0e7bfd commit 4bed9ec
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 21 deletions.
14 changes: 9 additions & 5 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,20 +424,23 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.ann_post(ident)
}

fn strsep<T, F>(
fn strsep<'x, T: 'x, F, I>(
&mut self,
sep: &'static str,
space_before: bool,
b: Breaks,
elts: &[T],
elts: I,
mut op: F,
) where
F: FnMut(&mut Self, &T),
I: IntoIterator<Item = &'x T>,
{
let mut it = elts.into_iter();

self.rbox(0, b);
if let Some((first, rest)) = elts.split_first() {
if let Some(first) = it.next() {
op(self, first);
for elt in rest {
for elt in it {
if space_before {
self.space();
}
Expand All @@ -448,9 +451,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.end();
}

fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F)
fn commasep<'x, T: 'x, F, I>(&mut self, b: Breaks, elts: I, op: F)
where
F: FnMut(&mut Self, &T),
I: IntoIterator<Item = &'x T>,
{
self.strsep(",", false, b, elts, op)
}
Expand Down
76 changes: 60 additions & 16 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use rustc_ast_pretty::pprust::state::MacHeader;
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir::{
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TyPatKind,
HirId, ImplicitSelfKind, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
TyPatKind,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, Ident, Span, Symbol, kw};
Expand Down Expand Up @@ -2086,6 +2087,28 @@ impl<'a> State<'a> {
self.print_pat(arg.pat);
}

fn print_implicit_self(&mut self, implicit_self_kind: &hir::ImplicitSelfKind) {
match implicit_self_kind {
ImplicitSelfKind::Imm => {
self.word("self");
}
ImplicitSelfKind::Mut => {
self.print_mutability(hir::Mutability::Mut, false);
self.word("self");
}
ImplicitSelfKind::RefImm => {
self.word("&");
self.word("self");
}
ImplicitSelfKind::RefMut => {
self.word("&");
self.print_mutability(hir::Mutability::Mut, false);
self.word("self");
}
ImplicitSelfKind::None => unreachable!(),
}
}

fn print_arm(&mut self, arm: &hir::Arm<'_>) {
// I have no idea why this check is necessary, but here it
// is :(
Expand Down Expand Up @@ -2151,27 +2174,33 @@ impl<'a> State<'a> {
// Make sure we aren't supplied *both* `arg_names` and `body_id`.
assert!(arg_names.is_empty() || body_id.is_none());
let mut i = 0;
let mut print_arg = |s: &mut Self| {
if let Some(arg_name) = arg_names.get(i) {
s.word(arg_name.to_string());
s.word(":");
s.space();
} else if let Some(body_id) = body_id {
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
s.word(":");
s.space();
let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| {
if i == 0 && decl.implicit_self.has_implicit_self() {
s.print_implicit_self(&decl.implicit_self);
} else {
if let Some(arg_name) = arg_names.get(i) {
s.word(arg_name.to_string());
s.word(":");
s.space();
} else if let Some(body_id) = body_id {
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
s.word(":");
s.space();
}
if let Some(ty) = ty {
s.print_type(ty);
}
}
i += 1;
};
self.commasep(Inconsistent, decl.inputs, |s, ty| {
s.ibox(INDENT_UNIT);
print_arg(s);
s.print_type(ty);
print_arg(s, Some(ty));
s.end();
});
if decl.c_variadic {
self.word(", ");
print_arg(self);
print_arg(self, None);
self.word("...");
}
self.pclose();
Expand Down Expand Up @@ -2284,7 +2313,9 @@ impl<'a> State<'a> {
GenericBound::Use(args, _) => {
self.word("use <");

self.commasep(Inconsistent, args, |s, arg| s.print_precise_capturing_arg(*arg));
self.commasep(Inconsistent, *args, |s, arg| {
s.print_precise_capturing_arg(*arg)
});

self.word(">");
}
Expand All @@ -2300,10 +2331,23 @@ impl<'a> State<'a> {
}

fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) {
if !generic_params.is_empty() {
let is_lifetime_elided = |generic_param: &GenericParam<'_>| {
matches!(
generic_param.kind,
GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) }
)
};

// We don't want to show elided lifetimes as they are compiler-inserted and not
// expressible in surface level Rust.
if !generic_params.is_empty() && !generic_params.iter().all(is_lifetime_elided) {
self.word("<");

self.commasep(Inconsistent, generic_params, |s, param| s.print_generic_param(param));
self.commasep(
Inconsistent,
generic_params.iter().filter(|gp| !is_lifetime_elided(gp)),
|s, param| s.print_generic_param(param),
);

self.word(">");
}
Expand Down
26 changes: 26 additions & 0 deletions tests/ui/unpretty/debug-fmt-hir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass

use std::fmt;

pub struct Bar {
a: String,
b: u8,
}

impl fmt::Debug for Bar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_struct_field2_finish(f, "Bar", "a", &self.a, "b", &&self.b)
}
}

fn debug_struct_field2_finish<'a>(
name: &str,
name1: &str,
value1: &'a dyn fmt::Debug,
name2: &str,
value2: &'a dyn fmt::Debug,
) -> fmt::Result
{
loop {}
}
25 changes: 25 additions & 0 deletions tests/ui/unpretty/debug-fmt-hir.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

use std::fmt;

struct Bar {
a: String,
b: u8,
}

impl fmt::Debug for Bar {
fn fmt(&self, f: &'_ mut fmt::Formatter<'_>)
->
fmt::Result {
debug_struct_field2_finish(f, "Bar", "a", &self.a, "b", &&self.b)
}
}

fn debug_struct_field2_finish<'a>(name: &'_ str, name1: &'_ str,
value1: &'a dyn fmt::Debug, name2: &'_ str, value2: &'a dyn fmt::Debug)
-> fmt::Result { loop { } }
14 changes: 14 additions & 0 deletions tests/ui/unpretty/self-hir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass

pub struct Bar {
a: String,
b: u8,
}

impl Bar {
fn imm_self(self) {}
fn mut_self(mut self) {}
fn refimm_self(&self) {}
fn refmut_self(&mut self) {}
}
18 changes: 18 additions & 0 deletions tests/ui/unpretty/self-hir.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

struct Bar {
a: String,
b: u8,
}

impl Bar {
fn imm_self(self) { }
fn mut_self(mut self) { }
fn refimm_self(&self) { }
fn refmut_self(&mut self) { }
}

0 comments on commit 4bed9ec

Please sign in to comment.