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 9155769

Browse files
authoredMar 20, 2025
Rollup merge of rust-lang#138685 - nnethercote:use-Option-Ident-for-lowered-param-names, r=compiler-errors
Use `Option<Ident>` for lowered param names. Parameter patterns are lowered to an `Ident` by `lower_fn_params_to_names`, which is used when lowering bare function types, trait methods, and foreign functions. Currently, there are two exceptional cases where the lowered param can become an empty `Ident`. - If the incoming pattern is an empty `Ident`. This occurs if the parameter is anonymous, e.g. in a bare function type. - If the incoming pattern is neither an ident nor an underscore. Any such parameter will have triggered a compile error (hence the `span_delayed_bug`), but lowering still occurs. This commit replaces these empty `Ident` results with `None`, which eliminates a number of `kw::Empty` uses, and makes it impossible to fail to check for these exceptional cases. Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It actually should have been removed in rust-lang#138482, the precursor to this PR. That PR changed the lowering of wild patterns to `_` symbols instead of empty symbols, which made the mentioned underscore check load-bearing. r? ``@compiler-errors``
2 parents d752721 + f27cab8 commit 9155769

File tree

20 files changed

+125
-87
lines changed

20 files changed

+125
-87
lines changed
 

‎compiler/rustc_ast_lowering/src/lib.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1513,16 +1513,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15131513
}))
15141514
}
15151515

1516-
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
1516+
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {
15171517
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
1518-
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
1519-
PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)),
1518+
PatKind::Ident(_, ident, _) => {
1519+
if ident.name != kw::Empty {
1520+
Some(self.lower_ident(ident))
1521+
} else {
1522+
None
1523+
}
1524+
}
1525+
PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),
15201526
_ => {
15211527
self.dcx().span_delayed_bug(
15221528
param.pat.span,
15231529
"non-ident/wild param pat must trigger an error",
15241530
);
1525-
Ident::new(kw::Empty, self.lower_span(param.pat.span))
1531+
None
15261532
}
15271533
}))
15281534
}

‎compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -2514,12 +2514,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
25142514
let ty::Tuple(params) = tupled_params.kind() else { return };
25152515

25162516
// Find the first argument with a matching type, get its name
2517-
let Some((_, this_name)) =
2518-
params.iter().zip(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| {
2517+
let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map(
2518+
|(param_ty, name)| {
25192519
// FIXME: also support deref for stuff like `Rc` arguments
2520-
param_ty.peel_refs() == local_ty && name != &Ident::empty()
2521-
})
2522-
else {
2520+
if param_ty.peel_refs() == local_ty { name } else { None }
2521+
},
2522+
) else {
25232523
return;
25242524
};
25252525

@@ -3787,7 +3787,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
37873787
method_args,
37883788
*fn_span,
37893789
call_source.from_hir_call(),
3790-
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
3790+
self.infcx.tcx.fn_arg_names(method_did)[0],
37913791
)
37923792
{
37933793
err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));

‎compiler/rustc_borrowck/src/diagnostics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
10291029
method_args,
10301030
*fn_span,
10311031
call_source.from_hir_call(),
1032-
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
1032+
self.infcx.tcx.fn_arg_names(method_did)[0],
10331033
);
10341034

