Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 370f8fb

Browse files
authoredMar 14, 2025
Rollup merge of #138482 - nnethercote:fix-hir-printing, r=compiler-errors
Fix HIR printing of parameters HIR pretty printing does the wrong thing for anonymous parameters, and there is no test coverage for it. This PR remedies both of those things. r? ``@lcnr``
2 parents 03cda6b + 79e4be1 commit 370f8fb

File tree

8 files changed

+115
-24
lines changed

8 files changed

+115
-24
lines changed
 

‎compiler/rustc_ast_lowering/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1516,7 +1516,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15161516
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
15171517
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
15181518
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
1519-
_ => Ident::new(kw::Empty, self.lower_span(param.pat.span)),
1519+
PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)),
1520+
_ => {
1521+
self.dcx().span_delayed_bug(
1522+
param.pat.span,
1523+
"non-ident/wild param pat must trigger an error",
1524+
);
1525+
Ident::new(kw::Empty, self.lower_span(param.pat.span))
1526+
}
15201527
}))
15211528
}
15221529

‎compiler/rustc_hir_pretty/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2148,9 +2148,11 @@ impl<'a> State<'a> {
21482148
s.print_implicit_self(&decl.implicit_self);
21492149
} else {
21502150
if let Some(arg_name) = arg_names.get(i) {
2151-
s.word(arg_name.to_string());
2152-
s.word(":");
2153-
s.space();
2151+
if arg_name.name != kw::Empty {
2152+
s.word(arg_name.to_string());
2153+
s.word(":");
2154+
s.space();
2155+
}
21542156
} else if let Some(body_id) = body_id {
21552157
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
21562158
s.word(":");

‎compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+23-17
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
1919
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
2020
use rustc_middle::{bug, span_bug};
2121
use rustc_session::Session;
22-
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
22+
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
2323
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
2424
use rustc_trait_selection::infer::InferCtxtExt;
2525
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
@@ -2679,7 +2679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26792679
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
26802680
debug_assert_eq!(params.len(), fn_inputs.len());
26812681
Some((
2682-
fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect(),
2682+
fn_inputs.zip(params.iter().map(|&param| FnParam::Name(param))).collect(),
26832683
generics,
26842684
))
26852685
}
@@ -2710,32 +2710,38 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
27102710
#[derive(Clone, Copy)]
27112711
enum FnParam<'hir> {
27122712
Param(&'hir hir::Param<'hir>),
2713-
Name(&'hir Ident),
2713+
Name(Ident),
27142714
}
2715+
27152716
impl FnParam<'_> {
27162717
fn span(&self) -> Span {
27172718
match self {
2718-
Self::Param(x) => x.span,
2719-
Self::Name(x) => x.span,
2720-
}
2721-
}
2722-
2723-
fn name(&self) -> Option<Symbol> {
2724-
match self {
2725-
Self::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => {
2726-
Some(ident.name)
2727-
}
2728-
Self::Name(x) if x.name != kw::Empty => Some(x.name),
2729-
_ => None,
2719+
Self::Param(param) => param.span,
2720+
Self::Name(ident) => ident.span,
27302721
}
27312722
}
27322723

27332724
fn display(&self, idx: usize) -> impl '_ + fmt::Display {
27342725
struct D<'a>(FnParam<'a>, usize);
27352726
impl fmt::Display for D<'_> {
27362727
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2737-
if let Some(name) = self.0.name() {
2738-
write!(f, "`{name}`")
2728+
// A "unique" param name is one that (a) exists, and (b) is guaranteed to be unique
2729+
// among the parameters, i.e. `_` does not count.
2730+
let unique_name = match self.0 {
2731+
FnParam::Param(param)
2732+
if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2733+
{
2734+
Some(ident.name)
2735+
}
2736+
FnParam::Name(ident)
2737+
if ident.name != kw::Empty && ident.name != kw::Underscore =>
2738+
{
2739+
Some(ident.name)
2740+
}
2741+
_ => None,
2742+
};
2743+
if let Some(unique_name) = unique_name {
2744+
write!(f, "`{unique_name}`")
27392745
} else {
27402746
write!(f, "parameter #{}", self.1 + 1)
27412747
}

‎compiler/rustc_middle/src/hir/map.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,9 @@ impl<'tcx> TyCtxt<'tcx> {
281281
}
282282

283283
pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> {
284-
self.hir_body(id).params.iter().map(|arg| match arg.pat.kind {
284+
self.hir_body(id).params.iter().map(|param| match param.pat.kind {
285285
PatKind::Binding(_, _, ident, _) => ident,
286+
PatKind::Wild => Ident::new(kw::Underscore, param.pat.span),
286287
_ => Ident::empty(),
287288
})
288289
}

‎compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1998,7 +1998,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19981998
.iter()
19991999
.enumerate()
20002000
.map(|(i, ident)| {
2001-
if ident.name.is_empty() || ident.name == kw::SelfLower {
2001+
if ident.name.is_empty()
2002+
|| ident.name == kw::Underscore
2003+
|| ident.name == kw::SelfLower
2004+
{
20022005
format!("arg{i}")
20032006
} else {
20042007
format!("{ident}")

‎tests/pretty/hir-fn-params.pp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#[prelude_import]
2+
use ::std::prelude::rust_2015::*;
3+
#[macro_use]
4+
extern crate std;
5+
//@ pretty-compare-only
6+
//@ pretty-mode:hir
7+
//@ pp-exact:hir-fn-params.pp
8+
9+
// This tests the pretty-printing of various kinds of function parameters.
10+
11+
//---------------------------------------------------------------------------
12+
// Normal functions and methods.
13+
14+
fn normal_fn(_: u32, a: u32) { }
15+
16+
struct S;
17+
impl S {
18+
fn method(_: u32, a: u32) { }
19+
}
20+
21+
//---------------------------------------------------------------------------
22+
// More exotic forms, which get a different pretty-printing path. In the past,
23+
// anonymous params and `_` params printed incorrectly, e.g. `fn(u32, _: u32)`
24+
// was printed as `fn(: u32, : u32)`.
25+
//
26+
// Ideally we would also test invalid patterns, e.g. `fn(1: u32, &a: u32)`,
27+
// because they had similar problems. But the pretty-printing tests currently
28+
// can't contain compile errors.
29+
30+
fn bare_fn(x: fn(u32, _: u32, a: u32)) { }
31+
32+
extern "C" {
33+
unsafe fn foreign_fn(_: u32, a: u32);
34+
}
35+
36+
trait T {
37+
fn trait_fn(u32, _: u32, a: u32);
38+
}

‎tests/pretty/hir-fn-params.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//@ pretty-compare-only
2+
//@ pretty-mode:hir
3+
//@ pp-exact:hir-fn-params.pp
4+
5+
// This tests the pretty-printing of various kinds of function parameters.
6+
7+
//---------------------------------------------------------------------------
8+
// Normal functions and methods.
9+
10+
fn normal_fn(_: u32, a: u32) {}
11+
12+
struct S;
13+
impl S {
14+
fn method(_: u32, a: u32) {}
15+
}
16+
17+
//---------------------------------------------------------------------------
18+
// More exotic forms, which get a different pretty-printing path. In the past,
19+
// anonymous params and `_` params printed incorrectly, e.g. `fn(u32, _: u32)`
20+
// was printed as `fn(: u32, : u32)`.
21+
//
22+
// Ideally we would also test invalid patterns, e.g. `fn(1: u32, &a: u32)`,
23+
// because they had similar problems. But the pretty-printing tests currently
24+
// can't contain compile errors.
25+
26+
fn bare_fn(x: fn(u32, _: u32, a: u32)) {}
27+
28+
extern "C" {
29+
fn foreign_fn(_: u32, a: u32);
30+
}
31+
32+
trait T {
33+
fn trait_fn(u32, _: u32, a: u32);
34+
}

‎tests/ui/typeck/cyclic_type_ice.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ LL | let f = |_, _| ();
2323
help: provide the argument
2424
|
2525
LL - f(f);
26-
LL + f(/* */, /* */);
26+
LL + f(/* _ */, /* _ */);
2727
|
2828

2929
error: aborting due to 2 previous errors

0 commit comments

Comments
 (0)
Failed to load comments.