1
Fork 0

use fmt::from_fn in more places, instead of using structs that impl formatting traits

This commit is contained in:
Yotam Ofek 2025-01-23 19:48:54 +00:00
parent 815be937ab
commit 8b57fd9e43
6 changed files with 124 additions and 174 deletions

View file

@ -184,6 +184,50 @@ enum Scope<'a> {
}, },
} }
impl<'a> Scope<'a> {
// A helper for debugging scopes without printing parent scopes
fn debug_truncated(&'a self) -> impl fmt::Debug + 'a {
fmt::from_fn(move |f| match self {
Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
.debug_struct("Binder")
.field("bound_vars", bound_vars)
.field("scope_type", scope_type)
.field("hir_id", hir_id)
.field("where_bound_origin", where_bound_origin)
.field("s", &"..")
.finish(),
Self::Opaque { captures, def_id, s: _ } => f
.debug_struct("Opaque")
.field("def_id", def_id)
.field("captures", &captures.borrow())
.field("s", &"..")
.finish(),
Self::Body { id, s: _ } => {
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
}
Self::ObjectLifetimeDefault { lifetime, s: _ } => f
.debug_struct("ObjectLifetimeDefault")
.field("lifetime", lifetime)
.field("s", &"..")
.finish(),
Self::Supertrait { bound_vars, s: _ } => f
.debug_struct("Supertrait")
.field("bound_vars", bound_vars)
.field("s", &"..")
.finish(),
Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
Self::LateBoundary { s: _, what, deny_late_regions } => f
.debug_struct("LateBoundary")
.field("what", what)
.field("deny_late_regions", deny_late_regions)
.finish(),
Self::Root { opt_parent_item } => {
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
}
})
}
}
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
enum BinderScopeType { enum BinderScopeType {
/// Any non-concatenating binder scopes. /// Any non-concatenating binder scopes.
@ -200,52 +244,6 @@ enum BinderScopeType {
Concatenating, Concatenating,
} }
// A helper struct for debugging scopes without printing parent scopes
struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
.debug_struct("Binder")
.field("bound_vars", bound_vars)
.field("scope_type", scope_type)
.field("hir_id", hir_id)
.field("where_bound_origin", where_bound_origin)
.field("s", &"..")
.finish(),
Scope::Opaque { captures, def_id, s: _ } => f
.debug_struct("Opaque")
.field("def_id", def_id)
.field("captures", &captures.borrow())
.field("s", &"..")
.finish(),
Scope::Body { id, s: _ } => {
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
}
Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
.debug_struct("ObjectLifetimeDefault")
.field("lifetime", lifetime)
.field("s", &"..")
.finish(),
Scope::Supertrait { bound_vars, s: _ } => f
.debug_struct("Supertrait")
.field("bound_vars", bound_vars)
.field("s", &"..")
.finish(),
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
Scope::LateBoundary { s: _, what, deny_late_regions } => f
.debug_struct("LateBoundary")
.field("what", what)
.field("deny_late_regions", deny_late_regions)
.finish(),
Scope::Root { opt_parent_item } => {
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
}
}
}
}
type ScopeRef<'a> = &'a Scope<'a>; type ScopeRef<'a> = &'a Scope<'a>;
pub(crate) fn provide(providers: &mut Providers) { pub(crate) fn provide(providers: &mut Providers) {
@ -1144,7 +1142,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
{ {
let BoundVarContext { tcx, map, .. } = self; let BoundVarContext { tcx, map, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope }; let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(this.scope)); let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
{ {
let _enter = span.enter(); let _enter = span.enter();
f(&mut this); f(&mut this);

View file

@ -63,6 +63,7 @@ This API is completely unstable and subject to change.
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(coroutines)] #![feature(coroutines)]
#![feature(debug_closure_helpers)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_from_coroutine)] #![feature(iter_from_coroutine)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]

View file

@ -40,6 +40,7 @@
#![feature(const_type_name)] #![feature(const_type_name)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(coroutines)] #![feature(coroutines)]
#![feature(debug_closure_helpers)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(discriminant_kind)] #![feature(discriminant_kind)]
#![feature(extern_types)] #![feature(extern_types)]

View file

@ -1,6 +1,5 @@
//! Values computed by queries that use MIR. //! Values computed by queries that use MIR.
use std::cell::Cell;
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use rustc_abi::{FieldIdx, VariantIdx}; use rustc_abi::{FieldIdx, VariantIdx};
@ -62,55 +61,26 @@ pub struct CoroutineLayout<'tcx> {
impl Debug for CoroutineLayout<'_> { impl Debug for CoroutineLayout<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
/// Prints an iterator of (key, value) tuples as a map. fmt.debug_struct("CoroutineLayout")
struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>); .field_with("field_tys", |fmt| {
impl<'a, K, V> MapPrinter<'a, K, V> { fmt.debug_map().entries(self.field_tys.iter_enumerated()).finish()
fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self { })
Self(Cell::new(Some(Box::new(iter)))) .field_with("variant_fields", |fmt| {
} let mut map = fmt.debug_map();
} for (idx, fields) in self.variant_fields.iter_enumerated() {
impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { map.key_with(|fmt| {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let variant_name = ty::CoroutineArgs::variant_name(idx);
fmt.debug_map().entries(self.0.take().unwrap()).finish()
}
}
/// Prints the coroutine variant name.
struct GenVariantPrinter(VariantIdx);
impl From<VariantIdx> for GenVariantPrinter {
fn from(idx: VariantIdx) -> Self {
GenVariantPrinter(idx)
}
}
impl Debug for GenVariantPrinter {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let variant_name = ty::CoroutineArgs::variant_name(self.0);
if fmt.alternate() { if fmt.alternate() {
write!(fmt, "{:9}({:?})", variant_name, self.0) write!(fmt, "{variant_name:9}({idx:?})")
} else { } else {
write!(fmt, "{variant_name}") write!(fmt, "{variant_name}")
} }
});
// Force variant fields to print in regular mode instead of alternate mode.
map.value_with(|fmt| write!(fmt, "{fields:?}"));
} }
} map.finish()
})
/// Forces its contents to print in regular mode instead of alternate mode.
struct OneLinePrinter<T>(T);
impl<T: Debug> Debug for OneLinePrinter<T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "{:?}", self.0)
}
}
fmt.debug_struct("CoroutineLayout")
.field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
.field(
"variant_fields",
&MapPrinter::new(
self.variant_fields
.iter_enumerated()
.map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
),
)
.field("storage_conflicts", &self.storage_conflicts) .field("storage_conflicts", &self.storage_conflicts)
.finish() .finish()
} }