10351035
return FnSelfUse {

‎compiler/rustc_hir/src/hir.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -2949,7 +2949,7 @@ impl<'hir> TraitItem<'hir> {
29492949
#[derive(Debug, Clone, Copy, HashStable_Generic)]
29502950
pub enum TraitFn<'hir> {
29512951
/// No default body in the trait, just a signature.
2952-
Required(&'hir [Ident]),
2952+
Required(&'hir [Option<Ident>]),
29532953

29542954
/// Both signature and body are provided in the trait.
29552955
Provided(BodyId),
@@ -3354,7 +3354,9 @@ pub struct BareFnTy<'hir> {
33543354
pub abi: ExternAbi,
33553355
pub generic_params: &'hir [GenericParam<'hir>],
33563356
pub decl: &'hir FnDecl<'hir>,
3357-
pub param_names: &'hir [Ident],
3357+
// `Option` because bare fn parameter names are optional. We also end up
3358+
// with `None` in some error cases, e.g. invalid parameter patterns.
3359+
pub param_names: &'hir [Option<Ident>],
33583360
}
33593361

33603362
#[derive(Debug, Clone, Copy, HashStable_Generic)]
@@ -4335,7 +4337,12 @@ impl ForeignItem<'_> {
43354337
#[derive(Debug, Clone, Copy, HashStable_Generic)]
43364338
pub enum ForeignItemKind<'hir> {
43374339
/// A foreign function.
4338-
Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>),
4340+
///
4341+
/// All argument idents are actually always present (i.e. `Some`), but
4342+
/// `&[Option<Ident>]` is used because of code paths shared with `TraitFn`
4343+
/// and `BareFnTy`. The sharing is due to all of these cases not allowing
4344+
/// arbitrary patterns for parameters.
4345+
Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>),
43394346
/// A foreign static item (`static ext: u8`).
43404347
Static(&'hir Ty<'hir>, Mutability, Safety),
43414348
/// A foreign type.

