about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-03-14 08:40:43 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2025-03-14 09:45:38 +1100
commit958bc7b3655a0880361b11f9052fab84030cde26 (patch)
treeeed0f26438c0aee8e94d4a9e92bd5924a0fb4771 /compiler
parent9714f60f1d54450ac4d17416947d1c659429c311 (diff)
downloadrust-958bc7b3655a0880361b11f9052fab84030cde26.tar.gz
rust-958bc7b3655a0880361b11f9052fab84030cde26.zip
Handle `_` properly in a couple of places.
Currently (PatKind::Wild` (i.e. `_`) gets turned by
`lower_fn_params_to_names` into an empty identifier, which means it is
printed incorrectly by HIR pretty printing.

And likewise for `lower_fn_params_to_names`, which affects some error
messages.

This commit fixes them. This requires a slight tweak in a couple of
places to continue using parameter numbers in some error messages. And
it improves the output of `tests/ui/typeck/cyclic_type_ice.rs`:
`/* _ */` is a better suggestion than `/*  */`.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs23
-rw-r--r--compiler/rustc_middle/src/hir/map.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs5
4 files changed, 30 insertions, 10 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index c7d37e2704d..df671cf4b86 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1516,7 +1516,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
         self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
             PatKind::Ident(_, ident, _) => self.lower_ident(ident),
-            _ => Ident::new(kw::Empty, self.lower_span(param.pat.span)),
+            PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)),
+            _ => {
+                self.dcx().span_delayed_bug(
+                    param.pat.span,
+                    "non-ident/wild param pat must trigger an error",
+                );
+                Ident::new(kw::Empty, self.lower_span(param.pat.span))
+            }
         }))
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8ab6e0c4159..0a472c95221 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2712,11 +2712,12 @@ enum FnParam<'hir> {
     Param(&'hir hir::Param<'hir>),
     Name(&'hir Ident),
 }
+
 impl FnParam<'_> {
     fn span(&self) -> Span {
         match self {
-            Self::Param(x) => x.span,
-            Self::Name(x) => x.span,
+            Self::Param(param) => param.span,
+            Self::Name(ident) => ident.span,
         }
     }
 
@@ -2724,15 +2725,23 @@ impl FnParam<'_> {
         struct D<'a>(FnParam<'a>, usize);
         impl fmt::Display for D<'_> {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                let name = match self.0 {
-                    FnParam::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => {
+                // A "unique" param name is one that (a) exists, and (b) is guaranteed to be unique
+                // among the parameters, i.e. `_` does not count.
+                let unique_name = match self.0 {
+                    FnParam::Param(param)
+                        if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
+                    {
+                        Some(ident.name)
+                    }
+                    FnParam::Name(ident)
+                        if ident.name != kw::Empty && ident.name != kw::Underscore =>
+                    {
                         Some(ident.name)
                     }
-                    FnParam::Name(x) if x.name != kw::Empty => Some(x.name),
                     _ => None,
                 };
-                if let Some(name) = name {
-                    write!(f, "`{name}`")
+                if let Some(unique_name) = unique_name {
+                    write!(f, "`{unique_name}`")
                 } else {
                     write!(f, "parameter #{}", self.1 + 1)
                 }
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index c85af81ee25..5c34dd6309e 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -281,8 +281,9 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> {
-        self.hir_body(id).params.iter().map(|arg| match arg.pat.kind {
+        self.hir_body(id).params.iter().map(|param| match param.pat.kind {
             PatKind::Binding(_, _, ident, _) => ident,
+            PatKind::Wild => Ident::new(kw::Underscore, param.pat.span),
             _ => Ident::empty(),
         })
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index ad46a15a5ac..b56ed144377 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -1998,7 +1998,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 .iter()
                 .enumerate()
                 .map(|(i, ident)| {
-                    if ident.name.is_empty() || ident.name == kw::SelfLower {
+                    if ident.name.is_empty()
+                        || ident.name == kw::Underscore
+                        || ident.name == kw::SelfLower
+                    {
                         format!("arg{i}")
                     } else {
                         format!("{ident}")