View file

@ -2325,14 +2325,11 @@ macro_rules! sty_debug_print {
} }
impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxt<'tcx> {
pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx { pub fn debug_stats(self) -> impl fmt::Debug + 'tcx {
struct DebugStats<'tcx>(TyCtxt<'tcx>); fmt::from_fn(move |fmt| {
impl<'tcx> std::fmt::Debug for DebugStats<'tcx> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
sty_debug_print!( sty_debug_print!(
fmt, fmt,
self.0, self,
Adt, Adt,
Array, Array,
Slice, Slice,
@ -2356,20 +2353,13 @@ impl<'tcx> TyCtxt<'tcx> {
Foreign Foreign
)?; )?;
writeln!(fmt, "GenericArgs interner: #{}", self.0.interners.args.len())?; writeln!(fmt, "GenericArgs interner: #{}", self.interners.args.len())?;
writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?; writeln!(fmt, "Region interner: #{}", self.interners.region.len())?;
writeln!( writeln!(fmt, "Const Allocation interner: #{}", self.interners.const_allocation.len())?;
fmt, writeln!(fmt, "Layout interner: #{}", self.interners.layout.len())?;
"Const Allocation interner: #{}",
self.0.interners.const_allocation.len()
)?;
writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
Ok(()) Ok(())
} })
}
DebugStats(self)
} }
} }

View file

@ -1598,21 +1598,14 @@ impl<'a> Parser<'a> {
// Only used when debugging. // Only used when debugging.
#[allow(unused)] #[allow(unused)]
pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ { pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
struct DebugParser<'dbg> { fmt::from_fn(move |f| {
parser: &'dbg Parser<'dbg>,
lookahead: usize,
}
impl fmt::Debug for DebugParser<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { parser, lookahead } = self;
let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of
// we don't need N spans, but we want at least one, so print all of prev_token // we don't need N spans, but we want at least one, so print all of prev_token
dbg_fmt.field("prev_token", &parser.prev_token); dbg_fmt.field("prev_token", &self.prev_token);
let mut tokens = vec![]; let mut tokens = vec![];
for i in 0..*lookahead { for i in 0..lookahead {
let tok = parser.look_ahead(i, |tok| tok.kind.clone()); let tok = self.look_ahead(i, |tok| tok.kind.clone());
let is_eof = tok == TokenKind::Eof; let is_eof = tok == TokenKind::Eof;
tokens.push(tok); tokens.push(tok);
if is_eof { if is_eof {
@ -1621,22 +1614,19 @@ impl<'a> Parser<'a> {
} }
} }
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish()); dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls); dbg_fmt.field("approx_token_stream_pos", &self.num_bump_calls);
// some fields are interesting for certain values, as they relate to macro parsing // some fields are interesting for certain values, as they relate to macro parsing
if let Some(subparser) = parser.subparser_name { if let Some(subparser) = self.subparser_name {
dbg_fmt.field("subparser_name", &subparser); dbg_fmt.field("subparser_name", &subparser);
} }
if let Recovery::Forbidden = parser.recovery { if let Recovery::Forbidden = self.recovery {
dbg_fmt.field("recovery", &parser.recovery); dbg_fmt.field("recovery", &self.recovery);
} }
// imply there's "more to know" than this view // imply there's "more to know" than this view
dbg_fmt.finish_non_exhaustive() dbg_fmt.finish_non_exhaustive()
} })
}
DebugParser { parser: self, lookahead }
} }
pub fn clear_expected_token_types(&mut self) { pub fn clear_expected_token_types(&mut self) {