Skip to content

Commit cf80286

Browse files
Rollup merge of #160360 - mejrs:hir_pretty, r=nnethercote
Remove rustc_middle dependency on rustc_hir_pretty There is a `impl PpAnn for TyCtxt` that is unneeded. None of the big crates (middle, trait_selection) actually do any hir pretty printing so it can be removed and can either be implemented for local structs elsewhere or done by casting to `&dyn PpAnn` instead. This probably doesn't have any perf effects (its not bottlenecking in timings) but I expect it to compose with #160336 and its followup works quite well. Old graph: <img width="1999" height="2171" alt="graph" src="https://github.com/user-attachments/assets/756e6a50-a413-4a8d-a0f3-7bbf4de07933" /> New graph: <img width="1853" height="2171" alt="graph_hir_pretty" src="https://github.com/user-attachments/assets/f9607e5a-d00b-4a86-8f6a-cefb45b75ad7" />
2 parents 73bdae0 + 180c637 commit cf80286

16 files changed

Lines changed: 180 additions & 155 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3954,6 +3954,7 @@ dependencies = [
39543954
"rustc_errors",
39553955
"rustc_expand",
39563956
"rustc_feature",
3957+
"rustc_hir",
39573958
"rustc_hir_analysis",
39583959
"rustc_hir_pretty",
39593960
"rustc_index",
@@ -4414,7 +4415,6 @@ dependencies = [
44144415
"rustc_graphviz",
44154416
"rustc_hashes",
44164417
"rustc_hir",
4417-
"rustc_hir_pretty",
44184418
"rustc_index",
44194419
"rustc_lint_defs",
44204420
"rustc_macros",

compiler/rustc_driver_impl/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
1616
rustc_errors = { path = "../rustc_errors" }
1717
rustc_expand = { path = "../rustc_expand" }
1818
rustc_feature = { path = "../rustc_feature" }
19+
rustc_hir = { path = "../rustc_hir" }
1920
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
2021
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
2122
rustc_index = { path = "../rustc_index" }

compiler/rustc_driver_impl/src/pretty.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use std::io;
77

88
use rustc_ast as ast;
99
use rustc_ast_pretty::pprust as pprust_ast;
10+
use rustc_hir::intravisit;
1011
use rustc_hir_pretty as pprust_hir;
12+
use rustc_hir_pretty::PpAnn;
1113
use rustc_middle::bug;
1214
use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
1315
use rustc_middle::ty::{self, TyCtxt};
@@ -71,7 +73,8 @@ struct HirIdentifiedAnn<'tcx> {
7173

7274
impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> {
7375
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
74-
self.tcx.nested(state, nested)
76+
let this = &self.tcx as &dyn intravisit::HirTyCtxt<'_>;
77+
this.nested(state, nested)
7578
}
7679

7780
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
@@ -149,11 +152,12 @@ struct HirTypedAnn<'tcx> {
149152

150153
impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
151154
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
155+
let this = &self.tcx as &dyn intravisit::HirTyCtxt<'_>;
152156
let old_maybe_typeck_results = self.maybe_typeck_results.get();
153157
if let pprust_hir::Nested::Body(id) = nested {
154158
self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
155159
}
156-
self.tcx.nested(state, nested);
160+
this.nested(state, nested);
157161
self.maybe_typeck_results.set(old_maybe_typeck_results);
158162
}
159163

@@ -281,7 +285,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
281285
)
282286
};
283287
match s {
284-
PpHirMode::Normal => f(&tcx),
288+
PpHirMode::Normal => f(&(&tcx as &dyn intravisit::HirTyCtxt<'_>) as &dyn PpAnn),
285289
PpHirMode::Identified => {
286290
let annotation = HirIdentifiedAnn { tcx };
287291
f(&annotation)

compiler/rustc_hir_typeck/src/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
421421
return self.get_fn_decl(hir_id).map(|(_, fn_decl)| {
422422
let (ty, span) = match fn_decl.output {
423423
hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span),
424-
hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span),
424+
hir::FnRetTy::Return(ty) => (ty_to_string(self, ty), ty.span),
425425
};
426426
(span, format!("expected `{ty}` because of this return type"))
427427
});

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
903903
};
904904
let removal_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
905905
unit_variant =
906-
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(&self.tcx, qpath)));
906+
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(self, qpath)));
907907
}
908908

909909
let callee_ty = self.resolve_vars_if_possible(callee_ty);

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::diagnostics::{
5050
use crate::op::contains_let_in_chain;
5151
use crate::{
5252
BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, GatherLocalsVisitor, Needs,
53-
TupleArgumentsFlag, cast, fatally_break_rust, report_unexpected_variant_res, type_error_struct,
53+
TupleArgumentsFlag, cast, fatally_break_rust, type_error_struct,
5454
};
5555

5656
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -589,8 +589,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
589589
Ty::new_error(tcx, e)
590590
}
591591
Res::Def(DefKind::Variant, _) => {
592-
let e = report_unexpected_variant_res(
593-
tcx,
592+
let e = self.report_unexpected_variant_res(
594593
res,
595594
Some(expr),
596595
&[],

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,16 @@ impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
220220
}
221221
}
222222

223+
impl<'tcx> rustc_hir_pretty::PpAnn for FnCtxt<'_, 'tcx> {
224+
fn nested(&self, state: &mut rustc_hir_pretty::State<'_>, nested: rustc_hir_pretty::Nested) {
225+
rustc_hir_pretty::PpAnn::nested(
226+
&(&self.tcx as &dyn rustc_hir::intravisit::HirTyCtxt<'_>),
227+
state,
228+
nested,
229+
)
230+
}
231+
}
232+
223233
impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
224234
fn tcx(&self) -> TyCtxt<'tcx> {
225235
self.tcx

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,12 +723,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
723723
let hir::FnDecl { inputs, output, .. } = fn_ptr_ty.decl;
724724

725725
let inputs_str =
726-
inputs.iter().map(|ty| rustc_hir_pretty::ty_to_string(&self.tcx, ty)).join(", ");
726+
inputs.iter().map(|ty| rustc_hir_pretty::ty_to_string(self, ty)).join(", ");
727727

728728
let output_str = match output {
729729
hir::FnRetTy::DefaultReturn(_) => String::new(),
730730
hir::FnRetTy::Return(ty) => {
731-
format!(" -> {}", rustc_hir_pretty::ty_to_string(&self.tcx, ty))
731+
format!(" -> {}", rustc_hir_pretty::ty_to_string(self, ty))
732732
}
733733
};
734734

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 124 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -478,134 +478,138 @@ impl<'tcx> EnclosingBreakables<'tcx> {
478478
}
479479
}
480480
}
481-
482-
fn report_unexpected_variant_res(
483-
tcx: TyCtxt<'_>,
484-
res: Res,
485-
expr: Option<&hir::Expr<'_>>,
486-
sub_pats: &[hir::Pat<'_>],
487-
qpath: &hir::QPath<'_>,
488-
span: Span,
489-
err_code: ErrCode,
490-
expected: &str,
491-
) -> ErrorGuaranteed {
492-
let res_descr = match res {
493-
Res::Def(DefKind::Variant, _) => "struct variant",
494-
_ => res.descr(),
495-
};
496-
let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
497-
let mut err = tcx
498-
.dcx()
499-
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
500-
.with_code(err_code);
501-
match res {
502-
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
503-
let patterns_url = "https://doc.rust-lang.org/book/ch19-00-patterns.html";
504-
err.with_span_label(span, "`fn` calls are not allowed in patterns")
505-
.with_help(format!("for more information, visit {patterns_url}"))
506-
}
507-
Res::Def(DefKind::Variant, _) if let Some(expr) = expr => {
508-
err.span_label(span, format!("not a {expected}"));
509-
let variant = tcx.expect_variant_res(res);
510-
let sugg = if variant.fields.is_empty() {
511-
" {}".to_string()
512-
} else {
513-
format!(
514-
" {{ {} }}",
515-
variant
516-
.fields
517-
.iter()
518-
.map(|f| format!("{}: /* value */", f.name))
519-
.collect::<Vec<_>>()
520-
.join(", ")
521-
)
522-
};
523-
let descr = "you might have meant to create a new value of the struct";
524-
let mut suggestion = vec![];
525-
match tcx.parent_hir_node(expr.hir_id) {
526-
hir::Node::Expr(hir::Expr {
527-
kind: hir::ExprKind::Call(..),
528-
span: call_span,
529-
..
530-
}) => {
531-
suggestion.push((span.shrink_to_hi().with_hi(call_span.hi()), sugg));
532-
}
533-
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(..), hir_id, .. }) => {
534-
suggestion.push((expr.span.shrink_to_lo(), "(".to_string()));
535-
if let hir::Node::Expr(parent) = tcx.parent_hir_node(*hir_id)
536-
&& let hir::ExprKind::If(condition, block, None) = parent.kind
537-
&& condition.hir_id == *hir_id
538-
&& let hir::ExprKind::Block(block, _) = block.kind
539-
&& block.stmts.is_empty()
540-
&& let Some(expr) = block.expr
541-
&& let hir::ExprKind::Path(..) = expr.kind
542-
{
543-
// Special case: you can incorrectly write an equality condition:
544-
// if foo == Struct { field } { /* if body */ }
545-
// which should have been written
546-
// if foo == (Struct { field }) { /* if body */ }
547-
suggestion.push((block.span.shrink_to_hi(), ")".to_string()));
548-
} else {
549-
suggestion.push((span.shrink_to_hi().with_hi(expr.span.hi()), sugg));
481+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
482+
fn report_unexpected_variant_res(
483+
&self,
484+
res: Res,
485+
expr: Option<&hir::Expr<'_>>,
486+
sub_pats: &[hir::Pat<'_>],
487+
qpath: &hir::QPath<'_>,
488+
span: Span,
489+
err_code: ErrCode,
490+
expected: &str,
491+
) -> ErrorGuaranteed {
492+
let tcx = self.tcx;
493+
let res_descr = match res {
494+
Res::Def(DefKind::Variant, _) => "struct variant",
495+
_ => res.descr(),
496+
};
497+
let path_str = rustc_hir_pretty::qpath_to_string(self, qpath);
498+
let mut err = tcx
499+
.dcx()
500+
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
501+
.with_code(err_code);
502+
match res {
503+
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
504+
let patterns_url = "https://doc.rust-lang.org/book/ch19-00-patterns.html";
505+
err.with_span_label(span, "`fn` calls are not allowed in patterns")
506+
.with_help(format!("for more information, visit {patterns_url}"))
507+
}
508+
Res::Def(DefKind::Variant, _) if let Some(expr) = expr => {
509+
err.span_label(span, format!("not a {expected}"));
510+
let variant = tcx.expect_variant_res(res);
511+
let sugg = if variant.fields.is_empty() {
512+
" {}".to_string()
513+
} else {
514+
format!(
515+
" {{ {} }}",
516+
variant
517+
.fields
518+
.iter()
519+
.map(|f| format!("{}: /* value */", f.name))
520+
.collect::<Vec<_>>()
521+
.join(", ")
522+
)
523+
};
524+
let descr = "you might have meant to create a new value of the struct";
525+
let mut suggestion = vec![];
526+
match tcx.parent_hir_node(expr.hir_id) {
527+
hir::Node::Expr(hir::Expr {
528+
kind: hir::ExprKind::Call(..),
529+
span: call_span,
530+
..
531+
}) => {
532+
suggestion.push((span.shrink_to_hi().with_hi(call_span.hi()), sugg));
533+
}
534+
hir::Node::Expr(hir::Expr {
535+
kind: hir::ExprKind::Binary(..), hir_id, ..
536+
}) => {
537+
suggestion.push((expr.span.shrink_to_lo(), "(".to_string()));
538+
if let hir::Node::Expr(parent) = tcx.parent_hir_node(*hir_id)
539+
&& let hir::ExprKind::If(condition, block, None) = parent.kind
540+
&& condition.hir_id == *hir_id
541+
&& let hir::ExprKind::Block(block, _) = block.kind
542+
&& block.stmts.is_empty()
543+
&& let Some(expr) = block.expr
544+
&& let hir::ExprKind::Path(..) = expr.kind
545+
{
546+
// Special case: you can incorrectly write an equality condition:
547+
// if foo == Struct { field } { /* if body */ }
548+
// which should have been written
549+
// if foo == (Struct { field }) { /* if body */ }
550+
suggestion.push((block.span.shrink_to_hi(), ")".to_string()));
551+
} else {
552+
suggestion.push((span.shrink_to_hi().with_hi(expr.span.hi()), sugg));
553+
}
554+
}
555+
_ => {
556+
suggestion.push((span.shrink_to_hi(), sugg));
550557
}
551558
}
552-
_ => {
553-
suggestion.push((span.shrink_to_hi(), sugg));
554-
}
559+
560+
err.multipart_suggestion(descr, suggestion, Applicability::HasPlaceholders);
561+
err
555562
}
563+
Res::Def(DefKind::Variant, _) if expr.is_none() => {
564+
err.span_label(span, format!("not a {expected}"));
556565

557-
err.multipart_suggestion(descr, suggestion, Applicability::HasPlaceholders);
558-
err
559-
}
560-
Res::Def(DefKind::Variant, _) if expr.is_none() => {
561-
err.span_label(span, format!("not a {expected}"));
562-
563-
let fields = &tcx.expect_variant_res(res).fields.raw;
564-
let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi());
565-
let (msg, sugg) = if fields.is_empty() {
566-
("use the struct variant pattern syntax", " {}".to_string())
567-
} else {
568-
let msg = if fields.is_empty() {
569-
"use struct variant pattern syntax"
566+
let fields = &tcx.expect_variant_res(res).fields.raw;
567+
let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi());
568+
let (msg, sugg) = if fields.is_empty() {
569+
("use the struct variant pattern syntax", " {}".to_string())
570570
} else {
571-
"add the names to match a struct variant's fields"
571+
let msg = if fields.is_empty() {
572+
"use struct variant pattern syntax"
573+
} else {
574+
"add the names to match a struct variant's fields"
575+
};
576+
let fields_sugg = fields
577+
.iter()
578+
.enumerate()
579+
.map(|(i, field)| {
580+
let field_name = field.ident(tcx).to_string();
581+
582+
let pat_snippet = sub_pats
583+
.get(i)
584+
.and_then(|sub_pat| {
585+
tcx.sess.source_map().span_to_snippet(sub_pat.span).ok()
586+
})
587+
.unwrap_or_else(|| "_".to_string());
588+
589+
if field_name == pat_snippet {
590+
field_name
591+
} else {
592+
format!("{field_name}: {pat_snippet}")
593+
}
594+
})
595+
.collect::<Vec<_>>()
596+
.join(", ");
597+
let sugg = format!(" {{ {} }}", fields_sugg);
598+
(msg, sugg)
572599
};
573-
let fields_sugg = fields
574-
.iter()
575-
.enumerate()
576-
.map(|(i, field)| {
577-
let field_name = field.ident(tcx).to_string();
578-
579-
let pat_snippet = sub_pats
580-
.get(i)
581-
.and_then(|sub_pat| {
582-
tcx.sess.source_map().span_to_snippet(sub_pat.span).ok()
583-
})
584-
.unwrap_or_else(|| "_".to_string());
585-
586-
if field_name == pat_snippet {
587-
field_name
588-
} else {
589-
format!("{field_name}: {pat_snippet}")
590-
}
591-
})
592-
.collect::<Vec<_>>()
593-
.join(", ");
594-
let sugg = format!(" {{ {} }}", fields_sugg);
595-
(msg, sugg)
596-
};
597-
598-
err.span_suggestion_verbose(
599-
qpath.span().shrink_to_hi().to(span.shrink_to_hi()),
600-
msg,
601-
sugg,
602-
Applicability::HasPlaceholders,
603-
);
604-
err
600+
601+
err.span_suggestion_verbose(
602+
qpath.span().shrink_to_hi().to(span.shrink_to_hi()),
603+
msg,
604+
sugg,
605+
Applicability::HasPlaceholders,
606+
);
607+
err
608+
}
609+
_ => err.with_span_label(span, format!("not a {expected}")),
605610
}
606-
_ => err.with_span_label(span, format!("not a {expected}")),
611+
.emit()
607612
}
608-
.emit()
609613
}
610614

611615
/// Controls whether all arguments are tupled. This is used for the call operator only.

0 commit comments

Comments
 (0)