‎compiler/rustc_hir/src/intravisit.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
655655
ForeignItemKind::Fn(ref sig, param_names, ref generics) => {
656656
try_visit!(visitor.visit_generics(generics));
657657
try_visit!(visitor.visit_fn_decl(sig.decl));
658-
walk_list!(visitor, visit_ident, param_names.iter().copied());
658+
for ident in param_names.iter().copied() {
659+
visit_opt!(visitor, visit_ident, ident);
660+
}
659661
}
660662
ForeignItemKind::Static(ref typ, _, _) => {
661663
try_visit!(visitor.visit_ty_unambig(typ));
@@ -1169,7 +1171,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
11691171
}
11701172
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
11711173
try_visit!(visitor.visit_fn_decl(sig.decl));
1172-
walk_list!(visitor, visit_ident, param_names.iter().copied());
1174+
for ident in param_names.iter().copied() {
1175+
visit_opt!(visitor, visit_ident, ident);
1176+
}
11731177
}
11741178
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
11751179
try_visit!(visitor.visit_fn(

‎compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,13 @@ fn report_trait_method_mismatch<'tcx>(
10341034
let span = tcx
10351035
.hir_body_param_names(body)
10361036
.zip(sig.decl.inputs.iter())
1037-
.map(|(param, ty)| param.span.to(ty.span))
1037+
.map(|(param_name, ty)| {
1038+
if let Some(param_name) = param_name {
1039+
param_name.span.to(ty.span)
1040+
} else {
1041+
ty.span
1042+
}
1043+
})
10381044
.next()
10391045
.unwrap_or(impl_err_span);
10401046

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ pub(crate) fn validate_cmse_abi<'tcx>(
4949
Ok(Err(index)) => {
5050
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
5151
// ^^^^^^
52-
let span = bare_fn_ty.param_names[index]
53-
.span
54-
.to(bare_fn_ty.decl.inputs[index].span)
55-
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
52+
let span = if let Some(ident) = bare_fn_ty.param_names[index] {
53+
ident.span.to(bare_fn_ty.decl.inputs[index].span)
54+
} else {
55+
bare_fn_ty.decl.inputs[index].span
56+
}
57+
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
5658
let plural = bare_fn_ty.param_names.len() - index != 1;
5759
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
5860
}

‎compiler/rustc_hir_pretty/src/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
33
44
// tidy-alphabetical-start
5+
#![feature(let_chains)]
56
#![recursion_limit = "256"]
67
// tidy-alphabetical-end
78

@@ -898,7 +899,7 @@ impl<'a> State<'a> {
898899
ident: Ident,
899900
m: &hir::FnSig<'_>,
900901
generics: &hir::Generics<'_>,
901-
arg_names: &[Ident],
902+
arg_names: &[Option<Ident>],
902903
body_id: Option<hir::BodyId>,
903904
) {
904905
self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
@@ -2121,7 +2122,7 @@ impl<'a> State<'a> {
21212122
header: hir::FnHeader,
21222123
name: Option<Symbol>,
21232124
generics: &hir::Generics<'_>,
2124-
arg_names: &[Ident],
2125+
arg_names: &[Option<Ident>],
21252126
body_id: Option<hir::BodyId>,
21262127
) {
21272128
self.print_fn_header_info(header);
@@ -2141,7 +2142,7 @@ impl<'a> State<'a> {
21412142
s.print_implicit_self(&decl.implicit_self);
21422143
} else {
21432144
if let Some(arg_name) = arg_names.get(i) {
2144-
if arg_name.name != kw::Empty {
2145+
if let Some(arg_name) = arg_name {
21452146
s.word(arg_name.to_string());
21462147
s.word(":");
21472148
s.space();
@@ -2451,7 +2452,7 @@ impl<'a> State<'a> {
24512452
decl: &hir::FnDecl<'_>,
24522453
name: Option<Symbol>,
24532454
generic_params: &[hir::GenericParam<'_>],
2454-
arg_names: &[Ident],
2455+
arg_names: &[Option<Ident>],
24552456
) {
24562457
self.ibox(INDENT_UNIT);
24572458
self.print_formal_generic_params(generic_params);

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

+12-5
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11351135
&& self.tcx.def_kind(fn_def_id).is_fn_like()
11361136
&& let self_implicit =
11371137
matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
1138-
&& let Some(arg) =
1138+
&& let Some(Some(arg)) =
11391139
self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
11401140
&& arg.name != kw::SelfLower
11411141
{
@@ -2678,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26782678
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
26792679
debug_assert_eq!(params.len(), fn_inputs.len());
26802680
Some((
2681-
fn_inputs.zip(params.iter().map(|&param| FnParam::Name(param))).collect(),
2681+
fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(),
26822682
generics,
26832683
))
26842684
}
@@ -2709,14 +2709,20 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
27092709
#[derive(Clone, Copy)]
27102710
enum FnParam<'hir> {
27112711
Param(&'hir hir::Param<'hir>),
2712-
Name(Ident),
2712+
Name(Option<Ident>),
27132713
}
27142714

27152715
impl FnParam<'_> {
27162716
fn span(&self) -> Span {
27172717
match self {
27182718
Self::Param(param) => param.span,
2719-
Self::Name(ident) => ident.span,
2719+
Self::Name(ident) => {
2720+
if let Some(ident) = ident {
2721+
ident.span
2722+
} else {
2723+
DUMMY_SP
2724+
}
2725+
}
27202726
}
27212727
}
27222728

@@ -2733,7 +2739,8 @@ impl FnParam<'_> {
27332739
Some(ident.name)
27342740
}
27352741
FnParam::Name(ident)
2736-
if ident.name != kw::Empty && ident.name != kw::Underscore =>
2742+
if let Some(ident) = ident
2743+
&& ident.name != kw::Underscore =>
27372744
{
27382745
Some(ident.name)
27392746
}

‎compiler/rustc_hir_typeck/src/method/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3766,7 +3766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37663766
{
37673767
let self_first_arg = match method {
37683768
hir::TraitFn::Required([ident, ..]) => {
3769-
ident.name == kw::SelfLower
3769+
matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
37703770
}
37713771
hir::TraitFn::Provided(body_id) => {
37723772
self.tcx.hir_body(*body_id).params.first().is_some_and(

‎compiler/rustc_lint/src/nonstandard_style.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,9 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
424424
if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind {
425425
self.check_snake_case(cx, "trait method", &item.ident);
426426
for param_name in pnames {
427-
self.check_snake_case(cx, "variable", param_name);
427+
if let Some(param_name) = param_name {
428+
self.check_snake_case(cx, "variable", param_name);
429+
}
428430
}
429431
}
430432
}

‎compiler/rustc_metadata/src/rmeta/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ impl<'a> CrateMetadataRef<'a> {
13181318
.expect("argument names not encoded for a function")
13191319
.decode((self, sess))
13201320
.nth(0)
1321-
.is_some_and(|ident| ident.name == kw::SelfLower)
1321+
.is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
13221322
}
13231323

13241324
fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {

‎compiler/rustc_metadata/src/rmeta/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ define_tables! {
443443
rendered_const: Table<DefIndex, LazyValue<String>>,
444444
rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>,
445445
asyncness: Table<DefIndex, ty::Asyncness>,
446-
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
446+
fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
447447
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
448448
coroutine_for_closure: Table<DefIndex, RawDefId>,
449449
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,11 @@ impl<'tcx> TyCtxt<'tcx> {
280280
})
281281
}
282282

283-
pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> {
283+
pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> {
284284
self.hir_body(id).params.iter().map(|param| match param.pat.kind {
285-
PatKind::Binding(_, _, ident, _) => ident,
286-
PatKind::Wild => Ident::new(kw::Underscore, param.pat.span),
287-
_ => Ident::empty(),
285+
PatKind::Binding(_, _, ident, _) => Some(ident),
286+
PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)),
287+
_ => None,
288288
})
289289
}
290290

‎compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1410,7 +1410,7 @@ rustc_queries! {
14101410
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
14111411
}
14121412

1413-
query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::Ident] {
1413+
query fn_arg_names(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] {
14141414
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
14151415
separate_provide_extern
14161416
}

‎compiler/rustc_resolve/src/late/diagnostics.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -2217,12 +2217,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
22172217
.delegation_fn_sigs
22182218
.get(&def_id)
22192219
.is_some_and(|sig| sig.has_self),
2220-
None => self
2221-
.r
2222-
.tcx
2223-
.fn_arg_names(def_id)
2224-
.first()
2225-
.is_some_and(|ident| ident.name == kw::SelfLower),
2220+
None => {
2221+
self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| {
2222+
matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
2223+
})
2224+
}
22262225
};
22272226
if has_self {
22282227
return Some(AssocSuggestion::MethodWithSelf { called });

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

+4-5
Original file line numberDiff line numberDiff line change
@@ -1992,13 +1992,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19921992
.iter()
19931993
.enumerate()
19941994
.map(|(i, ident)| {
1995-
if ident.name.is_empty()
1996-
|| ident.name == kw::Underscore
1997-
|| ident.name == kw::SelfLower
1995+
if let Some(ident) = ident
1996+
&& !matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. })
19981997
{
1999-
format!("arg{i}")
2000-
} else {
20011998
format!("{ident}")
1999+
} else {
2000+
format!("arg{i}")
20022001
}
20032002
})
20042003
.collect();

‎src/librustdoc/clean/mod.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib
10881088

10891089
enum FunctionArgs<'tcx> {
10901090
Body(hir::BodyId),
1091-
Names(&'tcx [Ident]),
1091+
Names(&'tcx [Option<Ident>]),
10921092
}
10931093

10941094
fn clean_function<'tcx>(
@@ -1117,13 +1117,15 @@ fn clean_function<'tcx>(
11171117
fn clean_args_from_types_and_names<'tcx>(
11181118
cx: &mut DocContext<'tcx>,
11191119
types: &[hir::Ty<'tcx>],
1120-
names: &[Ident],
1120+
names: &[Option<Ident>],
11211121
) -> Arguments {
1122-
fn nonempty_name(ident: &Ident) -> Option<Symbol> {
1123-
if ident.name == kw::Underscore || ident.name == kw::Empty {
1124-
None
1125-
} else {
1122+
fn nonempty_name(ident: &Option<Ident>) -> Option<Symbol> {
1123+
if let Some(ident) = ident
1124+
&& ident.name != kw::Underscore
1125+
{
11261126
Some(ident.name)
1127+
} else {
1128+
None
11271129
}
11281130
}
11291131

@@ -1216,11 +1218,11 @@ fn clean_poly_fn_sig<'tcx>(
12161218
.iter()
12171219
.map(|t| Argument {
12181220
type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None),
1219-
name: names
1220-
.next()
1221-
.map(|i| i.name)
1222-
.filter(|i| !i.is_empty())
1223-
.unwrap_or(kw::Underscore),
1221+
name: if let Some(Some(ident)) = names.next() {
1222+
ident.name
1223+
} else {
1224+
kw::Underscore
1225+
},
12241226
is_const: false,
12251227
})
12261228
.collect(),
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.