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 #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.
This commit is contained in:
parent
75530e9f72
commit
f27cab806e
20 changed files with 125 additions and 87 deletions
|
@ -1513,16 +1513,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
|
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {
|
||||||
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
|
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
|
||||||
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
|
PatKind::Ident(_, ident, _) => {
|
||||||
PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)),
|
if ident.name != kw::Empty {
|
||||||
|
Some(self.lower_ident(ident))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),
|
||||||
_ => {
|
_ => {
|
||||||
self.dcx().span_delayed_bug(
|
self.dcx().span_delayed_bug(
|
||||||
param.pat.span,
|
param.pat.span,
|
||||||
"non-ident/wild param pat must trigger an error",
|
"non-ident/wild param pat must trigger an error",
|
||||||
);
|
);
|
||||||
Ident::new(kw::Empty, self.lower_span(param.pat.span))
|
None
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2514,12 +2514,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
let ty::Tuple(params) = tupled_params.kind() else { return };
|
let ty::Tuple(params) = tupled_params.kind() else { return };
|
||||||
|
|
||||||
// Find the first argument with a matching type, get its name
|
// Find the first argument with a matching type, get its name
|
||||||
let Some((_, this_name)) =
|
let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map(
|
||||||
params.iter().zip(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| {
|
|(param_ty, name)| {
|
||||||
// FIXME: also support deref for stuff like `Rc` arguments
|
// FIXME: also support deref for stuff like `Rc` arguments
|
||||||
param_ty.peel_refs() == local_ty && name != &Ident::empty()
|
if param_ty.peel_refs() == local_ty { name } else { None }
|
||||||
})
|
},
|
||||||
else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3787,7 +3787,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
method_args,
|
method_args,
|
||||||
*fn_span,
|
*fn_span,
|
||||||
call_source.from_hir_call(),
|
call_source.from_hir_call(),
|
||||||
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
|
self.infcx.tcx.fn_arg_names(method_did)[0],
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
|
err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
|
||||||
|
|
|
@ -1029,7 +1029,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
method_args,
|
method_args,
|
||||||
*fn_span,
|
*fn_span,
|
||||||
call_source.from_hir_call(),
|
call_source.from_hir_call(),
|
||||||
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
|
self.infcx.tcx.fn_arg_names(method_did)[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
return FnSelfUse {
|
return FnSelfUse {
|
||||||
|
|
|
@ -2949,7 +2949,7 @@ impl<'hir> TraitItem<'hir> {
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum TraitFn<'hir> {
|
pub enum TraitFn<'hir> {
|
||||||
/// No default body in the trait, just a signature.
|
/// No default body in the trait, just a signature.
|
||||||
Required(&'hir [Ident]),
|
Required(&'hir [Option<Ident>]),
|
||||||
|
|
||||||
/// Both signature and body are provided in the trait.
|
/// Both signature and body are provided in the trait.
|
||||||
Provided(BodyId),
|
Provided(BodyId),
|
||||||
|
@ -3354,7 +3354,9 @@ pub struct BareFnTy<'hir> {
|
||||||
pub abi: ExternAbi,
|
pub abi: ExternAbi,
|
||||||
pub generic_params: &'hir [GenericParam<'hir>],
|
pub generic_params: &'hir [GenericParam<'hir>],
|
||||||
pub decl: &'hir FnDecl<'hir>,
|
pub decl: &'hir FnDecl<'hir>,
|
||||||
pub param_names: &'hir [Ident],
|
// `Option` because bare fn parameter names are optional. We also end up
|
||||||
|
// with `None` in some error cases, e.g. invalid parameter patterns.
|
||||||
|
pub param_names: &'hir [Option<Ident>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
|
@ -4335,7 +4337,12 @@ impl ForeignItem<'_> {
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum ForeignItemKind<'hir> {
|
pub enum ForeignItemKind<'hir> {
|
||||||
/// A foreign function.
|
/// A foreign function.
|
||||||
Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>),
|
///
|
||||||
|
/// All argument idents are actually always present (i.e. `Some`), but
|
||||||
|
/// `&[Option<Ident>]` is used because of code paths shared with `TraitFn`
|
||||||
|
/// and `BareFnTy`. The sharing is due to all of these cases not allowing
|
||||||
|
/// arbitrary patterns for parameters.
|
||||||
|
Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>),
|
||||||
/// A foreign static item (`static ext: u8`).
|
/// A foreign static item (`static ext: u8`).
|
||||||
Static(&'hir Ty<'hir>, Mutability, Safety),
|
Static(&'hir Ty<'hir>, Mutability, Safety),
|
||||||
/// A foreign type.
|
/// A foreign type.
|
||||||
|
|
|
@ -655,7 +655,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
|
||||||
ForeignItemKind::Fn(ref sig, param_names, ref generics) => {
|
ForeignItemKind::Fn(ref sig, param_names, ref generics) => {
|
||||||
try_visit!(visitor.visit_generics(generics));
|
try_visit!(visitor.visit_generics(generics));
|
||||||
try_visit!(visitor.visit_fn_decl(sig.decl));
|
try_visit!(visitor.visit_fn_decl(sig.decl));
|
||||||
walk_list!(visitor, visit_ident, param_names.iter().copied());
|
for ident in param_names.iter().copied() {
|
||||||
|
visit_opt!(visitor, visit_ident, ident);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(ref typ, _, _) => {
|
ForeignItemKind::Static(ref typ, _, _) => {
|
||||||
try_visit!(visitor.visit_ty_unambig(typ));
|
try_visit!(visitor.visit_ty_unambig(typ));
|
||||||
|
@ -1169,7 +1171,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
|
||||||
}
|
}
|
||||||
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
|
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
|
||||||
try_visit!(visitor.visit_fn_decl(sig.decl));
|
try_visit!(visitor.visit_fn_decl(sig.decl));
|
||||||
walk_list!(visitor, visit_ident, param_names.iter().copied());
|
for ident in param_names.iter().copied() {
|
||||||
|
visit_opt!(visitor, visit_ident, ident);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
|
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
|
||||||
try_visit!(visitor.visit_fn(
|
try_visit!(visitor.visit_fn(
|
||||||
|
|
|
@ -1034,7 +1034,13 @@ fn report_trait_method_mismatch<'tcx>(
|
||||||
let span = tcx
|
let span = tcx
|
||||||
.hir_body_param_names(body)
|
.hir_body_param_names(body)
|
||||||
.zip(sig.decl.inputs.iter())
|
.zip(sig.decl.inputs.iter())
|
||||||
.map(|(param, ty)| param.span.to(ty.span))
|
.map(|(param_name, ty)| {
|
||||||
|
if let Some(param_name) = param_name {
|
||||||
|
param_name.span.to(ty.span)
|
||||||
|
} else {
|
||||||
|
ty.span
|
||||||
|
}
|
||||||
|
})
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or(impl_err_span);
|
.unwrap_or(impl_err_span);
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,11 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
||||||
Ok(Err(index)) => {
|
Ok(Err(index)) => {
|
||||||
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
|
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
|
||||||
// ^^^^^^
|
// ^^^^^^
|
||||||
let span = bare_fn_ty.param_names[index]
|
let span = if let Some(ident) = bare_fn_ty.param_names[index] {
|
||||||
.span
|
ident.span.to(bare_fn_ty.decl.inputs[index].span)
|
||||||
.to(bare_fn_ty.decl.inputs[index].span)
|
} else {
|
||||||
|
bare_fn_ty.decl.inputs[index].span
|
||||||
|
}
|
||||||
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
|
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
|
||||||
let plural = bare_fn_ty.param_names.len() - index != 1;
|
let plural = bare_fn_ty.param_names.len() - index != 1;
|
||||||
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
|
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
|
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
|
||||||
|
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
#![feature(let_chains)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
||||||
|
@ -898,7 +899,7 @@ impl<'a> State<'a> {
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
m: &hir::FnSig<'_>,
|
m: &hir::FnSig<'_>,
|
||||||
generics: &hir::Generics<'_>,
|
generics: &hir::Generics<'_>,
|
||||||
arg_names: &[Ident],
|
arg_names: &[Option<Ident>],
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
) {
|
) {
|
||||||
self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
|
self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
|
||||||
|
@ -2121,7 +2122,7 @@ impl<'a> State<'a> {
|
||||||
header: hir::FnHeader,
|
header: hir::FnHeader,
|
||||||
name: Option<Symbol>,
|
name: Option<Symbol>,
|
||||||
generics: &hir::Generics<'_>,
|
generics: &hir::Generics<'_>,
|
||||||
arg_names: &[Ident],
|
arg_names: &[Option<Ident>],
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
) {
|
) {
|
||||||
self.print_fn_header_info(header);
|
self.print_fn_header_info(header);
|
||||||
|
@ -2141,7 +2142,7 @@ impl<'a> State<'a> {
|
||||||
s.print_implicit_self(&decl.implicit_self);
|
s.print_implicit_self(&decl.implicit_self);
|
||||||
} else {
|
} else {
|
||||||
if let Some(arg_name) = arg_names.get(i) {
|
if let Some(arg_name) = arg_names.get(i) {
|
||||||
if arg_name.name != kw::Empty {
|
if let Some(arg_name) = arg_name {
|
||||||
s.word(arg_name.to_string());
|
s.word(arg_name.to_string());
|
||||||
s.word(":");
|
s.word(":");
|
||||||
s.space();
|
s.space();
|
||||||
|
@ -2451,7 +2452,7 @@ impl<'a> State<'a> {
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
name: Option<Symbol>,
|
name: Option<Symbol>,
|
||||||
generic_params: &[hir::GenericParam<'_>],
|
generic_params: &[hir::GenericParam<'_>],
|
||||||
arg_names: &[Ident],
|
arg_names: &[Option<Ident>],
|
||||||
) {
|
) {
|
||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
self.print_formal_generic_params(generic_params);
|
self.print_formal_generic_params(generic_params);
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&& self.tcx.def_kind(fn_def_id).is_fn_like()
|
&& self.tcx.def_kind(fn_def_id).is_fn_like()
|
||||||
&& let self_implicit =
|
&& let self_implicit =
|
||||||
matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
|
matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
|
||||||
&& let Some(arg) =
|
&& let Some(Some(arg)) =
|
||||||
self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
|
self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
|
||||||
&& arg.name != kw::SelfLower
|
&& arg.name != kw::SelfLower
|
||||||
{
|
{
|
||||||
|
@ -2678,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
|
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
|
||||||
debug_assert_eq!(params.len(), fn_inputs.len());
|
debug_assert_eq!(params.len(), fn_inputs.len());
|
||||||
Some((
|
Some((
|
||||||
fn_inputs.zip(params.iter().map(|¶m| FnParam::Name(param))).collect(),
|
fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(),
|
||||||
generics,
|
generics,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -2709,14 +2709,20 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum FnParam<'hir> {
|
enum FnParam<'hir> {
|
||||||
Param(&'hir hir::Param<'hir>),
|
Param(&'hir hir::Param<'hir>),
|
||||||
Name(Ident),
|
Name(Option<Ident>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnParam<'_> {
|
impl FnParam<'_> {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Self::Param(param) => param.span,
|
Self::Param(param) => param.span,
|
||||||
Self::Name(ident) => ident.span,
|
Self::Name(ident) => {
|
||||||
|
if let Some(ident) = ident {
|
||||||
|
ident.span
|
||||||
|
} else {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2733,7 +2739,8 @@ impl FnParam<'_> {
|
||||||
Some(ident.name)
|
Some(ident.name)
|
||||||
}
|
}
|
||||||
FnParam::Name(ident)
|
FnParam::Name(ident)
|
||||||
if ident.name != kw::Empty && ident.name != kw::Underscore =>
|
if let Some(ident) = ident
|
||||||
|
&& ident.name != kw::Underscore =>
|
||||||
{
|
{
|
||||||
Some(ident.name)
|
Some(ident.name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3766,7 +3766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
let self_first_arg = match method {
|
let self_first_arg = match method {
|
||||||
hir::TraitFn::Required([ident, ..]) => {
|
hir::TraitFn::Required([ident, ..]) => {
|
||||||
ident.name == kw::SelfLower
|
matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
|
||||||
}
|
}
|
||||||
hir::TraitFn::Provided(body_id) => {
|
hir::TraitFn::Provided(body_id) => {
|
||||||
self.tcx.hir_body(*body_id).params.first().is_some_and(
|
self.tcx.hir_body(*body_id).params.first().is_some_and(
|
||||||
|
|
|
@ -424,10 +424,12 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
|
||||||
if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind {
|
if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind {
|
||||||
self.check_snake_case(cx, "trait method", &item.ident);
|
self.check_snake_case(cx, "trait method", &item.ident);
|
||||||
for param_name in pnames {
|
for param_name in pnames {
|
||||||
|
if let Some(param_name) = param_name {
|
||||||
self.check_snake_case(cx, "variable", param_name);
|
self.check_snake_case(cx, "variable", param_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
|
fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
|
||||||
if let PatKind::Binding(_, hid, ident, _) = p.kind {
|
if let PatKind::Binding(_, hid, ident, _) = p.kind {
|
||||||
|
|
|
@ -1318,7 +1318,7 @@ impl<'a> CrateMetadataRef<'a> {
|
||||||
.expect("argument names not encoded for a function")
|
.expect("argument names not encoded for a function")
|
||||||
.decode((self, sess))
|
.decode((self, sess))
|
||||||
.nth(0)
|
.nth(0)
|
||||||
.is_some_and(|ident| ident.name == kw::SelfLower)
|
.is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {
|
fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {
|
||||||
|
|
|
@ -443,7 +443,7 @@ define_tables! {
|
||||||
rendered_const: Table<DefIndex, LazyValue<String>>,
|
rendered_const: Table<DefIndex, LazyValue<String>>,
|
||||||
rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>,
|
rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>,
|
||||||
asyncness: Table<DefIndex, ty::Asyncness>,
|
asyncness: Table<DefIndex, ty::Asyncness>,
|
||||||
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
|
fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
|
||||||
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
|
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
|
||||||
coroutine_for_closure: Table<DefIndex, RawDefId>,
|
coroutine_for_closure: Table<DefIndex, RawDefId>,
|
||||||
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
|
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
|
||||||
|
|
|
@ -280,11 +280,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> {
|
pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> {
|
||||||
self.hir_body(id).params.iter().map(|param| match param.pat.kind {
|
self.hir_body(id).params.iter().map(|param| match param.pat.kind {
|
||||||
PatKind::Binding(_, _, ident, _) => ident,
|
PatKind::Binding(_, _, ident, _) => Some(ident),
|
||||||
PatKind::Wild => Ident::new(kw::Underscore, param.pat.span),
|
PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)),
|
||||||
_ => Ident::empty(),
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1410,7 +1410,7 @@ rustc_queries! {
|
||||||
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::Ident] {
|
query fn_arg_names(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] {
|
||||||
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
|
@ -2217,12 +2217,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
||||||
.delegation_fn_sigs
|
.delegation_fn_sigs
|
||||||
.get(&def_id)
|
.get(&def_id)
|
||||||
.is_some_and(|sig| sig.has_self),
|
.is_some_and(|sig| sig.has_self),
|
||||||
None => self
|
None => {
|
||||||
.r
|
self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| {
|
||||||
.tcx
|
matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
|
||||||
.fn_arg_names(def_id)
|
})
|
||||||
.first()
|
}
|
||||||
.is_some_and(|ident| ident.name == kw::SelfLower),
|
|
||||||
};
|
};
|
||||||
if has_self {
|
if has_self {
|
||||||
return Some(AssocSuggestion::MethodWithSelf { called });
|
return Some(AssocSuggestion::MethodWithSelf { called });
|
||||||
|
|
|
@ -1992,13 +1992,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, ident)| {
|
.map(|(i, ident)| {
|
||||||
if ident.name.is_empty()
|
if let Some(ident) = ident
|
||||||
|| ident.name == kw::Underscore
|
&& !matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. })
|
||||||
|| ident.name == kw::SelfLower
|
|
||||||
{
|
{
|
||||||
format!("arg{i}")
|
|
||||||
} else {
|
|
||||||
format!("{ident}")
|
format!("{ident}")
|
||||||
|
} else {
|
||||||
|
format!("arg{i}")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -1088,7 +1088,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib
|
||||||
|
|
||||||
enum FunctionArgs<'tcx> {
|
enum FunctionArgs<'tcx> {
|
||||||
Body(hir::BodyId),
|
Body(hir::BodyId),
|
||||||
Names(&'tcx [Ident]),
|
Names(&'tcx [Option<Ident>]),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_function<'tcx>(
|
fn clean_function<'tcx>(
|
||||||
|
@ -1117,13 +1117,15 @@ fn clean_function<'tcx>(
|
||||||
fn clean_args_from_types_and_names<'tcx>(
|
fn clean_args_from_types_and_names<'tcx>(
|
||||||
cx: &mut DocContext<'tcx>,
|
cx: &mut DocContext<'tcx>,
|
||||||
types: &[hir::Ty<'tcx>],
|
types: &[hir::Ty<'tcx>],
|
||||||
names: &[Ident],
|
names: &[Option<Ident>],
|
||||||
) -> Arguments {
|
) -> Arguments {
|
||||||
fn nonempty_name(ident: &Ident) -> Option<Symbol> {
|
fn nonempty_name(ident: &Option<Ident>) -> Option<Symbol> {
|
||||||
if ident.name == kw::Underscore || ident.name == kw::Empty {
|
if let Some(ident) = ident
|
||||||
None
|
&& ident.name != kw::Underscore
|
||||||
} else {
|
{
|
||||||
Some(ident.name)
|
Some(ident.name)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1216,11 +1218,11 @@ fn clean_poly_fn_sig<'tcx>(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| Argument {
|
.map(|t| Argument {
|
||||||
type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None),
|
type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None),
|
||||||
name: names
|
name: if let Some(Some(ident)) = names.next() {
|
||||||
.next()
|
ident.name
|
||||||
.map(|i| i.name)
|
} else {
|
||||||
.filter(|i| !i.is_empty())
|
kw::Underscore
|
||||||
.unwrap_or(kw::Underscore),
|
},
|
||||||
is_const: false,
|
is_const: false,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rustc_hir::hir_id::OwnerId;
|
||||||
use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef};
|
use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
use rustc_span::symbol::{Ident, kw};
|
||||||
|
|
||||||
use super::RENAMED_FUNCTION_PARAMS;
|
use super::RENAMED_FUNCTION_PARAMS;
|
||||||
|
|
||||||
|
@ -51,22 +51,33 @@ struct RenamedFnArgs(Vec<(Span, String)>);
|
||||||
impl RenamedFnArgs {
|
impl RenamedFnArgs {
|
||||||
/// Comparing between an iterator of default names and one with current names,
|
/// Comparing between an iterator of default names and one with current names,
|
||||||
/// then collect the ones that got renamed.
|
/// then collect the ones that got renamed.
|
||||||
fn new<I, T>(default_names: &mut I, current_names: &mut T) -> Self
|
fn new<I1, I2>(default_idents: &mut I1, current_idents: &mut I2) -> Self
|
||||||
where
|
where
|
||||||
I: Iterator<Item = Ident>,
|
I1: Iterator<Item = Option<Ident>>,
|
||||||
T: Iterator<Item = Ident>,
|
I2: Iterator<Item = Option<Ident>>,
|
||||||
{
|
{
|
||||||
let mut renamed: Vec<(Span, String)> = vec![];
|
let mut renamed: Vec<(Span, String)> = vec![];
|
||||||
|
|
||||||
debug_assert!(default_names.size_hint() == current_names.size_hint());
|
debug_assert!(default_idents.size_hint() == current_idents.size_hint());
|
||||||
while let (Some(def_name), Some(cur_name)) = (default_names.next(), current_names.next()) {
|
while let (Some(default_ident), Some(current_ident)) =
|
||||||
let current_name = cur_name.name;
|
(default_idents.next(), current_idents.next())
|
||||||
let default_name = def_name.name;
|
{
|
||||||
if is_unused_or_empty_symbol(current_name) || is_unused_or_empty_symbol(default_name) {
|
let has_name_to_check = |ident: Option<Ident>| {
|
||||||
continue;
|
if let Some(ident) = ident
|
||||||
|
&& ident.name != kw::Underscore
|
||||||
|
&& !ident.name.as_str().starts_with('_')
|
||||||
|
{
|
||||||
|
Some(ident)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
if current_name != default_name {
|
};
|
||||||
renamed.push((cur_name.span, default_name.to_string()));
|
|
||||||
|
if let Some(default_ident) = has_name_to_check(default_ident)
|
||||||
|
&& let Some(current_ident) = has_name_to_check(current_ident)
|
||||||
|
&& default_ident.name != current_ident.name
|
||||||
|
{
|
||||||
|
renamed.push((current_ident.span, default_ident.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +94,6 @@ impl RenamedFnArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_unused_or_empty_symbol(symbol: Symbol) -> bool {
|
|
||||||
// FIXME: `body_param_names` currently returning empty symbols for `wild` as well,
|
|
||||||
// so we need to check if the symbol is empty first.
|
|
||||||
// Therefore the check of whether it's equal to [`kw::Underscore`] has no use for now,
|
|
||||||
// but it would be nice to keep it here just to be future-proof.
|
|
||||||
symbol.is_empty() || symbol == kw::Underscore || symbol.as_str().starts_with('_')
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the [`trait_item_def_id`](ImplItemRef::trait_item_def_id) of a relevant impl item.
|
/// Get the [`trait_item_def_id`](ImplItemRef::trait_item_def_id) of a relevant impl item.
|
||||||
fn trait_item_def_id_of_impl(items: &[ImplItemRef], target: OwnerId) -> Option<DefId> {
|
fn trait_item_def_id_of_impl(items: &[ImplItemRef], target: OwnerId) -> Option<DefId> {
|
||||||
items.iter().find_map(|item| {
|
items.iter().find_map(|item| {
|
||||||
|
|
|
@ -189,7 +189,7 @@ fn check_fn_inner<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
sig: &'tcx FnSig<'_>,
|
sig: &'tcx FnSig<'_>,
|
||||||
body: Option<BodyId>,
|
body: Option<BodyId>,
|
||||||
trait_sig: Option<&[Ident]>,
|
trait_sig: Option<&[Option<Ident>]>,
|
||||||
generics: &'tcx Generics<'_>,
|
generics: &'tcx Generics<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
report_extra_lifetimes: bool,
|
report_extra_lifetimes: bool,
|
||||||
|
@ -264,7 +264,7 @@ fn could_use_elision<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
func: &'tcx FnDecl<'_>,
|
func: &'tcx FnDecl<'_>,
|
||||||
body: Option<BodyId>,
|
body: Option<BodyId>,
|
||||||
trait_sig: Option<&[Ident]>,
|
trait_sig: Option<&[Option<Ident>]>,
|
||||||
named_generics: &'tcx [GenericParam<'_>],
|
named_generics: &'tcx [GenericParam<'_>],
|
||||||
msrv: Msrv,
|
msrv: Msrv,
|
||||||
) -> Option<(Vec<LocalDefId>, Vec<Lifetime>)> {
|
) -> Option<(Vec<LocalDefId>, Vec<Lifetime>)> {
|
||||||
|
@ -310,7 +310,7 @@ fn could_use_elision<'tcx>(
|
||||||
let body = cx.tcx.hir_body(body_id);
|
let body = cx.tcx.hir_body(body_id);
|
||||||
|
|
||||||
let first_ident = body.params.first().and_then(|param| param.pat.simple_ident());
|
let first_ident = body.params.first().and_then(|param| param.pat.simple_ident());
|
||||||
if non_elidable_self_type(cx, func, first_ident, msrv) {
|
if non_elidable_self_type(cx, func, Some(first_ident), msrv) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,8 +384,8 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet<LocalDefI
|
||||||
}
|
}
|
||||||
|
|
||||||
// elision doesn't work for explicit self types before Rust 1.81, see rust-lang/rust#69064
|
// elision doesn't work for explicit self types before Rust 1.81, see rust-lang/rust#69064
|
||||||
fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>, msrv: Msrv) -> bool {
|
fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Option<Ident>>, msrv: Msrv) -> bool {
|
||||||
if let Some(ident) = ident
|
if let Some(Some(ident)) = ident
|
||||||
&& ident.name == kw::SelfLower
|
&& ident.name == kw::SelfLower
|
||||||
&& !func.implicit_self.has_implicit_self()
|
&& !func.implicit_self.has_implicit_self()
|
||||||
&& let Some(self_ty) = func.inputs.first()
|
&& let Some(self_ty) = func.inputs.first()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue