From 5231f1977f254257a8adb1dabfb27f88d66332fc Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 8 Oct 2026 17:25:19 +0200 Subject: [PATCH 01/12] Move `hir::Param`s from `Body` of functions to `FnDecl`. --- .../rustc_ast_lowering/src/delegation/mod.rs | 62 +++++++++++---- compiler/rustc_ast_lowering/src/expr.rs | 19 ++--- .../rustc_ast_lowering/src/expr/closure.rs | 15 ++-- compiler/rustc_ast_lowering/src/item.rs | 63 ++++++++------- compiler/rustc_ast_lowering/src/lib.rs | 79 +++++++++++-------- compiler/rustc_ast_lowering/src/pat.rs | 4 +- .../src/diagnostics/conflict_errors.rs | 22 +++--- .../src/diagnostics/move_errors.rs | 3 +- .../src/diagnostics/mutability_errors.rs | 47 ++++++----- .../src/diagnostics/region_errors.rs | 4 +- .../src/diagnostics/region_name.rs | 7 +- compiler/rustc_hir/src/hir.rs | 16 ++-- compiler/rustc_hir/src/intravisit.rs | 15 ++-- .../src/check/compare_eii.rs | 16 ++-- .../src/check/compare_impl_item.rs | 38 ++++----- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/region.rs | 5 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 14 ++-- .../src/coherence/builtin/coerce_shared.rs | 1 + compiler/rustc_hir_analysis/src/collect.rs | 19 +++-- .../src/collect/resolve_bound_vars.rs | 31 ++++++-- .../wrong_number_of_generic_args.rs | 4 +- .../src/hir_ty_lowering/cmse.rs | 8 +- .../src/hir_ty_lowering/dyn_trait.rs | 4 +- .../src/hir_ty_lowering/mod.rs | 4 + .../rustc_hir_analysis/src/hir_wf_check.rs | 4 +- compiler/rustc_hir_pretty/src/lib.rs | 48 ++++++----- compiler/rustc_hir_typeck/src/check.rs | 16 ++-- compiler/rustc_hir_typeck/src/closure.rs | 10 +-- compiler/rustc_hir_typeck/src/demand.rs | 4 +- .../rustc_hir_typeck/src/expr_use_visitor.rs | 8 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 52 ++++++------ compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 7 +- .../src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_hir_typeck/src/lib.rs | 11 ++- .../rustc_hir_typeck/src/method/suggest.rs | 29 +++---- .../rustc_hir_typeck/src/naked_functions.rs | 13 ++- compiler/rustc_hir_typeck/src/upvar.rs | 22 +++++- compiler/rustc_hir_typeck/src/writeback.rs | 21 +++-- compiler/rustc_lint/src/gpukernel_abi.rs | 2 +- compiler/rustc_lint/src/lifetime_syntax.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 31 ++++---- .../rustc_lint/src/types/improper_ctypes.rs | 4 +- compiler/rustc_middle/src/hir/map.rs | 10 ++- compiler/rustc_middle/src/hir/mod.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 17 ++-- compiler/rustc_mir_transform/src/liveness.rs | 5 +- compiler/rustc_passes/src/check_attr.rs | 14 ++-- compiler/rustc_passes/src/check_export.rs | 2 +- compiler/rustc_passes/src/dead.rs | 14 +++- compiler/rustc_passes/src/input_stats.rs | 1 + compiler/rustc_passes/src/upvars.rs | 3 + compiler/rustc_privacy/src/lib.rs | 13 ++- .../error_reporting/infer/need_type_info.rs | 10 +-- .../infer/nice_region_error/find_anon_type.rs | 2 +- .../nice_region_error/placeholder_error.rs | 6 +- .../infer/nice_region_error/util.rs | 13 ++- .../src/error_reporting/infer/suggest.rs | 26 +++--- .../traits/fulfillment_errors.rs | 19 ++--- .../src/error_reporting/traits/mod.rs | 5 +- .../src/error_reporting/traits/suggestions.rs | 41 +++++----- .../src/traits/dyn_compatibility.rs | 17 ++-- compiler/rustc_ty_utils/src/implied_bounds.rs | 6 +- compiler/rustc_ty_walk/src/lib.rs | 2 +- src/librustdoc/clean/mod.rs | 39 ++++----- src/tools/clippy/clippy_lints/src/booleans.rs | 7 +- .../src/collection_is_never_read.rs | 3 +- .../clippy/clippy_lints/src/dereference.rs | 1 + src/tools/clippy/clippy_lints/src/escape.rs | 8 +- .../clippy/clippy_lints/src/eta_reduction.rs | 12 +-- .../clippy_lints/src/excessive_bools.rs | 2 +- .../clippy/clippy_lints/src/format_impl.rs | 8 +- .../clippy/clippy_lints/src/from_over_into.rs | 4 +- .../clippy_lints/src/functions/must_use.rs | 6 +- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- .../clippy_lints/src/functions/ref_option.rs | 4 +- .../src/functions/renamed_function_params.rs | 4 +- .../clippy_lints/src/implicit_hasher.rs | 6 +- .../clippy/clippy_lints/src/lifetimes.rs | 13 ++- .../src/loops/unused_enumerate_index.rs | 13 ++- .../clippy_lints/src/manual_is_ascii_check.rs | 4 +- .../clippy/clippy_lints/src/manual_pop_if.rs | 6 +- .../clippy/clippy_lints/src/manual_retain.rs | 6 +- .../clippy/clippy_lints/src/map_unit_fn.rs | 10 +-- .../clippy_lints/src/matches/manual_filter.rs | 2 +- .../src/matches/match_single_binding.rs | 2 +- .../clippy_lints/src/methods/bytecount.rs | 4 +- .../clippy_lints/src/methods/filter_map.rs | 14 ++-- .../src/methods/filter_map_bool_then.rs | 9 +-- .../clippy_lints/src/methods/iter_filter.rs | 4 +- .../clippy_lints/src/methods/iter_kv_map.rs | 2 +- .../src/methods/iter_overeager_cloned.rs | 7 +- .../src/methods/lines_filter_map_ok.rs | 11 ++- .../src/methods/manual_contains.rs | 6 +- .../src/methods/manual_inspect.rs | 4 +- .../clippy_lints/src/methods/manual_ok_or.rs | 2 +- .../src/methods/manual_option_zip.rs | 10 ++- .../clippy_lints/src/methods/map_clone.rs | 4 +- .../src/methods/map_err_ignore.rs | 6 +- .../map_with_unused_argument_over_ranges.rs | 9 +-- .../clippy/clippy_lints/src/methods/mod.rs | 10 +-- .../methods/needless_character_iteration.rs | 5 +- .../src/methods/option_as_ref_deref.rs | 6 +- .../clippy_lints/src/methods/or_fun_call.rs | 4 +- .../src/methods/range_zip_with_len.rs | 3 +- .../src/methods/return_and_then.rs | 2 +- .../src/methods/search_is_some.rs | 5 +- .../clippy_lints/src/methods/some_filter.rs | 6 +- .../src/methods/unnecessary_filter_map.rs | 8 +- .../src/methods/unnecessary_fold.rs | 8 +- .../src/methods/unnecessary_lazy_eval.rs | 6 +- .../src/methods/unnecessary_map_or.rs | 6 +- .../src/methods/unnecessary_sort_by.rs | 4 +- .../methods/unnecessary_unwrap_unchecked.rs | 10 +-- .../clippy_lints/src/methods/useless_asref.rs | 7 +- .../clippy_lints/src/min_ident_chars.rs | 13 +-- src/tools/clippy/clippy_lints/src/mut_key.rs | 4 +- .../clippy_lints/src/needless_for_each.rs | 4 +- .../src/needless_pass_by_ref_mut.rs | 34 ++++---- .../src/needless_pass_by_value.rs | 31 ++++---- .../clippy_lints/src/non_canonical_impls.rs | 18 ++--- .../src/only_used_in_recursion.rs | 12 +-- .../clippy_lints/src/pass_by_ref_or_value.rs | 17 ++-- .../clippy_lints/src/pattern_type_mismatch.rs | 6 +- .../clippy_lints/src/ptr/mut_from_ref.rs | 2 +- .../clippy/clippy_lints/src/ptr/ptr_arg.rs | 26 +++--- .../src/redundant_closure_call.rs | 7 +- .../clippy/clippy_lints/src/replace_box.rs | 5 +- src/tools/clippy/clippy_lints/src/shadow.rs | 14 +++- .../clippy_lints/src/single_option_map.rs | 2 +- .../clippy_lints/src/string_patterns.rs | 2 +- .../clippy_lints/src/toplevel_ref_arg.rs | 6 +- .../clippy/clippy_lints/src/types/mod.rs | 4 +- .../clippy/clippy_lints/src/unused_self.rs | 6 +- src/tools/clippy/clippy_lints/src/use_self.rs | 2 +- .../clippy_utils/src/check_proc_macro.rs | 4 +- .../clippy/clippy_utils/src/hir_utils.rs | 5 +- src/tools/clippy/clippy_utils/src/lib.rs | 14 ++-- src/tools/clippy/clippy_utils/src/sugg.rs | 6 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 2 +- .../clippy_utils/src/ty/type_certainty/mod.rs | 8 +- src/tools/clippy/clippy_utils/src/usage.rs | 8 +- .../min_ident_chars.stderr | 8 +- .../clippy/tests/ui/min_ident_chars.stderr | 16 ++-- tests/ui/stats/input-stats.stderr | 12 +-- tests/ui/thir-print/c-variadic.stdout | 2 +- 146 files changed, 911 insertions(+), 753 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs index b2c0e1ffa81b1..c90e57ce7142e 100644 --- a/compiler/rustc_ast_lowering/src/delegation/mod.rs +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -51,7 +51,7 @@ use rustc_hir::{self as hir, FnDeclFlags, QPath}; use rustc_middle::ty::Asyncness; use rustc_span::def_id::DefId; use rustc_span::symbol::kw; -use rustc_span::{Ident, Span, Symbol, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym}; use crate::delegation::generics::{GenericsGenerationResults, GenericsPosition}; use crate::delegation::resolution::resolver::DelegationResolver; @@ -82,10 +82,11 @@ impl<'hir> LoweringContext<'_, 'hir> { self.add_attrs_if_needed(&res); - let (body_id, call_expr_id, unused_target_expr) = + let (body_id, params, call_expr_id, unused_target_expr) = self.lower_delegation_body(delegation, &res, &mut generics); - let decl = self.lower_delegation_decl(&res, &generics, call_expr_id, unused_target_expr); + let decl = + self.lower_delegation_decl(&res, params, &generics, call_expr_id, unused_target_expr); let sig = self.lower_delegation_sig(res.sig_id, decl, span); @@ -105,6 +106,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_decl( &mut self, res: &DelegationResolution, + params: &'hir [hir::Param<'hir>], generics: &GenericsGenerationResults<'hir>, call_expr_id: HirId, unused_target_expr: bool, @@ -115,14 +117,23 @@ impl<'hir> LoweringContext<'_, 'hir> { // The last parameter in C variadic functions is skipped in the signature, // like during regular lowering. let decl_param_count = param_count - c_variadic as usize; - let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty { - hir_id: self.next_id(), - kind: hir::TyKind::InferDelegation(hir::InferDelegation::Sig( - sig_id, - hir::InferDelegationSig::Input(arg), - )), - span, - })); + let inputs = + self.arena.alloc_from_iter((0..decl_param_count).zip(params).map(|(arg, param)| { + hir::Param { + hir_id: param.hir_id, + pat: param.pat, + ty: self.arena.alloc(hir::Ty { + hir_id: self.next_id(), + kind: hir::TyKind::InferDelegation(hir::InferDelegation::Sig( + sig_id, + hir::InferDelegationSig::Input(arg), + )), + span, + }), + ty_span: param.ty_span, + param_span: param.param_span, + } + })); let output = self.arena.alloc(hir::Ty { hir_id: self.next_id(), @@ -162,6 +173,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .set_c_variadic(c_variadic) .set_splatted(splatted, inputs.len()) .unwrap(), + fn_has_body: true, }) } @@ -213,7 +225,22 @@ impl<'hir> LoweringContext<'_, 'hir> { default_binding_modes: false, }); - (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id) + let hir_id = self.next_id(); + ( + hir::Param { + hir_id, + pat, + ty_span: span, + param_span: span, + ty: self.arena.alloc(hir::Ty { + #[allow(deprecated)] + kind: hir::TyKind::Err(ErrorGuaranteed::unchecked_error_guaranteed()), + span: self.lower_span(span), + hir_id, + }), + }, + pat_node_id, + ) } fn generate_arg( @@ -248,14 +275,15 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation: &Delegation, res: &DelegationResolution, generics: &mut GenericsGenerationResults<'hir>, - ) -> (hir::BodyId, HirId, bool) { + ) -> (hir::BodyId, &'hir [hir::Param<'hir>], HirId, bool) { let block = delegation.body.as_deref(); let mut call_expr_id = HirId::INVALID; let mut unused_target_expr = false; - let block_id = self.lower_body(|this| { + let (params, block_id) = self.lower_body(|this| { let &DelegationResolution { param_info, span, is_method, .. } = res; - let ParamInfo { param_count, .. } = param_info; + let ParamInfo { param_count, c_variadic, .. } = param_info; + let param_count = param_count - c_variadic as usize; let arguments_to_map = &res.sig_mapping.arguments_to_map; let mut parameters: Vec> = Vec::with_capacity(param_count); @@ -315,7 +343,7 @@ impl<'hir> LoweringContext<'_, 'hir> { debug_assert_ne!(call_expr_id, HirId::INVALID); - (block_id, call_expr_id, unused_target_expr) + (block_id, params, call_expr_id, unused_target_expr) } fn lower_block_maybe_more_than_once( @@ -571,7 +599,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.lower_ident(delegation.ident); - let body_id = self.lower_body(|this| { + let (_params, body_id) = self.lower_body(|this| { let path = this.lower_qpath( delegation.id, &delegation.qself, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f4bfec24e3b1b..f2933559d6ca2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -872,7 +872,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // The `async` desugaring takes a resume argument and maintains a `task_context`, // whereas a generator does not. - let (inputs, params, task_context): (&[_], &[_], _) = match desugaring_kind { + let (inputs, task_context): (&[_], _) = match desugaring_kind { hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen => { // Resume argument type: `ResumeTy` let unstable_span = self.mark_span_with_reason( @@ -881,12 +881,11 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(Arc::clone(self.allow_gen_future())), ); let resume_ty = self.make_lang_item_qpath(LangItem::ResumeTy, unstable_span, None); - let input_ty = hir::Ty { + let input_ty = self.arena.alloc(hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Path(resume_ty), span: unstable_span, - }; - let inputs = arena_vec![self; input_ty]; + }); // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. let (pat, task_context_hid) = self.pat_ident_binding_mode( @@ -897,14 +896,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let param = hir::Param { hir_id: self.next_id(), pat, + ty: input_ty, ty_span: self.lower_span(span), - span: self.lower_span(span), + param_span: self.lower_span(span), }; let params = arena_vec![self; param]; - (inputs, params, Some(task_context_hid)) + (params, Some(task_context_hid)) } - hir::CoroutineDesugaring::Gen => (&[], &[], None), + hir::CoroutineDesugaring::Gen => (&[], None), }; let output = @@ -914,9 +914,10 @@ impl<'hir> LoweringContext<'_, 'hir> { inputs, output, fn_decl_kind: hir::FnDeclFlags::default(), + fn_has_body: true, }); - let body = self.lower_body(move |this| { + let (_, body) = self.lower_body(move |this| { this.coroutine_kind = Some(coroutine_kind); let old_ctx = this.task_context; @@ -926,7 +927,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = body(this); this.task_context = old_ctx; - (params, res) + (inputs, res) }); let explicit_captures: &'hir [hir::ExplicitCapture] = match coroutine_source { diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index 5924d53dd11e4..37ec9d0f129e8 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -133,7 +133,6 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, capture_clause, closure_id, - expr_hir_id, constness, movability, decl, @@ -160,7 +159,6 @@ impl<'hir> LoweringContext<'_, 'hir> { binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, - closure_hir_id: HirId, constness: Const, movability: Movability, decl: &FnDecl, @@ -171,7 +169,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let ((body_id, closure_kind), move_expr_state) = + let (((params, body_id), closure_kind), move_expr_state) = self.with_new_scopes(fn_decl_span, move |this| { let mut coroutine_kind = find_attr!( attrs, @@ -210,10 +208,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_decl = self.lower_fn_decl( decl, closure_id, - closure_hir_id, FnDeclKind::Closure, None, DiscardParams::No, + params, ); let c = self.arena.alloc(hir::Closure { @@ -310,15 +308,12 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let body = self.with_new_scopes(fn_decl_span, |this| { - let inner_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - + let (parameters, body) = self.with_new_scopes(fn_decl_span, |this| { // Transform `async |x: u8| -> X { ... }` into // `|x: u8| || -> X { ... }`. let body_id = this.lower_body(|this| { let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( - &inner_decl, + &decl, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), fn_decl_span, body.span, @@ -340,10 +335,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_decl = self.lower_fn_decl( &decl, closure_id, - closure_hir_id, FnDeclKind::Closure, None, DiscardParams::No, + parameters, ); if let Const::Yes(span) = constness { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9cea3519cf94e..985b4d7d53b52 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -247,7 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: hir::ExprKind::Block(self.lower_block(block, false), None), span: self.lower_span(*span), }; - self.record_body(&[], body) + self.record_body(body) }), ), ItemKind::Fn(Fn { @@ -265,7 +265,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // only cares about the input argument patterns in the function // declaration (decl), not the return types. let coroutine_marker = header.coroutine_marker; - let body_id = this.lower_maybe_coroutine_body( + let (params, body_id) = this.lower_maybe_coroutine_body( *fn_sig_span, span, hir_id, @@ -281,10 +281,10 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_fn_decl( decl, id, - hir_id, FnDeclKind::Fn, coroutine_marker, if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, + params, ) }); let sig = hir::FnSig { @@ -320,7 +320,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ItemKind::GlobalAsm(asm) => { let asm = self.lower_inline_asm(span, asm); - let fake_body = + let (_, fake_body) = self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); hir::ItemKind::GlobalAsm { asm, fake_body } } @@ -621,16 +621,18 @@ impl<'hir> LoweringContext<'_, 'hir> { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| { + let params = + this.arena.alloc_from_iter(fdec.inputs.iter().map(|x| this.lower_param(x))); ( // Disallow `impl Trait` in foreign items. // Parameters are discarded because foreign functions don't have a body this.lower_fn_decl( fdec, i.id, - hir_id, FnDeclKind::ExternFn, None, DiscardParams::Yes, + params, ), this.lower_fn_params_to_idents(fdec), ) @@ -849,16 +851,18 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. let idents = self.lower_fn_params_to_idents(&sig.decl); + let params = + self.arena.alloc_from_iter(sig.decl.inputs.iter().map(|x| self.lower_param(x))); let (generics, sig) = self.lower_method_sig( generics, sig, i.id, - hir_id, FnDeclKind::Trait, sig.header.coroutine_marker, attrs, // Parameters are discarded for functions without a body DiscardParams::Yes, + params, ); if define_opaque.is_some() { self.dcx().span_err( @@ -882,7 +886,7 @@ impl<'hir> LoweringContext<'_, 'hir> { define_opaque, .. }) => { - let body_id = self.lower_maybe_coroutine_body( + let (params, body_id) = self.lower_maybe_coroutine_body( sig.span, i.span, hir_id, @@ -896,11 +900,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, - hir_id, FnDeclKind::Trait, sig.header.coroutine_marker, attrs, DiscardParams::No, + params, ); self.lower_define_opaque(hir_id, &define_opaque); ( @@ -1094,7 +1098,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(Fn { sig, ident, generics, body, contract, define_opaque, .. }) => { - let body_id = self.lower_maybe_coroutine_body( + let (params, body_id) = self.lower_maybe_coroutine_body( sig.span, i.span, hir_id, @@ -1108,11 +1112,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, - hir_id, if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_marker, attrs, if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, + params, ); self.lower_define_opaque(hir_id, &define_opaque); @@ -1211,12 +1215,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn record_body( - &mut self, - params: &'hir [hir::Param<'hir>], - value: hir::Expr<'hir>, - ) -> hir::BodyId { - let body = hir::Body { params, value: self.arena.alloc(value) }; + fn record_body(&mut self, value: hir::Expr<'hir>) -> hir::BodyId { + let body = hir::Body { value: self.arena.alloc(value) }; let id = body.id(); assert_eq!(id.hir_id.owner, self.curr_owner.owner_id()); self.curr_owner.bodies.push((id.hir_id.local_id, self.arena.alloc(body))); @@ -1226,24 +1226,31 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_body( &mut self, f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>), - ) -> hir::BodyId { + ) -> (&'hir [hir::Param<'hir>], hir::BodyId) { let prev_coroutine_kind = self.coroutine_kind.take(); let task_context = self.task_context.take(); let (parameters, result) = f(self); - let body_id = self.record_body(parameters, result); + let body_id = self.record_body(result); self.task_context = task_context; self.coroutine_kind = prev_coroutine_kind; - body_id + (parameters, body_id) } - fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { + pub(super) fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { let hir_id = self.lower_node_id(param.id); self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param); hir::Param { hir_id, pat: self.lower_pat(¶m.pat), + // Placeholder value that will be overwritten in `lower_fn_decl` + ty: self.arena.alloc(hir::Ty { + #[allow(deprecated)] + kind: hir::TyKind::Err(ErrorGuaranteed::unchecked_error_guaranteed()), + span: self.lower_span(param.ty.span), + hir_id, + }), ty_span: self.lower_span(param.ty.span), - span: self.lower_span(param.span), + param_span: self.lower_span(param.span), } } @@ -1252,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: &FnDecl, contract: Option<&FnContract>, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, - ) -> hir::BodyId { + ) -> (&'hir [hir::Param<'hir>], hir::BodyId) { self.lower_body(|this| { let params = this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x))); @@ -1271,7 +1278,7 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: &FnDecl, body: &Block, contract: Option<&FnContract>, - ) -> hir::BodyId { + ) -> (&'hir [hir::Param<'hir>], hir::BodyId) { self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body)) } @@ -1285,6 +1292,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ) }) + .1 } /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or @@ -1299,7 +1307,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body: Option<&Block>, attrs: &'hir [rustc_attr_ir::Attribute], contract: Option<&FnContract>, - ) -> hir::BodyId { + ) -> (&'hir [hir::Param<'hir>], hir::BodyId) { let Some(body) = body else { // Functions without a body are an error, except if this is an intrinsic. For those we // create a fake body so that the entire rest of the compiler doesn't have to deal with @@ -1432,8 +1440,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let new_parameter = hir::Param { hir_id: parameter.hir_id, pat: new_parameter_pat, + ty: parameter.ty, ty_span: self.lower_span(parameter.ty_span), - span: self.lower_span(parameter.span), + param_span: self.lower_span(parameter.param_span), }; if is_simple_parameter { @@ -1556,16 +1565,16 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &Generics, sig: &FnSig, node_id: NodeId, - hir_id: HirId, kind: FnDeclKind, coroutine_marker: Option, attrs: &[rustc_attr_ir::Attribute], discard_params: DiscardParams, + inputs: &'hir [hir::Param<'hir>], ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker, discard_params) + this.lower_fn_decl(&sig.decl, node_id, kind, coroutine_marker, discard_params, inputs) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a99db03007b51..2d6f38305ebb7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1558,6 +1558,8 @@ impl<'hir> LoweringContext<'_, 'hir> { TyKind::FnPtr(f) => { let hir_id = self.lower_node_id(t.id); let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); + let params = + self.arena.alloc_from_iter(f.decl.inputs.iter().map(|x| self.lower_param(x))); let kind = hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy { generic_params, safety: self.lower_safety(f.safety, hir::Safety::Safe), @@ -1565,10 +1567,10 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: self.lower_fn_decl( &f.decl, t.id, - hir_id, FnDeclKind::Pointer, None, DiscardParams::Yes, + params, ), param_idents: self.lower_fn_params_to_idents(&f.decl), })); @@ -1732,13 +1734,7 @@ impl<'hir> LoweringContext<'_, 'hir> { TyKind::MacCall(_) => { span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now") } - TyKind::CVarArgs => { - let guar = self.dcx().span_delayed_bug( - t.span, - "`TyKind::CVarArgs` should have been handled elsewhere", - ); - hir::TyKind::Err(guar) - } + TyKind::CVarArgs => hir::TyKind::CVarArgs, TyKind::View(ty, fields) => { let ty = self.lower_ty_alloc(ty, itctx); let fields = self.arena.alloc_slice(fields); @@ -1934,10 +1930,10 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, decl: &FnDecl, fn_node_id: NodeId, - fn_hir_id: HirId, kind: FnDeclKind, coro: Option, discard_params: DiscardParams, + hir_inputs: &'hir [hir::Param<'hir>], ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); let mut splatted = decl.splatted(); @@ -1945,35 +1941,47 @@ impl<'hir> LoweringContext<'_, 'hir> { // Skip the `...` (`CVarArgs`) trailing arguments from the AST, // as they are not explicit in HIR/Ty function signatures. // (instead, the `c_variadic` flag is set to `true`) - let mut inputs = &decl.inputs[..]; + let inputs = &decl.inputs[..]; if decl.c_variadic() { // Splat + variadic errors in AST validation, so just ignore one of them here. splatted = None; - inputs = &inputs[..inputs.len() - 1]; + // inputs = &inputs[..inputs.len() - 1]; } - let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { - if let DiscardParams::Yes = discard_params { - // FIXME This uses `fn_hir_id`, which is not correct, it should use the parameter hir id instead - // The parameter is currently not lowered for functions without bodies, so there is no place to store the lowered hir id - // This should be fixed by storing function parameters in the `hir::FnSig` instead of `hir::Body` - self.lower_attrs(fn_hir_id, ¶m.attrs, param.span, Target::Param); - } - let itctx = match kind { - FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => { - ImplTraitContext::Universal - } - FnDeclKind::ExternFn => { - ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam) - } - FnDeclKind::Closure => { - ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam) + + let inputs = self.arena.alloc_from_iter(inputs.iter().zip(hir_inputs).enumerate().map( + |(i, (param, hir_param))| { + let itctx = match kind { + FnDeclKind::Fn + | FnDeclKind::Inherent + | FnDeclKind::Impl + | FnDeclKind::Trait => ImplTraitContext::Universal, + FnDeclKind::ExternFn => { + ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam) + } + FnDeclKind::Closure => { + ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam) + } + FnDeclKind::Pointer => { + ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam) + } + }; + + let mut ty = self.lower_ty(¶m.ty, itctx); + if matches!(ty.kind, hir::TyKind::CVarArgs) && i != inputs.len() - 1 { + ty.kind = hir::TyKind::Err( + self.dcx().span_delayed_bug(param.span, "CVarArgs not in final position"), + ); } - FnDeclKind::Pointer => { - ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam) + + hir::Param { + hir_id: hir_param.hir_id, + pat: hir_param.pat, + ty: self.arena.alloc(ty), + ty_span: hir_param.ty_span, + param_span: hir_param.param_span, } - }; - self.lower_ty(¶m.ty, itctx) - })); + }, + )); let output = match coro { Some(coro) => { @@ -2049,7 +2057,12 @@ impl<'hir> LoweringContext<'_, 'hir> { .set_splatted(splatted, inputs.len()) .unwrap(); - self.arena.alloc(hir::FnDecl { inputs, output, fn_decl_kind }) + self.arena.alloc(hir::FnDecl { + inputs, + output, + fn_decl_kind, + fn_has_body: matches!(discard_params, DiscardParams::No), + }) } // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }` diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index df3d7b1a3c0a6..eb13e8b4e084b 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -488,7 +488,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let anon_const = self.with_new_scopes(span, |this| { let def_id = this.local_def_id(e.id); let hir_id = this.lower_node_id(e.id); - let body = this.lower_body(|this| { + let (_, body) = this.lower_body(|this| { // Need to use a custom function as we can't just subtract `1` from a `char`. let kind = hir::ExprKind::Path(this.make_lang_item_qpath( LangItem::RangeSub, @@ -550,7 +550,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(hir::AnonConst { def_id, hir_id, - body: this.lower_body(|_this| (&[], path_expr)), + body: this.lower_body(|_this| (&[], path_expr)).1, span, }) }); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2f8ff159ceb0a..cd42a2a181da7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -512,13 +512,13 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { && let node = self.infcx.tcx.hir_node_by_def_id(local_def_id) && let Some(fn_decl) = node.fn_decl() && let Some(ident) = node.ident() - && let Some(arg) = fn_decl.inputs.get(pos + offset) + && let Some(param) = fn_decl.inputs.get(pos + offset) { // If we can't suggest borrowing in the call, but the function definition // is local, instead offer changing the function to borrow that argument. - let mut span: MultiSpan = arg.span.into(); + let mut span: MultiSpan = param.ty.span.into(); span.push_span_label( - arg.span, + param.ty.span, "this parameter takes ownership of the value".to_string(), ); let descr = match node.fn_kind() { @@ -2774,12 +2774,14 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let ty::Tuple(params) = tupled_params.kind() else { return }; // Find the first argument with a matching type and get its identifier. - let Some(this_name) = params.iter().zip(tcx.hir_body_param_idents(closure.body)).find_map( - |(param_ty, ident)| { + let Some(this_name) = params + .iter() + .zip(tcx.hir_body_param_idents(closure.fn_decl)) + .find_map(|(param_ty, ident)| { // FIXME: also support deref for stuff like `Rc` arguments if param_ty.peel_refs() == local_ty { ident } else { None } - }, - ) else { + }) + else { return; }; @@ -4599,7 +4601,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { // Need to use the `rustc_middle::ty` types to compare against the // `return_region`. Then use the `rustc_hir` type to get only // the lifetime span. - match &fn_decl.inputs[index].kind { + match &fn_decl.inputs[index].ty.kind { hir::TyKind::Ref(lifetime, ..) => { // With access to the lifetime, we can get // the span of it. @@ -4652,7 +4654,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { // This is case 2 from above but only for closures, return type is anonymous // reference so we select // the first argument. - let argument_span = fn_decl.inputs.first()?.span; + let argument_span = fn_decl.inputs.first()?.ty.span; let argument_ty = sig.inputs().skip_binder().first()?; // Closure arguments are wrapped in a tuple, so we need to get the first @@ -4672,7 +4674,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { ty::Ref(_, _, _) => { // This is also case 2 from above but for functions, return type is still an // anonymous reference so we select the first argument. - let argument_span = fn_decl.inputs.first()?.span; + let argument_span = fn_decl.inputs.first()?.ty.span; let argument_ty = *sig.inputs().skip_binder().first()?; let return_span = fn_decl.output.span(); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 4d65410455118..6db001e8334f5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,7 +1,7 @@ use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag}; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{HirTyCtxt, Visitor}; use rustc_hir::{self as hir, CaptureBy, ExprKind, HirId, Node}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -1188,6 +1188,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { cannot_remove: FxHashSet::default(), desugar_binding_spans: Vec::new(), }; + finder.visit_fn_decl(tcx.hir_fn_decl(self.mir_hir_id())); finder.visit_body(body); let mut suggestions = Vec::new(); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 1182cdb5c2c6e..51fb5414bf6e0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -7,7 +7,7 @@ use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, BindingMode, ByRef, Expr, Node}; +use rustc_hir::{self as hir, BindingMode, ByRef, Expr, Node, intravisit}; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::visit::PlaceContext; use rustc_middle::mir::{ @@ -926,11 +926,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let f_in_trait = f_in_trait.as_local()?; if let Node::TraitItem(ti) = self.infcx.tcx.hir_node_by_def_id(f_in_trait) && let hir::TraitItemKind::Fn(sig, _) = ti.kind - && let Some(ty) = sig.decl.inputs.get(local.index() - 1) - && let hir::TyKind::Ref(_, _, hir::Mutability::Not) = ty.kind + && let Some(param) = sig.decl.inputs.get(local.index() - 1) + && let hir::TyKind::Ref(_, _, hir::Mutability::Not) = param.ty.kind && sig.decl.implicit_self().has_implicit_self() { - Some(ty.span) + Some(param.ty.span) } else { None } @@ -965,7 +965,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let def_id = self.body.source.def_id(); if let Some(local_def_id) = def_id.as_local() && let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id) - && let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value() + && let Some(hir_id) = (BindingFinder { tcx: self.infcx.tcx, span: pat_span }) + .visit_body(&body) + .break_value() && let node = self.infcx.tcx.hir_node(hir_id) && let hir::Node::LetStmt(hir::LetStmt { pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. }, @@ -1309,7 +1311,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { arg_pos + if sig.decl.implicit_self().has_implicit_self() { 1 } else { 0 }, ) - .map(|arg| arg.span) + .map(|param| param.ty.span) .unwrap_or(ident.span), ), _ => None, @@ -1614,7 +1616,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let hir_id = if let Some(local_def_id) = def_id.as_local() && let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id) { - BindingFinder { span: sugg_span }.visit_body(&body).break_value() + BindingFinder { tcx: self.infcx.tcx, span: sugg_span }.visit_body(&body).break_value() } else { None }; @@ -1789,21 +1791,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } } -struct BindingFinder { +struct BindingFinder<'tcx> { + tcx: TyCtxt<'tcx>, span: Span, } -impl<'tcx> Visitor<'tcx> for BindingFinder { +impl<'tcx> Visitor<'tcx> for BindingFinder<'tcx> { type Result = ControlFlow; - fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result { - if let hir::StmtKind::Let(local) = s.kind - && local.pat.span == self.span - { - ControlFlow::Break(local.hir_id) - } else { - hir::intravisit::walk_stmt(self, s) - } - } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result { if let hir::Pat { kind: hir::PatKind::Ref(_, _, _), span, .. } = param.pat @@ -1814,6 +1808,23 @@ impl<'tcx> Visitor<'tcx> for BindingFinder { ControlFlow::Continue(()) } } + + fn visit_body(&mut self, b: &rustc_hir::Body<'tcx>) -> Self::Result { + if let Some(decl) = self.tcx.hir_fn_decl_by_hir_id(self.tcx.hir_body_owner(b.id())) { + intravisit::walk_fn_decl(self, decl)?; + } + hir::intravisit::walk_body(self, b) + } + + fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result { + if let hir::StmtKind::Let(local) = s.kind + && local.pat.span == self.span + { + ControlFlow::Break(local.hir_id) + } else { + hir::intravisit::walk_stmt(self, s) + } + } } fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option) -> bool { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index c101191102979..c0528e35f2808 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -483,10 +483,10 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { if let Some(def_id) = def_id.as_local() && let owner = tcx.expect_hir_owner_node(def_id) && let Some(decl) = owner.fn_decl() - && let Some(ty) = decl.inputs.get(0) + && let Some(param) = decl.inputs.get(0) { // Point at the `&'static self` receiver. - bounds.push(ty.span); + bounds.push(param.ty.span); } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { // The method is not defined on the local crate, point at the signature instead of // just the receiver as an approximation. We don't add it if there are already diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 871b974d28eea..978ae12a87ef0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -416,9 +416,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let captured_place = self.upvars.get(upvar_index)?; let upvar_hir_id = captured_place.get_root_variable(); let parent_local_def_id = parent_def_id.as_local()?; - let parent_body = tcx.hir_body_owned_by(parent_local_def_id); + let parent_sig = + tcx.hir_fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(parent_local_def_id)).unwrap(); let param_index = - parent_body.params.iter().position(|param| param.pat.hir_id == upvar_hir_id)?; + parent_sig.decl.inputs.iter().position(|param| param.pat.hir_id == upvar_hir_id)?; // Get the parent fn's signature with liberated late-bound regions, // so we have `ReLateParam` instead of `ReBound`. @@ -536,7 +537,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { ) -> Option<&hir::Ty<'tcx>> { let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(self.mir_hir_id())?; // Closures don't have implicit self arguments in HIR, so use `user_arg_index` directly. - let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(user_arg_index)?; + let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(user_arg_index)?.ty; match argument_hir_ty.kind { // This indicates a variable with no type annotation, like // `|x|`... in that case, we can't highlight the type but diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ceb7f38c2a416..68f3ec26f9516 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1956,7 +1956,6 @@ pub struct BodyId { /// map using `body_owner_def_id()`. #[derive(Debug, Clone, Copy, StableHash)] pub struct Body<'hir> { - pub params: &'hir [Param<'hir>], pub value: &'hir Expr<'hir>, } @@ -3611,6 +3610,7 @@ pub enum TyKind<'hir, Unambig = ()> { /// This variant is not always used to represent inference types, sometimes /// [`GenericArg::Infer`] is used instead. Infer(Unambig), + CVarArgs, } /// Stores explicit register name from source @@ -3732,8 +3732,9 @@ pub struct Param<'hir> { #[stable_hash(ignore)] pub hir_id: HirId, pub pat: &'hir Pat<'hir>, + pub ty: &'hir Ty<'hir>, pub ty_span: Span, - pub span: Span, + pub param_span: Span, } /// Error type for splatted argument index errors. @@ -3917,13 +3918,11 @@ impl FnDeclFlags { /// Represents the header (not the body) of a function declaration. #[derive(Debug, Clone, Copy, StableHash)] pub struct FnDecl<'hir> { - /// The types of the function's parameters. - /// - /// Additional argument data is stored in the function's [body](Body::params). - pub inputs: &'hir [Ty<'hir>], + pub inputs: &'hir [Param<'hir>], pub output: FnRetTy<'hir>, /// The packed function declaration attributes. pub fn_decl_kind: FnDeclFlags, + pub fn_has_body: bool, } impl<'hir> FnDecl<'hir> { @@ -3968,6 +3967,7 @@ impl<'hir> FnDecl<'hir> { inputs: &[], output: FnRetTy::DefaultReturn(span), fn_decl_kind: FnDeclFlags::default().set_lifetime_elision_allowed(true), + fn_has_body: true, } } } @@ -5275,7 +5275,7 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(Block<'_>, 48); - static_assert_size!(Body<'_>, 24); + static_assert_size!(Body<'_>, 8); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 48); static_assert_size!(FnDecl<'_>, 40); @@ -5290,7 +5290,7 @@ mod size_asserts { static_assert_size!(Item<'_>, 88); static_assert_size!(ItemKind<'_>, 64); static_assert_size!(LetStmt<'_>, 64); - static_assert_size!(Param<'_>, 32); + static_assert_size!(Param<'_>, 40); static_assert_size!(Pat<'_>, 80); static_assert_size!(PatKind<'_>, 56); static_assert_size!(Path<'_>, 40); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b404d1708b85b..7293fb6254569 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -109,6 +109,7 @@ impl<'a> FnKind<'a> { pub trait HirTyCtxt<'hir> { /// Retrieves the `Node` corresponding to `id`. fn hir_node(&self, hir_id: HirId) -> Node<'hir>; + fn hir_fn_decl(&self, hir_id: HirId) -> &'hir FnDecl<'hir>; fn hir_body(&self, id: BodyId) -> &'hir Body<'hir>; fn hir_item(&self, id: ItemId) -> &'hir Item<'hir>; fn hir_trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>; @@ -121,6 +122,9 @@ impl<'hir> HirTyCtxt<'hir> for ! { fn hir_node(&self, _: HirId) -> Node<'hir> { *self } + fn hir_fn_decl(&self, _: HirId) -> &'hir FnDecl<'hir> { + *self + } fn hir_body(&self, _: BodyId) -> &'hir Body<'hir> { *self } @@ -542,7 +546,8 @@ pub trait Visitor<'v>: Sized { } pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result { - let Param { hir_id, pat, ty_span: _, span: _ } = param; + let Param { hir_id, pat, ty, ty_span: _, param_span: _ } = param; + try_visit!(visitor.visit_ty_unambig(*ty)); try_visit!(visitor.visit_id(*hir_id)); visitor.visit_pat(pat) } @@ -663,8 +668,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: } pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &Body<'v>) -> V::Result { - let Body { params, value } = body; - walk_list!(visitor, visit_param, *params); + let Body { value } = body; visitor.visit_expr(*value) } @@ -1079,6 +1083,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) - try_visit!(visitor.visit_ident(*field)); } } + TyKind::CVarArgs => {} } V::Result::output() } @@ -1233,8 +1238,8 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>( visitor: &mut V, function_declaration: &'v FnDecl<'v>, ) -> V::Result { - let FnDecl { inputs, output, fn_decl_kind: _ } = function_declaration; - walk_list!(visitor, visit_ty_unambig, *inputs); + let FnDecl { inputs, output, fn_decl_kind: _, fn_has_body: _ } = function_declaration; + walk_list!(visitor, visit_param, *inputs); visitor.visit_fn_ret_ty(output) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index 6e22ce3d84b76..f941f89250721 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -396,11 +396,11 @@ fn report_number_of_arguments_mismatch<'tcx>( .and_then(|def_id| { let declaration_sig = get_declaration_sig(tcx, def_id).expect("foreign item sig"); let pos = declaration_number_args.saturating_sub(1); - declaration_sig.decl.inputs.get(pos).map(|arg| { + declaration_sig.decl.inputs.get(pos).map(|param| { if pos == 0 { - arg.span + param.ty.span } else { - arg.span.with_lo(declaration_sig.decl.inputs[0].span.lo()) + param.ty.span.with_lo(declaration_sig.decl.inputs[0].ty.span.lo()) } }) }) @@ -413,11 +413,11 @@ fn report_number_of_arguments_mismatch<'tcx>( .decl .inputs .get(pos) - .map(|arg| { + .map(|param| { if pos == 0 { - arg.span + param.ty.span } else { - arg.span.with_lo(external_impl_sig.decl.inputs[0].span.lo()) + param.ty.span.with_lo(external_impl_sig.decl.inputs[0].ty.span.lo()) } }) .unwrap_or_else(|| tcx.def_span(external_impl)); @@ -536,12 +536,12 @@ fn extract_spans_for_error_reporting<'tcx>( let (mut external_impl_args, external_impl_name) = { let item = tcx.hir_expect_item(external_impl); let (ident, sig, _, _) = item.expect_fn(); - (sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())), ident) + (sig.decl.inputs.iter().map(|p| p.ty.span).chain(iter::once(sig.decl.output.span())), ident) }; let declaration_args = declaration.as_local().map(|def_id| { if let Some(sig) = get_declaration_sig(tcx, def_id) { - sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) + sig.decl.inputs.iter().map(|p| p.ty.span).chain(iter::once(sig.decl.output.span())) } else { panic!("expected {def_id:?} to be a foreign function"); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 204b6f913cb8b..3b299b4b6d5ed 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1023,15 +1023,15 @@ fn report_trait_method_mismatch<'tcx>( // When the `impl` receiver is an arbitrary self type, like `self: Box`, the // span points only at the type `Box, but we want to cover the whole // argument pattern and type. - let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); + let (sig, _) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); let span = tcx - .hir_body_param_idents(body) + .hir_body_param_idents(sig.decl) .zip(sig.decl.inputs.iter()) - .map(|(param_ident, ty)| { + .map(|(param_ident, param)| { if let Some(param_ident) = param_ident { - param_ident.span.to(ty.span) + param_ident.span.to(param.ty.span) } else { - ty.span + param.ty.span } }) .next() @@ -1471,12 +1471,12 @@ fn extract_spans_for_error_reporting<'tcx>( let tcx = infcx.tcx; let mut impl_args = { let (sig, _) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); - sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) + sig.decl.inputs.iter().map(|p| p.ty.span).chain(iter::once(sig.decl.output.span())) }; let trait_args = trait_m.def_id.as_local().map(|def_id| { let (sig, _) = tcx.hir_expect_trait_item(def_id).expect_fn(); - sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) + sig.decl.inputs.iter().map(|p| p.ty.span).chain(iter::once(sig.decl.output.span())) }); match terr { @@ -1745,11 +1745,11 @@ fn compare_number_of_method_arguments<'tcx>( .and_then(|def_id| { let (trait_m_sig, _) = &tcx.hir_expect_trait_item(def_id).expect_fn(); let pos = trait_number_args.saturating_sub(1); - trait_m_sig.decl.inputs.get(pos).map(|arg| { + trait_m_sig.decl.inputs.get(pos).map(|param| { if pos == 0 { - arg.span + param.ty.span } else { - arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo()) + param.ty.span.with_lo(trait_m_sig.decl.inputs[0].ty.span.lo()) } }) }) @@ -1761,11 +1761,11 @@ fn compare_number_of_method_arguments<'tcx>( .decl .inputs .get(pos) - .map(|arg| { + .map(|param| { if pos == 0 { - arg.span + param.ty.span } else { - arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo()) + param.ty.span.with_lo(impl_m_sig.decl.inputs[0].ty.span.lo()) } }) .unwrap_or_else(|| tcx.def_span(impl_m.def_id)); @@ -1820,8 +1820,8 @@ fn compare_number_of_method_arguments<'tcx>( let first_lo = arg_idents .get(0) .and_then(|id| id.map(|id| id.span.lo())) - .unwrap_or(first.span.lo()); - Some(impl_m_sig.span.with_lo(first_lo).with_hi(last.span.hi())) + .unwrap_or(first.ty.span.lo()); + Some(impl_m_sig.span.with_lo(first_lo).with_hi(last.ty.span.hi())) } else { // We have no inputs; construct the span to the left of the last parenthesis // fn foo( ) {} @@ -1882,7 +1882,7 @@ fn compare_number_of_method_arguments<'tcx>( .decl .inputs .get(trait_number_args - 1) - .map(|arg| arg.span.hi())? + .map(|param| param.ty.span.hi())? }; let span = full.with_lo(lo); Some(( @@ -2008,9 +2008,9 @@ fn compare_synthetic_generics<'tcx>( } } - let span = input_tys - .iter() - .find_map(|ty| Visitor(impl_def_id).visit_ty_unambig(ty).break_value())?; + let span = input_tys.iter().find_map(|param| { + Visitor(impl_def_id).visit_ty_unambig(param.ty).break_value() + })?; let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds; let bounds = bounds.first()?.span().to(bounds.last()?.span()); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 0a57a177be985..8d4262c681df6 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -668,7 +668,7 @@ pub fn check_function_signature<'tcx>( let mut args = { let node = tcx.expect_hir_owner_node(fn_id); let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node)); - decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span())) + decl.inputs.iter().map(|p| p.ty.span).chain(std::iter::once(decl.output.span())) }; match err { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 96acfd2f97177..bbc4926452fb3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -778,7 +778,10 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. this.cx.var_parent = this.cx.parent; - for param in body.params { + + let decl = + this.tcx.hir_fn_decl_by_hir_id(this.tcx.hir_body_owner(body_id)).unwrap(); + for param in decl.inputs { this.visit_pat(param.pat); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 86f386381b9e2..0f533e640cce3 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1635,8 +1635,12 @@ fn check_fn_or_method<'tcx>( // on the entire `FnSig`, since this would use the same `WellFormedLoc` // for each type, preventing the HIR wf check from generating // a nice error message. - let arg_span = - |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span); + let arg_span = |idx| { + hir_decl + .inputs + .get(idx) + .map_or(hir_decl.output.span(), |param: &hir::Param<'_>| param.ty.span) + }; sig.inputs_and_output = tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| { @@ -1682,14 +1686,14 @@ fn check_fn_or_method<'tcx>( ); } else { tcx.dcx().span_err( - hir_decl.inputs.last().map_or(span, |input| input.span), + hir_decl.inputs.last().map_or(span, |input| input.ty.span), "functions with the \"rust-call\" ABI must take a single non-self tuple argument", ); } // No more inputs other than the `self` type and the tuple type if inputs.next().is_some() { tcx.dcx().span_err( - hir_decl.inputs.last().map_or(span, |input| input.span), + hir_decl.inputs.last().map_or(span, |input| input.ty.span), "functions with the \"rust-call\" ABI must take a single non-self tuple argument", ); } @@ -1731,7 +1735,7 @@ fn check_method_receiver<'tcx>( return Ok(()); } - let span = fn_sig.decl.inputs[0].span; + let span = fn_sig.decl.inputs[0].ty.span; let loc = WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 }; let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip(); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs index 4d685ec3c6810..08ed1f15ea7a5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -171,6 +171,7 @@ fn first_explicit_lifetime_span_in_ty(ty: &hir::Ty<'_>) -> Option { hir::TyKind::InferDelegation(_) | hir::TyKind::Never | hir::TyKind::Infer(()) + | hir::TyKind::CVarArgs | hir::TyKind::Err(_) => None, } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b81b7aafb8c1d..4b8468960831b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -722,17 +722,22 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { let input_tys = decl .inputs .iter() + .filter(|param| !matches!(param.ty.kind, hir::TyKind::CVarArgs)) .enumerate() - .map(|(i, a)| { - if let hir::TyKind::Infer(()) = a.kind + .map(|(i, param)| { + if let hir::TyKind::Infer(()) = param.ty.kind && let Some(suggested_ty) = self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) { - infer_replacements.push((a.span, suggested_ty.to_string())); - return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string()); + infer_replacements.push((param.ty.span, suggested_ty.to_string())); + return Ty::new_error_with_message( + tcx, + param.ty.span, + suggested_ty.to_string(), + ); } - self.lowerer().lower_ty(a) + self.lowerer().lower_ty(param.ty) }) .collect(); @@ -1673,8 +1678,8 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .emit_err(diagnostics::SIMDFFIHighlyExperimental { span: hir_ty.span, snip }); } }; - for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { - check(input, *ty) + for (param, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { + check(param.ty, *ty) } if let hir::FnRetTy::Return(ty) = decl.output { check(ty, fty.output().skip_binder()) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 1dc6c1c96e93e..5a284d7451828 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -18,7 +18,8 @@ use rustc_hir::def_id::LocalDefIdMap; use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorsMap}; use rustc_hir::intravisit::{self, InferKind, Visitor}; use rustc_hir::{ - self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node, + self as hir, AmbigArg, FnDecl, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, + Node, }; use rustc_macros::extension; use rustc_middle::hir::nested_filter; @@ -434,9 +435,20 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.tcx } + fn visit_fn_decl(&mut self, decl: &'tcx FnDecl<'tcx>) -> Self::Result { + if !decl.fn_has_body { + intravisit::walk_fn_decl(self, decl); + } + } + fn visit_nested_body(&mut self, body: hir::BodyId) { let body = self.tcx.hir_body(body); self.with(Scope::Body { id: body.id(), s: self.scope }, |this| { + if let Some(decl) = this.tcx.hir_fn_decl_by_hir_id(this.tcx.hir_body_owner(body.id())) { + for input in decl.inputs { + intravisit::walk_pat(this, input.pat); + } + } this.visit_body(body); }); } @@ -474,6 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let infer_spans = fn_decl .inputs .into_iter() + .map(|param| param.ty) .filter_map(span_of_infer) .chain(infer_in_rt_sp) .collect::>(); @@ -976,7 +989,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id); self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars); } - self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); + self.visit_fn_like_elision( + fd.inputs.iter().map(|p| p.ty), + output, + matches!(fk, intravisit::FnKind::Closure), + ); intravisit::walk_fn_kind(self, fk); self.visit_nested_body(body_id) } @@ -1811,7 +1828,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { path: &hir::Path<'tcx>, ) { if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() { - self.visit_fn_like_elision(inputs, Some(output), false); + self.visit_fn_like_elision(inputs.iter(), Some(output), false); return; } @@ -2260,10 +2277,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, inputs))] fn visit_fn_like_elision( &mut self, - inputs: &'tcx [hir::Ty<'tcx>], + inputs: impl Iterator>, output: Option<&'tcx hir::Ty<'tcx>>, in_closure: bool, ) { @@ -2594,8 +2611,8 @@ fn is_late_bound_map( let mut late_bound = FxIndexSet::default(); let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx }; - for arg_ty in sig.decl.inputs { - constrained_by_input.visit_ty_unambig(arg_ty); + for param in sig.decl.inputs { + constrained_by_input.visit_ty_unambig(param.ty); } let mut appears_in_output = diff --git a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs index f2b166e0b2a01..980dd14a0fb07 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs @@ -359,7 +359,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id { - let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id); + let in_arg = fn_decl.inputs.iter().any(|p| p.ty.hir_id == ty_id); let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id); @@ -460,7 +460,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let fn_sig = self.tcx.hir_get_if_local(self.def_id).and_then(hir::Node::fn_sig); let is_used_in_input = |def_id| { fn_sig.is_some_and(|fn_sig| { - fn_sig.decl.inputs.iter().any(|ty| match ty.kind { + fn_sig.decl.inputs.iter().any(|param| match param.ty.kind { hir::TyKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Def(_, id), .. }, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 530706b0653db..b5229b500e062 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -84,15 +84,15 @@ fn is_valid_cmse_inputs<'tcx>( let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); let fn_sig = tcx.erase_and_anonymize_regions(fn_sig); - for (ty, hir_ty) in fn_sig.inputs().iter().zip(fn_decl.inputs) { + for (ty, hir_param) in fn_sig.inputs().iter().zip(fn_decl.inputs) { if ty.has_infer_types() { let err = LayoutError::Unknown(*ty); - return Err((hir_ty.span, tcx.arena.alloc(err))); + return Err((hir_param.ty.span, tcx.arena.alloc(err))); } let layout = tcx .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty)) - .map_err(|e| (hir_ty.span, e))?; + .map_err(|e| (hir_param.ty.span, e))?; let align = layout.layout.align().bytes(); let size = layout.layout.size().bytes(); @@ -102,7 +102,7 @@ fn is_valid_cmse_inputs<'tcx>( // i.e. exceeds 4 32-bit registers if accum > 16 { - excess_argument_spans.push(hir_ty.span); + excess_argument_spans.push(hir_param.ty.span); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 9123afd5986f5..7b0426b54becd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -950,8 +950,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // Suggestions for function parameters. - for ty in sig.decl.inputs { - if ty.peel_refs().hir_id != hir_id { + for param in sig.decl.inputs { + if param.ty.peel_refs().hir_id != hir_id { continue; } let sugg = self.add_generic_param_suggestion(generics, span, &trait_name); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 4fa02926f15d8..8d2eb23276607 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3435,6 +3435,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::TyKind::View(ty, fields) => { self.lower_view(self.lower_ty(ty), fields, hir_ty.span) } + hir::TyKind::CVarArgs => Ty::new_error( + tcx, + self.dcx().delayed_bug("This is only reachable if errors previously occurred"), + ), hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar), }; diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 9806b7b873918..d4ab8fe53e28b 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -195,14 +195,14 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( WellFormedLoc::Param { param_idx, .. } => { let fn_decl = tcx.hir_fn_decl_by_hir_id(hir_id).unwrap(); // Get return type - if param_idx as usize == fn_decl.inputs.len() { + if param_idx == fn_decl.inputs.len() { match fn_decl.output { hir::FnRetTy::Return(ty) => vec![ty], // The unit type `()` is always well-formed hir::FnRetTy::DefaultReturn(_span) => vec![], } } else { - vec![&fn_decl.inputs[param_idx as usize]] + vec![fn_decl.inputs[param_idx].ty] } } WellFormedLoc::HirId(_) | WellFormedLoc::None => return None, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d8c57bfbdb56b..6ad58bf39dc25 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -47,7 +47,7 @@ pub enum Nested { ImplItem(hir::ImplItemId), ForeignItem(hir::ForeignItemId), Body(hir::BodyId), - BodyParamPat(hir::BodyId, usize), + BodyParamPat(hir::HirId, usize), } pub trait PpAnn { @@ -64,7 +64,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> { Nested::ImplItem(id) => state.print_impl_item(self.hir_impl_item(id)), Nested::ForeignItem(id) => state.print_foreign_item(self.hir_foreign_item(id)), Nested::Body(id) => state.print_expr(self.hir_body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(self.hir_body(id).params[i].pat), + Nested::BodyParamPat(id, i) => state.print_pat(self.hir_fn_decl(id).inputs[i].pat), } } } @@ -493,6 +493,7 @@ impl<'a> State<'a> { } self.word("})"); } + hir::TyKind::CVarArgs => unreachable!("Filtered out before calling `print_type`"), } self.end(ib) } @@ -652,7 +653,14 @@ impl<'a> State<'a> { } hir::ItemKind::Fn { ident, sig, generics, body, .. } => { let (cb, ib) = self.head(""); - self.print_fn(sig.header, Some(ident.name), generics, sig.decl, &[], Some(body)); + self.print_fn( + sig.header, + Some(ident.name), + generics, + sig.decl, + &[], + Some(item.hir_id()), + ); self.word(" "); self.end(ib); self.end(cb); @@ -974,7 +982,7 @@ impl<'a> State<'a> { m: &hir::FnSig<'_>, generics: &hir::Generics<'_>, arg_idents: &[Option], - body_id: Option, + body_id: Option, ) { self.print_fn(m.header, Some(ident.name), generics, m.decl, arg_idents, body_id); } @@ -994,7 +1002,7 @@ impl<'a> State<'a> { } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let (cb, ib) = self.head(""); - self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(body)); + self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(ti.hir_id())); self.nbsp(); self.end(ib); self.end(cb); @@ -1019,7 +1027,7 @@ impl<'a> State<'a> { } hir::ImplItemKind::Fn(ref sig, body) => { let (cb, ib) = self.head(""); - self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(body)); + self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(ii.hir_id())); self.nbsp(); self.end(ib); self.end(cb); @@ -1685,7 +1693,7 @@ impl<'a> State<'a> { self.print_constness(constness); self.print_capture_clause(capture_clause); - self.print_closure_params(fn_decl, body); + self.print_closure_params(fn_decl, expr.hir_id); self.space(); // This is a bare expression. @@ -2273,7 +2281,7 @@ impl<'a> State<'a> { generics: &hir::Generics<'_>, decl: &hir::FnDecl<'_>, arg_idents: &[Option], - body_id: Option, + body_id: Option, ) { self.print_fn_header_info(header); @@ -2311,13 +2319,17 @@ impl<'a> State<'a> { } i += 1; }; - self.commasep(Inconsistent, decl.inputs, |s, ty| { - let ib = s.ibox(INDENT_UNIT); - print_arg(s, Some(ty)); - s.end(ib); - }); + self.commasep( + Inconsistent, + decl.inputs.iter().filter(|param| !matches!(param.ty.kind, hir::TyKind::CVarArgs)), + |s, param| { + let ib = s.ibox(INDENT_UNIT); + print_arg(s, Some(param.ty)); + s.end(ib); + }, + ); if decl.c_variadic() { - if !decl.inputs.is_empty() { + if decl.inputs.len() != 1 { self.word(", "); } print_arg(self, None); @@ -2329,21 +2341,21 @@ impl<'a> State<'a> { self.print_where_clause(generics) } - fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) { + fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::HirId) { self.word("|"); let mut i = 0; - self.commasep(Inconsistent, decl.inputs, |s, ty| { + self.commasep(Inconsistent, decl.inputs, |s, param| { let ib = s.ibox(INDENT_UNIT); s.ann.nested(s, Nested::BodyParamPat(body_id, i)); i += 1; - if let hir::TyKind::Infer(()) = ty.kind { + if let hir::TyKind::Infer(()) = param.ty.kind { // Print nothing. } else { s.word(":"); s.space(); - s.print_type(ty); + s.print_type(param.ty); } s.end(ib); }); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 8061e522f43aa..759f1a581afb8 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -50,14 +50,14 @@ pub(super) fn check_fn<'a, 'tcx>( let span = body.value.span; - for param in body.params { + for param in decl.inputs { GatherLocalsVisitor::gather_from_param(fcx, param); } // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` // (as it's created inside the body itself, not passed in from outside). let maybe_va_list = fn_sig.c_variadic().then(|| { - let span = body.params.last().unwrap().span; + let span = decl.inputs.last().unwrap().ty.span; let va_list_did = tcx.require_lang_item(LangItem::VaList, span); let region = fcx.next_region_var(RegionVariableOrigin::Misc(span)); @@ -66,12 +66,12 @@ pub(super) fn check_fn<'a, 'tcx>( // Add formal parameters. let inputs_fn = fn_sig.inputs().iter().copied(); - for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { + for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(decl.inputs).enumerate() { // We checked the root's signature during wfcheck, but not the child. if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) { fcx.register_wf_obligation( param_ty.into(), - param.span, + param.param_span, ObligationCauseCode::WellFormed(WellFormedLoc::Param { function: fn_def_id, param_idx: idx, @@ -80,9 +80,7 @@ pub(super) fn check_fn<'a, 'tcx>( } // Check the pattern. - let ty: Option<&hir::Ty<'_>> = decl.inputs.get(idx); - let ty_span = ty.map(|ty| ty.span); - fcx.check_pat_top(param.pat, param_ty, ty_span, None, None); + fcx.check_pat_top(param.pat, param_ty, Some(param.ty.span), None, None); if param.pat.is_never_pattern() { fcx.function_diverges_because_of_empty_arguments.set(Diverges::Always { span: param.pat.span, @@ -98,10 +96,10 @@ pub(super) fn check_fn<'a, 'tcx>( // ty.span == binding_span iff this is a closure parameter with no type ascription, // or if it's an implicit `self` parameter ObligationCauseCode::SizedArgumentType( - if ty_span == Some(param.span) && tcx.is_closure_like(fn_def_id.into()) { + if param.ty.span == param.param_span && tcx.is_closure_like(fn_def_id.into()) { None } else { - ty.map(|ty| ty.hir_id) + Some(param.ty.hir_id) }, ), ); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 79b4eff9153b0..71e31ff4657e1 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -792,12 +792,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The liberated version of this signature should be a subtype // of the liberated form of the expectation. - for ((hir_ty, &supplied_ty), expected_ty) in iter::zip( + for ((hir_pram, &supplied_ty), expected_ty) in iter::zip( iter::zip(decl.inputs, supplied_sig.inputs()), expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'. ) { // Check that E' = S'. - let cause = self.misc(hir_ty.span); + let cause = self.misc(hir_pram.ty.span); let InferOk { value: (), obligations } = self.at(&cause, self.param_env).eq( DefineOpaqueTypes::Yes, *expected_ty, @@ -851,7 +851,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let bound_vars = self.tcx.late_bound_vars(hir_id); // First, convert the types that the user supplied (if any). - let supplied_arguments = decl.inputs.iter().map(|a| lowerer.lower_ty(a)); + let supplied_arguments = decl.inputs.iter().map(|p| lowerer.lower_ty(p.ty)); let supplied_return = match decl.output { hir::FnRetTy::Return(ref output) => lowerer.lower_ty(output), hir::FnRetTy::DefaultReturn(_) => match closure_kind { @@ -1047,9 +1047,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let lowerer = self.lowerer(); let err_ty = Ty::new_error(self.tcx, guar); - let supplied_arguments = decl.inputs.iter().map(|a| { + let supplied_arguments = decl.inputs.iter().map(|p| { // Convert the types that the user supplied (if any), but ignore them. - lowerer.lower_ty(a); + lowerer.lower_ty(p.ty); err_ty }); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index e1ad43f0c00c9..9827e1be5dee3 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -893,8 +893,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(ty_ref) = fn_decl .inputs .iter() - .filter_map(|ty| match ty.kind { - hir::TyKind::Ref(lt, inner_ty, mutbl) if ty.span == *ty_span => Some((lt, inner_ty, mutbl)), + .filter_map(|param| match param.ty.kind { + hir::TyKind::Ref(lt, inner_ty, mutbl) if param.ty.span == *ty_span => Some((lt, inner_ty, mutbl)), _ => None, }) .next() diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 0c49ec002671d..ae73330d06418 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -305,8 +305,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } - pub fn consume_body(&self, body: &hir::Body<'_>) -> Result<(), Cx::Error> { - for param in body.params { + pub fn consume_body( + &self, + decl: &hir::FnDecl<'_>, + body: &hir::Body<'_>, + ) -> Result<(), Cx::Error> { + for param in decl.inputs { let param_ty = self.pat_ty_adjusted(param.pat)?; debug!("consume_body: param_ty = {:?}", param_ty); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8ecd7838a0e69..c5b444ec5083e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -769,9 +769,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let spans = if let SplatLoweringInfo::FnDef(def_id) = fn_id && let Some(hir_node) = self.tcx.hir_get_if_local(def_id) && let Some(fn_decl) = hir_node.fn_decl() - && let Some(arg_ty) = fn_decl.inputs.get(first_tupled_arg_index_usz) + && let Some(param) = fn_decl.inputs.get(first_tupled_arg_index_usz) { - let arg_def_span = arg_ty.span; + let arg_def_span = param.ty.span; vec![call_span, arg_def_span] } else { vec![call_span] @@ -1923,10 +1923,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id) - && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind + && let hir::ExprKind::Closure(hir::Closure { fn_decl, .. }) = &e.kind { - let param = expected_idx - .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx)); + let param = expected_idx.and_then(|expected_idx| fn_decl.inputs.get(expected_idx)); let (kind, span) = if let Some(param) = param { // Try to find earlier invocations of this closure to find if the type mismatch // is because of inference. If we find one, point at them. @@ -1967,7 +1966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - ("closure parameter", param.span) + ("closure parameter", param.param_span) } else { ("closure", self.tcx.def_span(def_id)) }; @@ -2093,25 +2092,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Make sure to remove both the receiver and variadic argument. Both are removed // when matching parameter types. - let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| { - if let hir::TyKind::Path(QPath::Resolved( - _, - &hir::Path { res: Res::Def(_, res_def_id), .. }, - )) = param.kind - { - generics - .params - .iter() - .position(|param| param.def_id.to_def_id() == res_def_id) - .map(GenericIdx::from_usize) - } else { - None - } - }); + let fn_inputs = sig + .decl + .inputs + .get(is_method as usize..(sig.decl.inputs.len() - sig.decl.c_variadic() as usize))? + .iter() + .map(|param| { + if let hir::TyKind::Path(QPath::Resolved( + _, + &hir::Path { res: Res::Def(_, res_def_id), .. }, + )) = param.ty.kind + { + generics + .params + .iter() + .position(|param| param.def_id.to_def_id() == res_def_id) + .map(GenericIdx::from_usize) + } else { + None + } + }); match (body_id, params) { (Some(_), Some(_)) | (None, None) => unreachable!(), - (Some(body), None) => { - let params = self.tcx.hir_body(body).params; + (Some(_body), None) => { + let params = sig.decl.inputs; let params = params .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?; debug_assert_eq!(params.len(), fn_inputs.len()); @@ -2159,7 +2163,7 @@ enum FnParam<'hir> { impl FnParam<'_> { fn span(&self) -> Span { match self { - Self::Param(param) => param.span, + Self::Param(param) => param.param_span, Self::Ident(ident) => { if let Some(ident) = ident { ident.span diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index b2b49dc06b7a6..8940820a54a13 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -455,7 +455,12 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { _hir_id: rustc_hir::HirId, _hir_ty: Option<&hir::Ty<'_>>, ) -> (Vec>, Ty<'tcx>) { - let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_ty(a)).collect(); + let input_tys = decl + .inputs + .iter() + .filter(|p| !matches!(p.ty.kind, hir::TyKind::CVarArgs)) + .map(|p| self.lowerer().lower_ty(p.ty)) + .collect(); let output_ty = match decl.output { hir::FnRetTy::Return(output) => self.lowerer().lower_ty(output), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 116bbf6280642..809db98f3fd19 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::FnDecl { inputs, output, .. } = fn_ptr_ty.decl; let inputs_str = - inputs.iter().map(|ty| rustc_hir_pretty::ty_to_string(self, ty)).join(", "); + inputs.iter().map(|param| rustc_hir_pretty::ty_to_string(self, param.ty)).join(", "); let output_str = match output { hir::FnRetTy::DefaultReturn(_) => String::new(), @@ -1293,7 +1293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let all_bounds_str = all_matching_bounds_strs.join(" + "); let ty_param_used_in_fn_params = fn_parameters.iter().any(|param| { - let ty = self.lowerer().lower_ty( param); + let ty = self.lowerer().lower_ty(param.ty); matches!(ty.kind(), ty::Param(fn_param_ty_param) if expected_ty_as_param == fn_param_ty_param) }); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 2945a6b3b5136..a3044b133c6a6 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -147,19 +147,18 @@ fn typeck_with_inspect<'tcx>( }; check_abi(tcx, id, span, fn_sig.abi()); - loops::check(tcx, def_id, body); // Compute the function signature from point of view of inside the fn. let mut fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); - // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` // for each type, preventing the HIR wf check from generating // a nice error message. - let arg_span = - |idx| decl.inputs.get(idx).map_or(decl.output.span(), |arg: &hir::Ty<'_>| arg.span); + let arg_span = |idx| { + decl.inputs.get(idx).map_or(decl.output.span(), |param: &hir::Param<'_>| param.ty.span) + }; fn_sig.inputs_and_output = tcx.mk_type_list_from_iter( fn_sig @@ -170,7 +169,7 @@ fn typeck_with_inspect<'tcx>( ); if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) { - naked_functions::typeck_naked_fn(tcx, def_id, body); + naked_functions::typeck_naked_fn(tcx, def_id, decl, body); } check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params()); @@ -265,7 +264,7 @@ fn typeck_with_inspect<'tcx>( fcx.check_asms(); - let typeck_results = fcx.resolve_type_vars_in_body(body); + let typeck_results = fcx.resolve_type_vars_in_body(node, body); fcx.detect_opaque_types_added_during_writeback(); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 53b081962a386..1ef029f6dc00e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -453,10 +453,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind && let hir::def::Res::Local(hir_id) = path.res && let hir::Node::Pat(b) = self.tcx.hir_node(hir_id) - && let hir::Node::Param(p) = self.tcx.parent_hir_node(b.hir_id) - && let Some(decl) = self.tcx.parent_hir_node(p.hir_id).fn_decl() - && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span) - && let hir::TyKind::Ref(_, inner_ty, hir::Mutability::Not) = &ty.kind + && let hir::Node::Param(param) = self.tcx.parent_hir_node(b.hir_id) + && let hir::TyKind::Ref(_, inner_ty, hir::Mutability::Not) = + ¶m.ty.kind { err.span_suggestion_verbose( inner_ty.span.shrink_to_lo(), @@ -4466,16 +4465,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::TraitFn::Required([ident, ..]) => { matches!(ident, Some(Ident { name: kw::SelfLower, .. })) } - hir::TraitFn::Provided(body_id) => { - self.tcx.hir_body(*body_id).params.first().is_some_and( - |param| { - matches!( - param.pat.kind, - hir::PatKind::Binding(_, _, ident, _) - if ident.name == kw::SelfLower - ) - }, - ) + hir::TraitFn::Provided(_body_id) => { + fn_sig.decl.inputs.first().is_some_and(|param| { + matches!( + param.pat.kind, + hir::PatKind::Binding(_, _, ident, _) + if ident.name == kw::SelfLower + ) + }) } _ => false, }; @@ -4483,8 +4480,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !fn_sig.decl.implicit_self().has_implicit_self() && self_first_arg { - if let Some(ty) = fn_sig.decl.inputs.get(0) { - arbitrary_rcvr.push(ty.span); + if let Some(param) = fn_sig.decl.inputs.get(0) { + arbitrary_rcvr.push(param.ty.span); } return false; } diff --git a/compiler/rustc_hir_typeck/src/naked_functions.rs b/compiler/rustc_hir_typeck/src/naked_functions.rs index ce4893ce94b1f..60cf9bd2a7d6a 100644 --- a/compiler/rustc_hir_typeck/src/naked_functions.rs +++ b/compiler/rustc_hir_typeck/src/naked_functions.rs @@ -18,11 +18,12 @@ use crate::diagnostics::{ pub(crate) fn typeck_naked_fn<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, + decl: &'tcx hir::FnDecl<'tcx>, body: &'tcx hir::Body<'tcx>, ) { debug_assert!(find_attr!(tcx, def_id, Naked(..))); - check_no_patterns(tcx, body.params); - check_no_parameters_use(tcx, body); + check_no_patterns(tcx, decl.inputs); + check_no_parameters_use(tcx, decl, body); check_asm(tcx, def_id, body); } @@ -39,9 +40,13 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) { } /// Checks that function parameters aren't used in the function body. -fn check_no_parameters_use<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) { +fn check_no_parameters_use<'tcx>( + tcx: TyCtxt<'tcx>, + decl: &'tcx hir::FnDecl<'tcx>, + body: &'tcx hir::Body<'tcx>, +) { let mut params = HirIdSet::default(); - for param in body.params { + for param in decl.inputs { param.pat.each_binding(|_binding_mode, hir_id, _span, _ident| { params.insert(hir_id); }); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 98155d9a8d5ef..30fbff51bef67 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -94,6 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { capture_clause, body: body_id, explicit_captures, + fn_decl, .. }) = expr.kind else { @@ -128,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fake_reads: Default::default(), }; - let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(body); + let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(fn_decl, body); for capture in explicit_captures { let place = closure_fcx.place_for_root_variable(closure_def_id, capture.var_hir_id); @@ -220,10 +221,22 @@ struct InferBorrowKindVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { match expr.kind { - hir::ExprKind::Closure(&hir::Closure { capture_clause, body: body_id, .. }) => { + hir::ExprKind::Closure(&hir::Closure { + capture_clause, + body: body_id, + fn_decl, + .. + }) => { let body = self.fcx.tcx.hir_body(body_id); self.visit_body(body); - self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause); + self.fcx.analyze_closure( + expr.hir_id, + expr.span, + fn_decl, + body_id, + body, + capture_clause, + ); } _ => {} } @@ -244,6 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, closure_hir_id: HirId, span: Span, + fn_decl: &'tcx hir::FnDecl<'tcx>, body_id: hir::BodyId, body: &'tcx hir::Body<'tcx>, mut capture_clause: hir::CaptureBy, @@ -288,7 +302,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // First collect the captures implied by the operations in the closure // body. This records how each place is actually used: borrowed, modified, // moved, and so on. - let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(body); + let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(fn_decl, body); // Save the captures that must be upgraded to by-value after inferring // the closure kind from the operations in the body. diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 923c0d49936c8..8faf4b1247acf 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -17,7 +17,7 @@ use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{E0720, ErrorGuaranteed}; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, InferKind, Visitor}; -use rustc_hir::{self as hir, AmbigArg, HirId}; +use rustc_hir::{self as hir, AmbigArg, FnDecl, HirId}; use rustc_infer::traits::solve::Goal; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; @@ -40,6 +40,7 @@ use crate::FnCtxt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn resolve_type_vars_in_body( &self, + node: hir::Node<'tcx>, body: &'tcx hir::Body<'tcx>, ) -> &'tcx ty::TypeckResults<'tcx> { let item_def_id = self.tcx.hir_body_owner_def_id(body.id()); @@ -50,8 +51,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.has_rustc_attrs && find_attr!(self.tcx, item_def_id, RustcDumpUserArgs); let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_args); - for param in body.params { - wbcx.visit_node_id(param.pat.span, param.hir_id); + if let Some(decl) = node.fn_decl() { + for param in decl.inputs { + wbcx.visit_node_id(param.pat.span, param.hir_id); + wbcx.visit_param(param); + } } match self.tcx.hir_body_owner_kind(item_def_id) { // Visit the type of a const or static, which is used during THIR building. @@ -260,10 +264,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { match e.kind { - hir::ExprKind::Closure(&hir::Closure { body, .. }) => { + hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) => { let body = self.fcx.tcx.hir_body(body); - for param in body.params { + for param in fn_decl.inputs { self.visit_node_id(e.span, param.hir_id); + self.visit_param(param); } self.visit_body(body); @@ -373,6 +378,12 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { self.write_ty_to_typeck_results(inf_id, ty); } } + + fn visit_fn_decl(&mut self, fd: &'tcx FnDecl<'tcx>) -> Self::Result { + if fd.fn_has_body { + intravisit::walk_fn_decl(self, fd); + } + } } impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { diff --git a/compiler/rustc_lint/src/gpukernel_abi.rs b/compiler/rustc_lint/src/gpukernel_abi.rs index 05f41cd6fdf48..1d9f009087134 100644 --- a/compiler/rustc_lint/src/gpukernel_abi.rs +++ b/compiler/rustc_lint/src/gpukernel_abi.rs @@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperGpuKernelLint { cx.tcx.emit_node_span_lint( IMPROPER_GPU_KERNEL_ARG, input_hir.hir_id, - input_hir.span, + input_hir.ty.span, ImproperGpuKernelArg { ty: *input_ty }, ); } diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index ea09ce79fd49d..5f747fdd63b34 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -126,7 +126,7 @@ fn check_fn_like<'tcx>(cx: &LateContext<'tcx>, fd: &'tcx hir::FnDecl<'tcx>) { } for input in fd.inputs { - LifetimeInfoCollector::collect(input, |info| { + LifetimeInfoCollector::collect(input.ty, |info| { if let Some(group) = map.get_mut(&info.lifetime.kind) { group.inputs.push(info); } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 66478f052d68b..5202ae61cedac 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{GenericParamKind, PatExprKind, PatKind}; +use rustc_hir::{GenericParamKind, Node, PatExprKind, PatKind}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty::AssocContainer; @@ -417,28 +417,25 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_, hir::AmbigArg>) { - if let hir::TyKind::FnPtr(hir::FnPtrTy { param_idents, .. }) = &ty.kind { - for param_ident in *param_idents { - if let Some(param_ident) = param_ident { - self.check_snake_case(cx, "variable", param_ident); - } - } - } - } - fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(param_idents)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); - for param_ident in param_idents { - if let Some(param_ident) = param_ident { - self.check_snake_case(cx, "variable", param_ident); - } - } } } fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { + // Ignore patterns in foreign items for now + // FIXME(#33995) remove this check + if let Node::ForeignItem(_) = cx + .tcx + .hir_parent_iter(p.hir_id) + .find(|(_, n)| !matches!(n, Node::Pat(_) | Node::Param(_))) + .unwrap() + .1 + { + return; + } + if let PatKind::Binding(_, hid, ident, _) = p.kind { if let hir::Node::PatField(field) = cx.tcx.parent_hir_node(hid) { if !field.is_shorthand { diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 04b381261e428..c90c71b0b7cb9 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -1117,7 +1117,7 @@ impl<'tcx> ImproperCTypesLint { for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { let state = VisitorState::fn_entry_point(fn_mode, FnPos::Arg); - self.check_type_for_external_abi_fnptr(cx, state, input_hir, *input_ty, fn_mode); + self.check_type_for_external_abi_fnptr(cx, state, input_hir.ty, *input_ty, fn_mode); } if let hir::FnRetTy::Return(ret_hir) = decl.output { @@ -1165,7 +1165,7 @@ impl<'tcx> ImproperCTypesLint { for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { let state = VisitorState::fn_entry_point(fn_mode, FnPos::Arg); - self.check_ffi_type(cx, *input_ty, state, input_hir.span, fn_mode, || { + self.check_ffi_type(cx, *input_ty, state, input_hir.ty.span, fn_mode, || { let input_ty = Unnormalized::new_wip(*input_ty); let mut visitor = ImproperCTypesVisitor::new(cx, input_ty, fn_mode); visitor.check_type(state, input_ty) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index ea266e0032add..64c9ab335a9af 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -309,8 +309,8 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn hir_body_param_idents(self, id: BodyId) -> impl Iterator> { - self.hir_body(id).params.iter().map(|param| match param.pat.kind { + pub fn hir_body_param_idents(self, decl: &FnDecl<'_>) -> impl Iterator> { + decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Binding(_, _, ident, _) => Some(ident), PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)), _ => None, @@ -1037,7 +1037,7 @@ impl<'tcx> TyCtxt<'tcx> { /// (instead of just the item header) pub fn hir_span_with_body(self, hir_id: HirId) -> Span { match self.hir_node(hir_id) { - Node::Param(param) => param.span, + Node::Param(param) => param.param_span, Node::Item(item) => item.span, Node::ForeignItem(foreign_item) => foreign_item.span, Node::TraitItem(trait_item) => trait_item.span, @@ -1142,6 +1142,10 @@ impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> { (*self).hir_node(hir_id) } + fn hir_fn_decl(&self, hir_id: HirId) -> &'tcx FnDecl<'tcx> { + (*self).hir_fn_decl_by_hir_id(hir_id).unwrap() + } + fn hir_body(&self, id: BodyId) -> &'tcx Body<'tcx> { (*self).hir_body(id) } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 02865e81c4c69..c6aa73098109c 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -477,8 +477,8 @@ pub fn provide(providers: &mut Providers) { }; providers.fn_arg_idents = |tcx, def_id| { let node = tcx.hir_node_by_def_id(def_id); - if let Some(body_id) = node.body_id() { - tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(body_id)) + if let Some(decl) = node.fn_decl() { + tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(decl)) } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), .. diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index ad1227bb51df0..71bb253676541 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -37,12 +37,12 @@ pub(crate) fn thir_body<'tcx>( let owner_id = tcx.local_def_id_to_hir_id(owner_def); if let Some(fn_decl) = tcx.hir_fn_decl_by_hir_id(owner_id) { let closure_env_param = cx.closure_env_param(owner_def, owner_id); - let explicit_params = cx.explicit_params(owner_id, fn_decl, &body); + let explicit_params = cx.explicit_params(owner_id, fn_decl); cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect(); // The resume argument may be missing, in that case we need to provide it here. // It will always be `()` in this case. - if tcx.is_coroutine(owner_def.to_def_id()) && body.params.is_empty() { + if tcx.is_coroutine(owner_def.to_def_id()) && fn_decl.inputs.is_empty() { cx.thir.params.push(Param { ty: tcx.types.unit, pat: None, @@ -179,16 +179,11 @@ impl<'tcx> ThirBuildCx<'tcx> { &mut self, owner_id: HirId, fn_decl: &'tcx hir::FnDecl<'tcx>, - body: &'tcx hir::Body<'tcx>, ) -> impl Iterator> { let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id]; - body.params.iter().enumerate().map(move |(index, param)| { - let ty_span = fn_decl - .inputs - .get(index) - // Make sure that inferred closure args have no type span - .and_then(|ty| if param.pat.span != ty.span { Some(ty.span) } else { None }); + fn_decl.inputs.iter().enumerate().map(move |(index, param)| { + let ty_span = if param.ty.span != param.pat.span { Some(param.ty.span) } else { None }; let self_kind = if index == 0 && fn_decl.implicit_self().has_implicit_self() { Some(fn_decl.implicit_self()) @@ -198,8 +193,8 @@ impl<'tcx> ThirBuildCx<'tcx> { // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` // (as it's created inside the body itself, not passed in from outside). - let ty = if fn_decl.c_variadic() && index == fn_decl.inputs.len() { - let va_list_did = self.tcx.require_lang_item(LangItem::VaList, param.span); + let ty = if fn_decl.c_variadic() && index == fn_decl.inputs.len() - 1 { + let va_list_did = self.tcx.require_lang_item(LangItem::VaList, param.ty.span); self.tcx .type_of(va_list_did) diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index 77b8cfa3b86c2..ddeea0bad0cdb 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -292,12 +292,11 @@ fn annotate_mut_binding_to_immutable_binding<'tcx>( let hir_param_index = local.as_usize() - if tcx.is_closure_like(body_def_id.to_def_id()) { 2 } else { 1 }; let fn_decl = tcx.hir_node_by_def_id(body_def_id).fn_decl()?; - let ty = fn_decl.inputs[hir_param_index]; - let hir::TyKind::Ref(lt, inner_ty, mutbl) = ty.kind else { return None }; + let param = fn_decl.inputs[hir_param_index]; + let hir::TyKind::Ref(lt, inner_ty, mutbl) = param.ty.kind else { return None }; // ... as a binding pattern. let hir_body = tcx.hir_maybe_body_owned_by(body_def_id)?; - let param = hir_body.params[hir_param_index]; let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = param.pat.kind else { return None; }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3eb6892177b05..6b9f48f728011 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1273,9 +1273,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if let Some(hir_sig) = hir_sig { match terr { TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => { - if let Some(ty) = hir_sig.decl.inputs.get(idx) { - diag.span(ty.span); - cause.span = ty.span; + if let Some(param) = hir_sig.decl.inputs.get(idx) { + diag.span(param.ty.span); + cause.span = param.ty.span; } else if idx == hir_sig.decl.inputs.len() { let span = hir_sig.decl.output.span(); diag.span(span); @@ -1283,9 +1283,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } TypeError::ArgCount => { - if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) { - diag.span(ty.span); - cause.span = ty.span; + if let Some(param) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) { + diag.span(param.ty.span); + cause.span = param.ty.span; } } TypeError::SafetyMismatch(_) => { @@ -1515,7 +1515,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - self.check_attributes(param.hir_id, param.span, Target::Param, None); + self.check_attributes(param.hir_id, param.param_span, Target::Param, None); intravisit::walk_param(self, param); } diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index dbb6d4b72d432..e065b92acb1c7 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -225,7 +225,7 @@ impl<'tcx, 'a> ExportableItemsChecker<'tcx, 'a> { let decl = self.tcx.hir_fn_decl_by_hir_id(hir_id).unwrap(); for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { - self.check_nested_types_are_exportable(*input_ty, input_hir.span); + self.check_nested_types_are_exportable(*input_ty, input_hir.ty.span); } if let hir::FnRetTy::Return(ret_hir) = decl.output { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ffa3a7443ecc4..b7cfeda66adac 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -15,7 +15,7 @@ use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ForeignItemId, ItemId, Node, PatKind, QPath}; +use rustc_hir::{self as hir, BodyId, FnDecl, ForeignItemId, ItemId, Node, PatKind, QPath}; use rustc_lint_defs::builtin::{DEAD_CODE, DEAD_CODE_PUB_IN_BINARY}; use rustc_lint_defs::{self as lint, Lint, StableLintExpectationId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -691,7 +691,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { type Result = ControlFlow; - fn visit_nested_body(&mut self, body: hir::BodyId) -> Self::Result { + fn visit_fn_decl(&mut self, decl: &'tcx FnDecl<'tcx>) -> Self::Result { + if !decl.fn_has_body { + intravisit::walk_fn_decl(self, decl)?; + } + ControlFlow::Continue(()) + } + + fn visit_nested_body(&mut self, body: BodyId) -> Self::Result { let typeck_results = self.tcx.typeck_body(body); // The result shouldn't be tainted, otherwise it will cause ICE. @@ -700,6 +707,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } let old_maybe_typeck_results = self.maybe_typeck_results.replace(typeck_results); + if let Some(decl) = self.tcx.hir_fn_decl_by_hir_id(self.tcx.hir_body_owner(body)) { + intravisit::walk_fn_decl(self, decl)?; + } let body = self.tcx.hir_body(body); let result = self.visit_body(body); self.maybe_typeck_results = old_maybe_typeck_results; diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index d8524efb35bc2..36a8c847a7ba0 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -412,6 +412,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Pat, FieldOf, View, + CVarArgs, Err ] ); diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 88f202919bb59..f9552d24b44d3 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -16,9 +16,11 @@ pub(crate) fn provide(providers: &mut Providers) { } let local_def_id = def_id.expect_local(); + let fn_decl = tcx.hir_fn_decl_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id))?; let body = tcx.hir_maybe_body_owned_by(local_def_id)?; let mut local_collector = LocalCollector::default(); + local_collector.visit_fn_decl(fn_decl); local_collector.visit_body(&body); let mut capture_collector = CaptureCollector { @@ -26,6 +28,7 @@ pub(crate) fn provide(providers: &mut Providers) { locals: &local_collector.locals, upvars: FxIndexMap::default(), }; + capture_collector.visit_fn_decl(fn_decl); capture_collector.visit_body(&body); if !capture_collector.upvars.is_empty() { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 16a2ee9f22eaf..00e4e09adcfe5 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -24,7 +24,7 @@ use rustc_errors::{MultiSpan, listify}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, InferKind, Visitor}; -use rustc_hir::{self as hir, AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind}; +use rustc_hir::{self as hir, AmbigArg, FnDecl, ForeignItemId, ItemId, OwnerId, PatKind}; use rustc_lint_defs::builtin::{ EXPORTED_PRIVATE_DEPENDENCIES, PRIVATE_BOUNDS, PRIVATE_INTERFACES, UNNAMEABLE_TYPES, }; @@ -1046,6 +1046,8 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { } impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { + fn visit_fn_decl(&mut self, _fd: &'tcx FnDecl<'tcx>) -> Self::Result {} + fn visit_nested_body(&mut self, body_id: hir::BodyId) { let new_typeck_results = self.tcx.typeck_body(body_id); // Do not try reporting privacy violations if we failed to infer types. @@ -1171,9 +1173,18 @@ impl<'tcx> rustc_ty_walk::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> } impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { + fn visit_fn_decl(&mut self, _fd: &'tcx FnDecl<'tcx>) -> Self::Result { + // Handled in `visit_nested_body` + } + fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id)); + if let Some(decl) = self.tcx.hir_fn_decl_by_hir_id(self.tcx.hir_body_owner(body_id)) { + for param in decl.inputs { + self.visit_pat(param.pat); + } + } self.visit_body(self.tcx.hir_body(body_id)); self.maybe_typeck_results = old_maybe_typeck_results; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index e4cf2a40bd3fc..843b04ca65bae 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -8,7 +8,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource, PatKind, + self as hir, Closure, Expr, ExprKind, FnDecl, FnRetTy, HirId, LetStmt, LocalSource, PatKind, }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind}; @@ -1380,11 +1380,11 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { /// For closures, we first visit the parameters and then the content, /// as we prefer those. - fn visit_body(&mut self, body: &Body<'tcx>) { - for param in body.params { + fn visit_fn_decl(&mut self, decl: &'tcx FnDecl<'tcx>) { + for param in decl.inputs { debug!( "param: span {:?}, ty_span {:?}, pat.span {:?}", - param.span, param.ty_span, param.pat.span + param.param_span, param.ty_span, param.pat.span ); if param.ty_span != param.pat.span { debug!("skipping param: has explicit type"); @@ -1404,7 +1404,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { }) } } - intravisit::walk_body(self, body); + intravisit::walk_fn_decl(self, decl); } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 7079dd39fe64d..4fbe24364817d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -35,7 +35,7 @@ pub fn find_anon_type<'tcx>( .decl .inputs .iter() - .find_map(|arg| find_component_for_bound_region(tcx, arg, anon_reg.region_def_id)) + .find_map(|param| find_component_for_bound_region(tcx, param.ty, anon_reg.region_def_id)) .map(|ty| (ty, fn_sig)) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index fecf41c84a0e2..76462cf6f4f21 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -464,12 +464,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) = self.tcx().hir_node_by_def_id(local_def_id) { - let body = self.tcx().hir_body(closure.body); // For Fn traits, args[1] is the tupled input types (e.g. `(&mut [u8],)`). let expected_input_tys = expected_args.type_at(1); if let ty::Tuple(input_tys) = *expected_input_tys.kind() { - let suggestions: Vec<_> = body - .params + let suggestions: Vec<_> = closure + .fn_decl + .inputs .iter() .zip(input_tys.iter()) .filter_map(|(param, ty)| { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index c51016e779c4b..0b7942610603a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -64,20 +64,19 @@ pub fn find_param_with_region<'tcx>( _ => {} } - let body = tcx.hir_maybe_body_owned_by(def_id)?; - - let owner_id = tcx.hir_body_owner(body.id()); + let owner_id = tcx.local_def_id_to_hir_id(def_id); let fn_decl = tcx.hir_fn_decl_by_hir_id(owner_id)?; let poly_fn_sig = tcx.fn_sig(id).instantiate_identity().skip_norm_wip(); let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig); - body.params + fn_decl + .inputs .iter() .take(if fn_sig.c_variadic() { fn_sig.inputs().len() } else { - assert_eq!(fn_sig.inputs().len(), body.params.len()); - body.params.len() + assert_eq!(fn_sig.inputs().len(), fn_decl.inputs.len()); + fn_decl.inputs.len() }) .enumerate() .find_map(|(index, param)| { @@ -93,7 +92,7 @@ pub fn find_param_with_region<'tcx>( } }); found_anon_region.then(|| { - let ty_hir_id = fn_decl.inputs[index].hir_id; + let ty_hir_id = fn_decl.inputs[index].ty.hir_id; let param_ty_span = tcx.hir_span(ty_hir_id); let is_first = index == 0; AnonymousParamInfo { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 4ccc7ab986f1e..561ea43272943 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -726,13 +726,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { // 0. Extract fn_decl from hir let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }), + kind: hir::ExprKind::Closure(hir::Closure { fn_decl, .. }), .. }) = hir else { return; }; - let hir::Body { params, .. } = self.tcx.hir_body(*body); // 1. Get the args of the closure. // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1]. @@ -755,8 +754,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let mut is_first = true; let mut has_suggestion = false; - for (((expected, found), param_hir), arg_hir) in - expected.iter().zip(found.iter()).zip(params.iter()).zip(fn_decl.inputs.iter()) + for ((expected, found), param_hir) in + expected.iter().zip(found.iter()).zip(fn_decl.inputs.iter()) { if is_first { is_first = false; @@ -768,7 +767,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let ty::Ref(found_region, _, _) = found.kind() && expected_region.is_bound() && !found_region.is_bound() - && let hir::TyKind::Infer(()) = arg_hir.kind + && let hir::TyKind::Infer(()) = param_hir.ty.kind { // If the expected region is late bound, the found region is not, and users are asking compiler // to infer the type, we can suggest adding `: &_`. @@ -795,7 +794,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } has_suggestion = true; } else { - let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.span) else { + let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.param_span) + else { return; }; // Otherwise, keep it as-is. @@ -951,19 +951,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pat.walk(&mut find_compatible_candidates); } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { body, .. }, .. }) + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { sig: hir::FnSig { decl, .. }, .. }, + .. + }) | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(_, body), .. + kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, _), + .. }) | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)), + kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, _), .. }) | hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { body, .. }), + kind: hir::ExprKind::Closure(hir::Closure { fn_decl: decl, .. }), .. }) => { - for param in self.tcx.hir_body(*body).params { + for param in decl.inputs { param.pat.walk(&mut find_compatible_candidates); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 1614899ece03d..f2537c7379c0b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3819,17 +3819,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let sm = self.tcx.sess.source_map(); Some(match node { Node::Expr(&hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }), + kind: + hir::ExprKind::Closure(&hir::Closure { fn_decl, fn_decl_span, fn_arg_span, .. }), .. }) => ( fn_decl_span, fn_arg_span, - self.tcx - .hir_body(body) - .params + fn_decl + .inputs .iter() - .map(|arg| { - if let hir::Pat { kind: hir::PatKind::Tuple(args, _), span, .. } = *arg.pat + .map(|param| { + if let hir::Pat { kind: hir::PatKind::Tuple(args, _), span, .. } = + *param.pat { Some(ArgKind::Tuple( Some(span), @@ -3842,7 +3843,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .collect::>>()?, )) } else { - let name = sm.span_to_snippet(arg.pat.span).ok()?; + let name = sm.span_to_snippet(param.pat.span).ok()?; Some(ArgKind::Arg(name, "_".to_owned())) } }) @@ -3862,9 +3863,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sig.decl .inputs .iter() - .map(|arg| match arg.kind { + .map(|param| match param.ty.kind { hir::TyKind::Tup(tys) => ArgKind::Tuple( - Some(arg.span), + Some(param.ty.span), vec![("_".to_owned(), "_".to_owned()); tys.len()], ), _ => ArgKind::empty(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 1a661270a5d5d..91c029858c5ef 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -862,8 +862,9 @@ fn attempt_dyn_to_impl_suggestion(tcx: TyCtxt<'_>, hir_id: Option, e // This ensures that we don't suggest converting e.g. // `type Alias = Box;` to // `type Alias = Box;` - let Some((_id, first_non_type_parent_node)) = - tcx.hir_parent_iter(hir_id).find(|(_id, node)| !matches!(node, hir::Node::Ty(_))) + let Some((_id, first_non_type_parent_node)) = tcx + .hir_parent_iter(hir_id) + .find(|(_id, node)| !matches!(node, hir::Node::Ty(_) | hir::Node::Param(_))) else { return; }; 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 a2aae724228ba..aecacf4f63692 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -182,7 +182,7 @@ pub fn suggest_restriction<'tcx>( let mut ty_spans = vec![]; for input in fn_sig.decl.inputs { ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id } - .visit_ty_unambig(input); + .visit_ty_unambig(input.ty); } // The type param `T: Trait` we will suggest to introduce. let type_param = format!("{type_param_name}: {bound_str}"); @@ -2312,11 +2312,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// Suggest removing `&` from a function parameter type like `&impl Future`. fn suggest_remove_ref_from_param(&self, param: &hir::Param<'_>, err: &mut Diag<'_>) -> bool { - if let Some(decl) = self.tcx.parent_hir_node(param.hir_id).fn_decl() - && let Some(input_ty) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) - && let hir::TyKind::Ref(_, ty, _) = input_ty.kind - { - let ref_span = input_ty.span.until(ty.span); + if let hir::TyKind::Ref(_, ty, _) = param.ty.kind { + let ref_span = param.ty.span.until(ty.span); match self.tcx.sess.source_map().span_to_snippet(ref_span) { Ok(snippet) if snippet.starts_with("&") => { err.span_suggestion_verbose( @@ -4238,17 +4235,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { types always have a known size"; if let Some(hir_id) = hir_id && let hir::Node::Param(param) = self.tcx.hir_node(hir_id) - && let Some(decl) = self.tcx.parent_hir_node(hir_id).fn_decl() - && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) { - // We use `contains` because the type might be surrounded by parentheses, - // which makes `ty_span` and `t.span` disagree with each other, but one - // fully contains the other: `foo: (dyn Foo + Bar)` - // ^-------------^ - // || - // |t.span - // param._ty_span - ty = Some(t); + ty = Some(param.ty); } else if let Some(hir_id) = hir_id && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id) { @@ -4268,13 +4256,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let needs_parens = traits.len() != 1; // Don't recommend impl Trait as a closure argument if let Some(hir_id) = hir_id - && matches!( + && (matches!( self.tcx.parent_hir_node(hir_id), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. }) - ) + ) || matches!( + self.tcx.parent_hir_node(hir_id), + hir::Node::Param(_) + ) && matches!( + self.tcx.parent_hir_node(self.tcx.parent_hir_id(hir_id)), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { .. }, + .. + }) + )) { err.span_suggestion_verbose( span, @@ -6823,7 +6820,7 @@ fn hint_missing_borrow<'tcx>( let mut to_borrow = Vec::new(); let mut remove_borrow = Vec::new(); - for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) { + for ((found_arg, expected_arg), param) in found_args.zip(expected_args).zip(args) { let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg); let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg); @@ -6833,7 +6830,7 @@ fn hint_missing_borrow<'tcx>( && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..] { to_borrow.push(( - arg.span.shrink_to_lo(), + param.ty.span.shrink_to_lo(), expected_refs[..expected_refs.len() - found_refs.len()] .iter() .map(|mutbl| format!("&{}", mutbl.prefix_str())) @@ -6841,9 +6838,9 @@ fn hint_missing_borrow<'tcx>( .join(""), )); } else if found_refs.len() > expected_refs.len() { - let mut span = arg.span.shrink_to_lo(); + let mut span = param.ty.span.shrink_to_lo(); let mut left = found_refs.len() - expected_refs.len(); - let mut ty = arg; + let mut ty = param.ty; while let hir::TyKind::Ref(_, inner_ty, _) = &ty.kind && left > 0 { diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 0cc886a2c1909..97d96ab784ba7 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -483,7 +483,7 @@ fn virtual_call_violations_for_method<'tcx>( .. })) = tcx.hir_get_if_local(method.def_id).as_ref() { - Some(sig.decl.inputs[i].span) + Some(sig.decl.inputs[i].ty.span) } else { None }; @@ -525,7 +525,7 @@ fn virtual_call_violations_for_method<'tcx>( })) = tcx.hir_get_if_local(method.def_id).as_ref() { // If we have `self: &'a Ty`, get `'a`, so that we can suggest `&'a self`. - let lt = match sig.decl.inputs[0].kind { + let lt = match sig.decl.inputs[0].ty.kind { hir::TyKind::Ref(lt, ..) if lt.ident.name == kw::UnderscoreLifetime => { sym::empty } @@ -535,16 +535,15 @@ fn virtual_call_violations_for_method<'tcx>( // Get the `Span` for all of `self: Ty`, not just `Ty`. match trait_fn { hir::TraitFn::Required([Some(name), ..]) - if name.span.eq_ctxt(sig.decl.inputs[0].span) => + if name.span.eq_ctxt(sig.decl.inputs[0].ty.span) => { - Some(name.span.to(sig.decl.inputs[0].span)) + Some(name.span.to(sig.decl.inputs[0].ty.span)) } - hir::TraitFn::Provided(body_id) - if let body = tcx.hir_body(*body_id) - && let Some(p) = body.params.get(0) - && p.span.eq_ctxt(p.ty_span) => + hir::TraitFn::Provided(_body_id) + if let Some(p) = sig.decl.inputs.get(0) + && p.param_span.eq_ctxt(p.ty_span) => { - Some(p.span.to(p.ty_span)) + Some(p.param_span.to(p.ty_span)) } _ => None, } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 88d08aa355407..2076720591d40 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -162,7 +162,11 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator { let node = tcx.hir_node_by_def_id(def_id); if let Some(decl) = node.fn_decl() { - decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span())) + decl.inputs + .iter() + .filter(|param| !matches!(param.ty.kind, hir::TyKind::CVarArgs)) + .map(|param| param.ty.span) + .chain(iter::once(decl.output.span())) } else { bug!("unexpected item for fn {def_id:?}: {node:?}") } diff --git a/compiler/rustc_ty_walk/src/lib.rs b/compiler/rustc_ty_walk/src/lib.rs index 0ca1b06f05e3b..0d9ea5fb907a8 100644 --- a/compiler/rustc_ty_walk/src/lib.rs +++ b/compiler/rustc_ty_walk/src/lib.rs @@ -56,7 +56,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Walk over the inputs and outputs manually in order to get good spans for them. try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output())); for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { - try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x))); + try_visit!(visitor.visit(hir.ty.span, ty.map_bound(|x| *x))); } for (clause, span) in tcx.explicit_clauses_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, clause.skip_norm_wip())); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e03a0b13f79f..85cee5eb427c0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1087,7 +1087,6 @@ fn clean_fn_or_proc_macro<'tcx>( item: &hir::Item<'tcx>, sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'tcx>, - body_id: hir::BodyId, name: &mut Symbol, cx: &mut DocContext<'tcx>, ) -> ItemKind { @@ -1105,13 +1104,8 @@ fn clean_fn_or_proc_macro<'tcx>( match macro_kind { Some(kind) => clean_proc_macro(item, name, kind, cx.tcx), None => { - let mut func = clean_function( - cx, - sig, - generics, - ParamsSrc::Body(body_id), - item.owner_id.to_def_id(), - ); + let mut func = + clean_function(cx, sig, generics, ParamsSrc::Body, item.owner_id.to_def_id()); clean_fn_decl_legacy_const_generics(&mut func, attrs); FunctionItem(func) } @@ -1141,7 +1135,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[rustc_attr_ } enum ParamsSrc<'tcx> { - Body(hir::BodyId), + Body, Idents(&'tcx [Option]), } @@ -1166,7 +1160,7 @@ fn clean_function<'tcx>( clean_poly_fn_sig(cx, Some(def_id), sig) } else { let params = match params { - ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl, body_id), + ParamsSrc::Body => clean_params_via_body(cx, sig.decl), // Let's not perpetuate anon params from Rust 2015; use `_` for them. ParamsSrc::Idents(idents) => clean_params(cx, sig.decl, idents, |ident| { Some(ident.map_or(kw::Underscore, |ident| ident.name)) @@ -1187,10 +1181,11 @@ fn clean_params<'tcx>( ) -> Vec { decl.inputs .iter() + .filter(|param| !matches!(param.ty.kind, hir::TyKind::CVarArgs)) .enumerate() - .map(|(i, ty)| Parameter { + .map(|(i, param)| Parameter { name: postprocess(idents[i]), - type_: clean_ty(ty, cx), + type_: clean_ty(param.ty, cx), is_const: false, is_splat: decl.splatted().is_some_and(|j| j as usize == i), }) @@ -1200,15 +1195,13 @@ fn clean_params<'tcx>( fn clean_params_via_body<'tcx>( cx: &mut DocContext<'tcx>, decl: &hir::FnDecl<'tcx>, - body_id: hir::BodyId, ) -> Vec { decl.inputs .iter() - .zip(cx.tcx.hir_body(body_id).params) .enumerate() - .map(|(i, (ty, param))| Parameter { + .map(|(i, param)| Parameter { name: Some(name_from_pat(param.pat)), - type_: clean_ty(ty, cx), + type_: clean_ty(param.ty, cx), is_const: false, is_splat: decl.splatted().is_some_and(|j| j as usize == i), }) @@ -1309,9 +1302,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - let m = - clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body), local_did); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(_)) => { + let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body, local_did); MethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => { @@ -1361,8 +1353,8 @@ pub(crate) fn clean_impl_item<'tcx>( kind: clean_const_item_rhs(expr, local_did), type_: clean_ty(ty, cx), })), - hir::ImplItemKind::Fn(ref sig, body) => { - let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body), local_did); + hir::ImplItemKind::Fn(ref sig, _) => { + let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body, local_did); let defaultness = match impl_.impl_kind { hir::ImplItemImplKind::Inherent { .. } => hir::Defaultness::Final, hir::ImplItemImplKind::Trait { defaultness, .. } => defaultness, @@ -2001,6 +1993,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'_>, cx: &mut DocContext<'tcx>) -> Typ // FIXME(scrabsha): propagate view types to `rustdoc`. clean_ty(ty, cx) } + TyKind::CVarArgs => unreachable!("Var args should be filtered out before reaching this"), // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. TyKind::Infer(()) | TyKind::Err(_) @@ -3032,8 +3025,8 @@ fn clean_maybe_renamed_item<'tcx>( ), }, // proc macros can have a name set by attributes - ItemKind::Fn { ref sig, generics, body: body_id, .. } => { - clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) + ItemKind::Fn { ref sig, generics, .. } => { + clean_fn_or_proc_macro(item, sig, generics, &mut name, cx) } // FIXME: rustdoc will need to handle `impl` restrictions at some point ItemKind::Trait { generics, bounds, items: item_ids, .. } => { diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index b2c21377a0a3f..73c1ee71c670f 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -453,10 +453,11 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: Msrv, expr: &Expr<'_>) -> Optio }, ExprKind::Closure(closure) => { let body = cx.tcx.hir_body(closure.body); - let params = body - .params + let params = closure + .fn_decl + .inputs .iter() - .map(|param| param.span.get_text(cx).map(|t| t.to_string())) + .map(|param| param.param_span.get_text(cx).map(|t| t.to_string())) .collect::>>()? .join(", "); let negated = simplify_not(cx, curr_msrv, body.value)?; diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs index 099100bf9d1f6..a7ca1f01ac72f 100644 --- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs +++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs @@ -118,7 +118,8 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI let is_read_in_closure_arg = args.iter().any(|arg| { if let ExprKind::Closure(closure) = arg.kind // To keep things simple, we only check the first param to see if its read. - && let Body { params: [param, ..], value } = cx.tcx.hir_body(closure.body) + && let [param, ..] = closure.fn_decl.inputs + && let Body { value } = cx.tcx.hir_body(closure.body) { !has_no_read_access(cx, param.hir_id, *value) } else { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 6257ec51eb8da..4621f4a326a4c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -905,6 +905,7 @@ impl TyCoercionStability { Self::for_hir_ty(ty) }, TyKind::UnsafeBinder(..) => Self::None, + TyKind::CVarArgs => unreachable!(), }; } } diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 63c7855f5f4b1..0c4e7975a7bd9 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { &mut self, cx: &LateContext<'tcx>, fn_kind: intravisit::FnKind<'tcx>, - _: &'tcx FnDecl<'_>, + decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, _: Span, fn_def_id: LocalDefId, @@ -106,8 +106,8 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { // Seed the set with the `Box` parameters that could be unboxed. The `ExprUseVisitor` walk // below then removes any that escape by being moved or borrowed. - let set: HirIdSet = body - .params + let set: HirIdSet = decl + .inputs .iter() .filter_map(|param| { // Only simple bindings (`x: Box<_>`) bind a local that the walk can track and report. @@ -140,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { let mut v = EscapeDelegate { set }; ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v) - .consume_body(body) + .consume_body(decl, body) .into_ok(); for node in v.set { diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index e3674fcf0d0b6..cd404a635f887 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -88,18 +88,18 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { #[expect(clippy::too_many_lines)] fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx>>, expr: &Expr<'tcx>) { - let body = if let ExprKind::Closure(c) = expr.kind - && c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) + let (hir_closure, body) = if let ExprKind::Closure(c) = expr.kind + && c.fn_decl.inputs.iter().all(|param| matches!(param.ty.kind, TyKind::Infer(()))) && matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_)) && !expr.span.from_expansion() { - cx.tcx.hir_body(c.body) + (c, cx.tcx.hir_body(c.body)) } else { return; }; if body.value.span.from_expansion() { - if body.params.is_empty() + if hir_closure.fn_decl.inputs.is_empty() && let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) { let vec_crate = if is_no_std_crate(cx) { "alloc" } else { "std" }; @@ -145,7 +145,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx let callee_ty_raw = typeck.expr_ty(callee); let callee_ty = callee_ty_raw.peel_refs(); if matches!(callee_ty.opt_diag_name(cx), Some(sym::Arc | sym::Rc)) - || !check_inputs(typeck, body.params, None, args) + || !check_inputs(typeck, hir_closure.fn_decl.inputs, None, args) { return; } @@ -262,7 +262,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx ); } }, - ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => { + ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, hir_closure.fn_decl.inputs, Some(self_), args) => { if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id) && !find_attr!(cx.tcx, method_def_id, TrackCaller(..)) && check_sig(closure_sig, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder()) diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index a64f9db2fd88c..5ea0c2dbf5e61 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -131,7 +131,7 @@ fn has_n_bools<'tcx>(iter: impl Iterator>, mut count: u64) } fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) { - if has_n_bools(decl.inputs.iter(), max) && !sp.from_expansion() { + if has_n_bools(decl.inputs.iter().map(|p| p.ty), max) && !sp.from_expansion() { span_lint_and_help( cx, FN_PARAMS_EXCESSIVE_BOOLS, diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs index 38661ebf5eb83..b9204b813d087 100644 --- a/src/tools/clippy/clippy_lints/src/format_impl.rs +++ b/src/tools/clippy/clippy_lints/src/format_impl.rs @@ -256,7 +256,7 @@ impl FormatImplExpr<'_, '_> { fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option { if impl_item.ident.name == sym::fmt - && let ImplItemKind::Fn(_, body_id) = impl_item.kind + && let ImplItemKind::Fn(sig, _) = impl_item.kind && let Some(Impl { of_trait: Some(of_trait), .. @@ -265,9 +265,9 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio && let Some(name) = cx.tcx.get_diagnostic_name(did) && matches!(name, sym::Debug | sym::Display) { - let body = cx.tcx.hir_body(body_id); - let formatter_name = body - .params + let formatter_name = sig + .decl + .inputs .get(1) .and_then(|param| param.pat.simple_ident()) .map(|ident| ident.name); diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index ed936e7f14aec..00c02bc6db93e 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -193,8 +193,7 @@ fn convert_to_from( let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind else { return None; }; - let body = cx.tcx.hir_body(body_id); - let [self_param] = body.params else { return None }; + let [self_param] = sig.decl.inputs else { return None }; let PatKind::Binding(.., self_ident, None) = self_param.pat.kind else { return None; }; @@ -232,6 +231,7 @@ fn convert_to_from( lower: Vec::new(), }; + let body = cx.tcx.hir_body(body_id); if finder.visit_expr(body.value).is_break() { return None; } diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 4cb798c67a7d2..2a742718ecb69 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -244,7 +244,7 @@ fn check_must_use_candidate<'tcx>( item_id: hir::OwnerId, msg: &'static str, ) { - if has_mutable_arg(cx, body) + if has_mutable_arg(cx, decl) || mutates_static(cx, body) || returns_unit(decl) || !cx.effective_visibilities.is_exported(item_id.def_id) @@ -281,9 +281,9 @@ fn returns_unit(decl: &hir::FnDecl<'_>) -> bool { } } -fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool { +fn has_mutable_arg(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>,) -> bool { let mut tys = DefIdSet::default(); - body.params.iter().any(|param| is_mutable_pat(cx, param.pat, &mut tys)) + decl.inputs.iter().any(|param| is_mutable_pat(cx, param.pat, &mut tys)) } fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 7555a6719b6de..f1680f94ab17a 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -44,7 +44,7 @@ fn check_raw_ptr<'tcx>( def_id: LocalDefId, ) { if safety.is_safe() && cx.effective_visibilities.is_exported(def_id) { - let raw_ptrs = iter_input_pats(decl, body) + let raw_ptrs = iter_input_pats(decl) .filter_map(|arg| raw_ptr_arg(cx, arg)) .collect::(); diff --git a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs index 733f10b3506f8..2e17752f8985e 100644 --- a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs +++ b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs @@ -43,7 +43,7 @@ fn check_fn_sig<'a>(cx: &LateContext<'a>, decl: &FnDecl<'a>, span: Span, sig: ty let mut fixes = Vec::new(); // Check function arguments' types for (param, param_ty) in decl.inputs.iter().zip(sig.inputs()) { - check_ty(cx, param, *param_ty, &mut fixes); + check_ty(cx, param.ty, *param_ty, &mut fixes); } // Check return type if let hir::FnRetTy::Return(ty) = &decl.output { @@ -89,7 +89,7 @@ pub(crate) fn check_fn<'a>( span.with_hi(out_ty.span.hi()) } } else if let (Some(first), Some(last)) = (decl.inputs.first(), decl.inputs.last()) { - first.span.to(last.span) + first.ty.span.to(last.ty.span) } else { // No parameters - no point in checking return; diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs index 2d330835a037a..baa26e7a4d7a3 100644 --- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs @@ -11,7 +11,7 @@ use super::RENAMED_FUNCTION_PARAMS; pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored_traits: &DefIdSet) { if !item.span.from_expansion() - && let ImplItemKind::Fn(_, body_id) = item.kind + && let ImplItemKind::Fn(sig, _) = item.kind && let parent_node = cx.tcx.parent_hir_node(item.hir_id()) && let Node::Item(parent_item) = parent_node && let ItemKind::Impl(Impl { @@ -21,7 +21,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored && let Some(did) = cx.tcx.trait_item_of(item.owner_id) && !is_from_ignored_trait(&of_trait.trait_ref, ignored_traits) { - let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id); + let mut param_idents_iter = cx.tcx.hir_body_param_idents(sig.decl); let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied(); let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index ea443487df9ba..605d6503167ed 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -155,9 +155,9 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } => { let body = cx.tcx.hir_body(body_id); - for ty in sig.decl.inputs { + for param in sig.decl.inputs { let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty_unambig(ty); + vis.visit_ty_unambig(param.ty); for target in &vis.found { if generics.span.from_expansion() { @@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } let generics_suggestion_span = generics.span.substitute_dummy({ let range = - (item.span.lo()..body.params[0].pat.span.lo()).map_range(cx, |_, src, range| { + (item.span.lo()..sig.decl.inputs[0].pat.span.lo()).map_range(cx, |_, src, range| { let (pre, post) = src.get(range.clone())?.split_once("fn")?; let pos = post.find('(')? + pre.len() + 2; Some(pos..pos) diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 408d78ae623c0..b46656ff5eee2 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -313,7 +313,7 @@ fn could_use_elision<'tcx>( // extract lifetimes in input argument types for arg in func.inputs { - input_visitor.visit_ty_unambig(arg); + input_visitor.visit_ty_unambig(arg.ty); } // extract lifetimes in output type if let Return(ty) = func.output { @@ -337,14 +337,13 @@ fn could_use_elision<'tcx>( } if let Some(body_id) = body { - let body = cx.tcx.hir_body(body_id); - - let first_ident = body.params.first().and_then(|param| param.pat.simple_ident()); + let first_ident = func.inputs.first().and_then(|param| param.pat.simple_ident()); if non_elidable_self_type(cx, func, first_ident, msrv) { return None; } let mut checker = BodyLifetimeChecker::new(cx); + let body = cx.tcx.hir_body(body_id); if checker.visit_expr(body.value).is_break() { return None; } @@ -418,11 +417,11 @@ fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ide if let Some(ident) = ident && ident.name == kw::SelfLower && !func.implicit_self().has_implicit_self() - && let Some(self_ty) = func.inputs.first() + && let Some(self_param) = func.inputs.first() && !msrv.meets(cx, msrvs::EXPLICIT_SELF_TYPE_ELISION) { let mut visitor = RefVisitor::new(cx); - visitor.visit_ty_unambig(self_ty); + visitor.visit_ty_unambig(self_param.ty); !visitor.all_lts().is_empty() } else { @@ -702,7 +701,7 @@ fn is_candidate_for_elision(fd: &FnDecl<'_>) -> bool { // The first encountered input lifetime will either be one on `self`, or will be the only lifetime. fd.inputs .iter() - .find_map(|ty| walk_unambig_ty(&mut V, ty).break_value()) + .find_map(|param| walk_unambig_ty(&mut V, param.ty).break_value()) .unwrap() } else { false diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs index 3d46991d1c224..3ecf3245f4cfa 100644 --- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs @@ -64,22 +64,21 @@ pub(super) fn check_method<'tcx>( arg: &'tcx Expr<'tcx>, closure: &'tcx Closure<'tcx>, ) { - let body = cx.tcx.hir_body(closure.body); - if let [param] = body.params - && let [input] = closure.fn_decl.inputs + if let [param] = closure.fn_decl.inputs && !arg.span.from_expansion() - && !input.span.from_expansion() + && !param.ty.span.from_expansion() && !recv.span.from_expansion() - && !param.span.from_expansion() + && !param.param_span.from_expansion() { - let ty_spans = if let TyKind::Tup([_, inner]) = input.kind { + let ty_spans = if let TyKind::Tup([_, inner]) = param.ty.kind { let Some(inner) = walk_span_to_context(inner.span, SyntaxContext::root()) else { return; }; - Some((input.span, inner)) + Some((param.ty.span, inner)) } else { None }; + let body = cx.tcx.hir_body(closure.body); check(cx, recv, param.pat, ty_spans, body.value); } } diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index a20e2f1d44c10..8d9a45f2bf4ed 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -136,9 +136,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { fn get_ty_sugg<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'_>) -> Option<(Span, Ty<'tcx>)> { let local_hid = arg.res_local_id()?; - if let Node::Param(Param { ty_span, span, .. }) = cx.tcx.parent_hir_node(local_hid) + if let Node::Param(Param { ty_span, param_span, .. }) = cx.tcx.parent_hir_node(local_hid) // `ty_span` and `span` are the same for inferred type, thus a type suggestion must be given - && ty_span == span + && ty_span == param_span { let arg_type = cx.typeck_results().expr_ty(arg); return Some((*ty_span, arg_type)); diff --git a/src/tools/clippy/clippy_lints/src/manual_pop_if.rs b/src/tools/clippy/clippy_lints/src/manual_pop_if.rs index afafe25f8ffd0..625ef763bc7af 100644 --- a/src/tools/clippy/clippy_lints/src/manual_pop_if.rs +++ b/src/tools/clippy/clippy_lints/src/manual_pop_if.rs @@ -210,12 +210,12 @@ fn check_is_some_and_pattern<'tcx>( && check_path.ident.name == peek_method && kind.is_diag_item(cx, collection_expr) && let ExprKind::Closure(closure) = closure_arg.kind - && let body = cx.tcx.hir_body(closure.body) && let Some((pop_collection, pop_span, suggestable)) = check_pop_unwrap(cx, then_block, pop_method) && eq_expr_value(cx, if_expr_span.ctxt(), collection_expr, pop_collection) - && let Some(param) = body.params.first() + && let Some(param) = closure.fn_decl.inputs.first() && let Some(ident) = param.pat.simple_ident() { + let body = cx.tcx.hir_body(closure.body); return Some(ManualPopIfPattern { kind, collection_expr, @@ -373,7 +373,7 @@ fn check_map_unwrap_or_pattern<'tcx>( && cx.typeck_results().expr_ty(body.value).is_bool() && let Some((pop_collection, pop_span, suggestable)) = check_pop_unwrap(cx, then_block, pop_method) && eq_expr_value(cx, if_expr_span.ctxt(), collection_expr, pop_collection) - && let Some(param) = body.params.first() + && let Some(param) = closure.fn_decl.inputs.first() && let Some(ident) = param.pat.simple_ident() { return Some(ManualPopIfPattern { diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index d00d91be2fbde..47e4d9a200b26 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -89,7 +89,7 @@ fn check_into_iter( && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = target_expr.kind && let hir::ExprKind::Closure(closure) = closure_expr.kind && let filter_body = cx.tcx.hir_body(closure.body) - && let [filter_params] = filter_body.params + && let [filter_params] = closure.fn_decl.inputs { if match_map_type(cx, left_expr) { if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind @@ -136,7 +136,7 @@ fn check_iter( && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind && let hir::ExprKind::Closure(closure) = closure_expr.kind && let filter_body = cx.tcx.hir_body(closure.body) - && let [filter_params] = filter_body.params + && let [filter_params] = closure.fn_decl.inputs { match filter_params.pat.kind { // hir::PatKind::Binding(_, _, _, None) => { @@ -194,7 +194,7 @@ fn check_to_owned( && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind && let hir::ExprKind::Closure(closure) = closure_expr.kind && let filter_body = cx.tcx.hir_body(closure.body) - && let [filter_params] = filter_body.params + && let [filter_params] = closure.fn_decl.inputs && msrv.meets(cx, msrvs::STRING_RETAIN) && let hir::PatKind::Ref(pat, _, _) = filter_params.pat.kind { diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 9187cb6fc98c2..78c294b323574 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -161,16 +161,16 @@ fn reduce_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option< } } -fn unit_closure<'tcx>( - cx: &LateContext<'tcx>, - expr: &hir::Expr<'_>, -) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> { +fn unit_closure<'a, 'b>( + cx: &LateContext<'a>, + expr: &hir::Expr<'b>, +) -> Option<(&'b hir::Param<'b>, &'a hir::Expr<'a>)> { if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind && let body = cx.tcx.hir_body(body) && let body_expr = &body.value && fn_decl.inputs.len() == 1 && is_unit_expression(cx, body_expr) - && let Some(binding) = iter_input_pats(fn_decl, body).next() + && let Some(binding) = iter_input_pats(fn_decl).next() { return Some((binding, body_expr)); } diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs index 94a2910cef3b9..34613521ed59d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs @@ -104,7 +104,7 @@ pub(crate) fn check_and_then_method<'tcx>( && let ExprKind::Closure(closure) = arg.kind && let body = cx.tcx.hir_body(closure.body) && let Some(fn_arg_span) = closure.fn_arg_span - && let [param] = body.params + && let [param] = closure.fn_decl.inputs && let expr_span_ctxt = expr.span.ctxt() && let Some(some_expr) = get_cond_expr(cx, param.pat, body.value, expr_span_ctxt) { diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index 2a15d732939c3..a792a6964396d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -222,7 +222,7 @@ impl<'tcx> Visitor<'tcx> for VarBindingVisitor<'_, 'tcx> { ExprKind::Closure(closure) => { let body = self.cx.tcx.hir_body(closure.body); let before = self.identifiers.clone(); - for param in body.params { + for param in closure.fn_decl.inputs { param.pat.each_binding(|_, _, _, ident| { self.identifiers.remove(&ident.name); }); diff --git a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs index 2a81abac4896a..61efb0cbd2456 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs @@ -16,9 +16,9 @@ pub(super) fn check<'tcx>( filter_recv: &'tcx Expr<'_>, filter_arg: &'tcx Expr<'_>, ) { - if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind + if let ExprKind::Closure(&Closure { fn_decl, body, .. }) = filter_arg.kind && let body = cx.tcx.hir_body(body) - && let [param] = body.params + && let [param] = fn_decl.inputs && let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind && let ExprKind::Binary(ref op, l, r) = body.value.kind && op.node == BinOpKind::Eq diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index f42b73fce6bdc..0545ab5b9b318 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -21,7 +21,7 @@ fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, ExprKind::Path(QPath::Resolved(_, segments)) => segments.segments.last().unwrap().ident.name == method_name, ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, - ExprKind::Closure(Closure { body, .. }) => { + ExprKind::Closure(Closure { fn_decl, body, .. }) => { let body = cx.tcx.hir_body(*body); let closure_expr = peel_blocks(body.value); match closure_expr.kind { @@ -29,9 +29,9 @@ fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool if ident.name == method_name && let ExprKind::Path(path) = &receiver.kind && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id) - && !body.params.is_empty() + && !fn_decl.inputs.is_empty() { - let arg_id = body.params[0].pat.hir_id; + let arg_id = fn_decl.inputs[0].pat.hir_id; return arg_id == *local; } false @@ -407,9 +407,9 @@ fn is_find_or_filter<'a>( ) -> Option<(Ident, CheckResult<'a>)> { if cx.ty_based_def(map_recv).opt_parent(cx).is_diag_item(cx, sym::Iterator) // filter(|x| ...is_some())... - && let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind + && let ExprKind::Closure(&Closure { fn_decl, body: filter_body_id, .. }) = filter_arg.kind && let filter_body = cx.tcx.hir_body(filter_body_id) - && let [filter_param] = filter_body.params + && let [filter_param] = fn_decl.inputs // optional ref pattern: `filter(|&x| ..)` && let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _, _) = filter_param.pat.kind { (ref_pat, true) @@ -420,9 +420,9 @@ fn is_find_or_filter<'a>( && let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind && let Some(offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id) - && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind + && let ExprKind::Closure(&Closure { fn_decl, body: map_body_id, .. }) = map_arg.kind && let map_body = cx.tcx.hir_body(map_body_id) - && let [map_param] = map_body.params + && let [map_param] = fn_decl.inputs && let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind && let Some(check_result) = diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index 00c7ca82d10dd..e021c581c26e5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -13,20 +13,19 @@ use rustc_middle::ty::Binder; use rustc_middle::ty::adjustment::Adjust; use rustc_span::Span; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &Expr<'_>, call_span: Span) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &'tcx Expr<'tcx>, call_span: Span) { if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator) && let ExprKind::Closure(closure) = arg.kind && let body = cx.tcx.hir_body(closure.body) && let value = peel_blocks(body.value) // Indexing should be fine as `filter_map` always has 1 input, we unfortunately need both // `inputs` and `params` here as we need both the type and the span - && let param_ty = closure.fn_decl.inputs[0] - && let param = body.params[0] + && let param = closure.fn_decl.inputs[0] // Issue #11309 && let param_ty = cx.tcx.liberate_late_bound_regions( closure.def_id.to_def_id(), Binder::bind_with_vars( - cx.typeck_results().node_type(param_ty.hir_id), + cx.typeck_results().node_type(param.ty.hir_id), cx.tcx.late_bound_vars(cx.tcx.local_def_id_to_hir_id(closure.def_id)), ), ) @@ -43,7 +42,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & .iter() .filter(|adj| matches!(adj.kind, Adjust::Deref(_))) .count() - && let Some(param_snippet) = param.span.get_text(cx) + && let Some(param_snippet) = param.param_span.get_text(cx) { let mut applicability = Applicability::MachineApplicable; let (filter, _) = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs index 1f5b48a6f78f2..e8b8a3b757641 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs @@ -94,10 +94,10 @@ fn is_method( } false }, - ExprKind::Closure(&hir::Closure { body, .. }) => { + ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) => { let body = cx.tcx.hir_body(body); let closure_expr = peel_blocks(body.value); - let params = body.params.iter().map(|param| param.pat).collect::>(); + let params = fn_decl.inputs.iter().map(|param| param.pat).collect::>(); is_method(cx, closure_expr, type_symbol, method_name, params.as_slice()) }, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs index f8a8277d82d71..a2173e0f08520 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs @@ -28,8 +28,8 @@ pub(super) fn check<'tcx>( } if !expr.span.from_expansion() && let ExprKind::Closure(c) = m_arg.kind + && let [p] = c.fn_decl.inputs && let Body { - params: [p], value: body_expr, } = cx.tcx.hir_body(c.body) && let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index 241791e57c8e6..12a51310ed92c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures; use core::ops::ControlFlow; use rustc_ast::BindingMode; use rustc_errors::Applicability; -use rustc_hir::{Body, CaptureBy, Closure, Expr, ExprKind, HirId, HirIdSet, Param, PatKind}; +use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, HirId, HirIdSet, Param, PatKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::LateContext; use rustc_middle::mir::{FakeReadCause, Mutability}; @@ -63,9 +63,10 @@ pub(super) fn check<'tcx>( let ExprKind::Closure(closure) = expr.kind else { return; }; - let body @ Body { params: [p], .. } = cx.tcx.hir_body(closure.body) else { + let [p] = closure.fn_decl.inputs else { return; }; + let body = cx.tcx.hir_body(closure.body); if param_captured_by_move_block(cx, body.value, p) { return; @@ -76,7 +77,7 @@ pub(super) fn check<'tcx>( }; ExprUseVisitor::for_clippy(cx, closure.def_id, &mut delegate) - .consume_body(body) + .consume_body(closure.fn_decl, body) .into_ok(); let mut to_be_discarded = false; diff --git a/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs index 607979719f894..fdbe95d753520 100644 --- a/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs +++ b/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs @@ -3,7 +3,7 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _, MaybeTypeckRes as _}; use clippy_utils::sym; use rustc_errors::Applicability; -use rustc_hir::{Body, Closure, Expr, ExprKind}; +use rustc_hir::{Closure, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::Span; @@ -41,15 +41,14 @@ pub(super) fn check_filter_or_flat_map( .qpath_res(qpath, method_arg.hir_id) .is_diag_item(cx, sym::result_ok_method), // Detect `|x| x.ok()` - ExprKind::Closure(&Closure { body, .. }) => { - if let Body { - params: [param], value, .. - } = cx.tcx.hir_body(body) + ExprKind::Closure(&Closure { fn_decl, body, .. }) => { + let value = cx.tcx.hir_body(body).value; + if let [param] = fn_decl.inputs && let ExprKind::MethodCall(method, receiver, [], _) = value.kind { method.ident.name == sym::ok && receiver.res_local_id() == Some(param.pat.hir_id) - && cx.ty_based_def(*value).is_diag_item(cx, sym::result_ok_method) + && cx.ty_based_def(value).is_diag_item(cx, sym::result_ok_method) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs b/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs index 58453a3c08774..58681b944326c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs @@ -7,7 +7,7 @@ use clippy_utils::usage::local_used_in; use rustc_ast::UnOp; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{BinOpKind, Body, Expr, ExprKind, HirId, QPath}; +use rustc_hir::{BinOpKind, Expr, ExprKind, HirId, QPath}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Spanned; @@ -20,8 +20,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, clos if !expr.span.from_expansion() // check if `iter().any()` can be replaced with `contains()` && let ExprKind::Closure(closure) = closure_arg.kind - && let Body{params: [param],value} = cx.tcx.hir_body(closure.body) - && let ExprKind::Binary(op, lhs, rhs) = value.kind + && let [param] = closure.fn_decl.inputs + && let ExprKind::Binary(op, lhs, rhs) = cx.tcx.hir_body(closure.body).value.kind && let (peeled_ref_pat, _) = peel_hir_pat_refs(param.pat) && let Some((snip,snip_expr)) = can_replace_with_contains(cx, op, lhs, rhs, peeled_ref_pat.hir_id, &mut app) && let ref_type = cx.typeck_results().expr_ty_adjusted(recv) diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index aff6477c32547..96fd874ac397d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -25,7 +25,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: || fn_def.opt_parent(cx).opt_impl_ty(cx).is_diag_item(cx, sym::Result)) && msrv.meets(cx, msrvs::OPTION_RESULT_INSPECT))) && let body = cx.tcx.hir_body(c.body) - && let [param] = body.params + && let [param] = c.fn_decl.inputs && let PatKind::Binding(BindingMode(ByRef::No, Mutability::Not), arg_id, _, None) = param.pat.kind && let arg_ty = typeck.node_type(arg_id) && let ExprKind::Block(block, _) = body.value.kind @@ -164,7 +164,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { if requires_deref { - edits.push((param.span.shrink_to_lo(), "&".into())); + edits.push((param.param_span.shrink_to_lo(), "&".into())); } else { edits.extend(addr_of_edits); } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs index 5b6506b853b5f..ac8a4044a80fc 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs @@ -56,7 +56,7 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool { }, ExprKind::Closure(closure) => { let body = cx.tcx.hir_body(closure.body); - if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind + if let PatKind::Binding(_, param_id, ..) = closure.fn_decl.inputs[0].pat.kind && let ExprKind::Call(callee, [ok_arg]) = body.value.kind && callee.res(cx).ctor_parent(cx).is_lang_item(cx, ResultOk) { diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_option_zip.rs b/src/tools/clippy/clippy_lints/src/methods/manual_option_zip.rs index e168beddf57b6..82e3b13e9c05e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_option_zip.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_option_zip.rs @@ -22,8 +22,9 @@ pub(super) fn check<'tcx>( ) { // Looking for: `a.and_then(|a| b.map(|b| (a, b)))`. // `and_then(|a| ...)` - if let ExprKind::Closure(&hir::Closure { body: outer_body_id, .. }) = arg.kind - && let hir::Body { params: [outer_param], value: outer_value, .. } = cx.tcx.hir_body(outer_body_id) + if let ExprKind::Closure(&hir::Closure { fn_decl: outer_fn_decl, body: outer_body_id, .. }) = arg.kind + && let [outer_param] = outer_fn_decl.inputs + && let outer_value = cx.tcx.hir_body(outer_body_id).value && let PatKind::Binding(_, outer_param_id, _, None) = outer_param.pat.kind && cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Option) // `b.map(|b| ...)` @@ -35,8 +36,9 @@ pub(super) fn check<'tcx>( // `b` does not reference the outer closure parameter `a`. && !local_used_in(cx, outer_param_id, map_recv) // `|b| (a, b)` - && let ExprKind::Closure(&hir::Closure { body: inner_body_id, .. }) = map_arg.kind - && let hir::Body { params: [inner_param], value: inner_value, .. } = cx.tcx.hir_body(inner_body_id) + && let ExprKind::Closure(&hir::Closure { fn_decl: inner_fn_decl, body: inner_body_id, .. }) = map_arg.kind + && let [inner_param] = inner_fn_decl.inputs + && let inner_value = cx.tcx.hir_body(inner_body_id).value && let PatKind::Binding(_, inner_param_id, _, None) = inner_param.pat.kind // `(a, b)` or `(b, a)` — tuple of outer and inner param in either order. && let ExprKind::Tup([first, second]) = peel_blocks(inner_value).kind diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs index 072f56b897014..51c765e18235f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs @@ -47,10 +47,10 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ && should_run_lint(cx, e, parent_id) { match arg.kind { - hir::ExprKind::Closure(&hir::Closure { body, .. }) => { + hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) => { let closure_body = cx.tcx.hir_body(body); let closure_expr = peel_blocks(closure_body.value); - match closure_body.params[0].pat.kind { + match fn_decl.inputs[0].pat.kind { hir::PatKind::Ref(inner, Pinnedness::Not, Mutability::Not) => { if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind && ident_eq(name, closure_expr) diff --git a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs index 9868d1a60d0a8..fa756b97f5a87 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef as _; -use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, PatKind}; +use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, PatKind, FnDecl}; use rustc_lint::LateContext; use rustc_span::sym; @@ -17,12 +17,10 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) { .is_diag_item(cx, sym::Result) && let ExprKind::Closure(&Closure { capture_clause: CaptureBy::Ref, - body, + fn_decl: FnDecl { inputs: [param], .. }, fn_decl_span, .. }) = arg.kind - && let closure_body = cx.tcx.hir_body(body) - && let [param] = closure_body.params && let PatKind::Wild = param.pat.kind { // span the area of the closure capture and warn that the diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs index aca065bbc65a5..866337a47602e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -8,7 +8,7 @@ use rustc_ast::LitKind; use rustc_ast::ast::RangeLimits; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{Body, Closure, Expr, ExprKind}; +use rustc_hir::{Body, Closure, Expr, ExprKind, FnDecl}; use rustc_lint::LateContext; use rustc_span::{Span, SyntaxContext}; @@ -68,13 +68,12 @@ pub(super) fn check( ) { let mut applicability = Applicability::MaybeIncorrect; if let Some(range) = higher::Range::hir(cx, receiver) - && let ExprKind::Closure(Closure { body, .. }) = arg.kind + && let ExprKind::Closure(Closure { fn_decl: decl@FnDecl { inputs: [param], .. }, body, .. }) = arg.kind && let body_hir = cx.tcx.hir_body(*body) && let Body { - params: [param], value: body_expr, } = body_hir - && !usage::BindingUsageFinder::are_params_used(cx, body_hir) + && !usage::BindingUsageFinder::are_params_used(cx, decl, body_hir) && let ctxt = ex.span.ctxt() && let Some(count) = extract_count_with_applicability(cx, range, &mut applicability, ctxt) && let Some(exec_context) = std_or_core(cx) @@ -88,7 +87,7 @@ pub(super) fn check( ("repeat", (arg.span, body_snippet.to_string()), true) } } else if msrv.meets(cx, msrvs::REPEAT_WITH) { - ("repeat_with", (param.span, String::new()), true) + ("repeat_with", (param.param_span, String::new()), true) } else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index f4b8c08321da9..24d5ebe6b7f6f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -5363,7 +5363,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { return; } - if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind { + if let hir::ImplItemKind::Fn(ref sig, _id) = impl_item.kind { let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir_expect_item(parent); let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip(); @@ -5377,7 +5377,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if sig.decl.implicit_self().has_implicit_self() && !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id)) - && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir_body(id)).next() + && let Some(first_arg) = iter_input_pats(sig.decl).next() && let Some(first_arg_ty) = first_arg_ty_opt { wrong_self_convention::check( @@ -5400,7 +5400,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { && !item.span.in_external_macro(cx.tcx.sess.source_map()) { if sig.decl.implicit_self().has_implicit_self() - && let Some(first_arg_hir_ty) = sig.decl.inputs.first() + && let Some(first_arg_hir) = sig.decl.inputs.first() && let Some(&first_arg_ty) = cx .tcx .fn_sig(item.owner_id) @@ -5416,7 +5416,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { item.ident.name, self_ty, first_arg_ty, - first_arg_hir_ty.span, + first_arg_hir.ty.span, false, true, ); @@ -5485,7 +5485,7 @@ impl Methods { Some((sym::chars, recv, _, _, _)) if let ExprKind::Closure(arg) = arg.kind && let body = cx.tcx.hir_body(arg.body) - && let [param] = body.params => + && let [param] = arg.fn_decl.inputs => { string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), self.msrv); }, diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs index aac4a344f5f99..e3792cf50a45c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs @@ -1,6 +1,6 @@ use clippy_utils::res::{MaybeDef as _, MaybeQPath as _, MaybeResPath as _}; use rustc_errors::Applicability; -use rustc_hir::{Closure, Expr, ExprKind, HirId, StmtKind, UnOp}; +use rustc_hir::{Closure, Expr, ExprKind, HirId, StmtKind, UnOp, FnDecl}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -96,9 +96,8 @@ fn handle_expr( } pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, closure_arg: &Expr<'_>, is_all: bool) { - if let ExprKind::Closure(&Closure { body, .. }) = closure_arg.kind + if let ExprKind::Closure(&Closure { fn_decl: FnDecl { inputs: [first_param], .. }, body, .. }) = closure_arg.kind && let body = cx.tcx.hir_body(body) - && let Some(first_param) = body.params.first() && let ExprKind::MethodCall(method, mut recv, [], _) = recv.kind && method.ident.name == sym::chars && let str_ty = cx.typeck_results().expr_ty_adjusted(recv).peel_refs() diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 31f294ff27d37..bf5f7ba2c9e9b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -45,13 +45,13 @@ pub(super) fn check( .is_some_and(|fun_name| { matches!(fun_name, sym::deref_method | sym::deref_mut_method) || deref_aliases.contains(&fun_name) }), - hir::ExprKind::Closure(&hir::Closure { body, .. }) => { + hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) => { let closure_body = cx.tcx.hir_body(body); let closure_expr = peel_blocks(closure_body.value); match &closure_expr.kind { hir::ExprKind::MethodCall(_, receiver, [], _) => { - if receiver.res_local_id() == Some(closure_body.params[0].pat.hir_id) + if receiver.res_local_id() == Some(fn_decl.inputs[0].pat.hir_id) && let adj = cx .typeck_results() .expr_adjustments(receiver) @@ -75,7 +75,7 @@ pub(super) fn check( if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind && let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind { - inner2.res_local_id() == Some(closure_body.params[0].pat.hir_id) + inner2.res_local_id() == Some(fn_decl.inputs[0].pat.hir_id) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index bf9c89e43de01..a01c58c5a1f05 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -317,10 +317,10 @@ fn check_or_fn_call<'tcx>( } fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = e.kind { + if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = e.kind { let body = cx.tcx.hir_body(body); - if body.params.is_empty() + if fn_decl.inputs.is_empty() && let hir::Expr { kind, .. } = &body.value && let hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, self_arg, [], _) = kind && ident.name == sym::to_string diff --git a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs index 20220f83620ec..c30019ccc5ad0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs @@ -103,8 +103,7 @@ fn methods_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option | sym::try_for_each ) && let ExprKind::Closure(closure) = arg.kind - && let body = cx.tcx.hir_body(closure.body) - && let [param] = body.params + && let [param] = closure.fn_decl.inputs { Some(param.pat) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs index 404ad551919f5..ddea16e78dd24 100644 --- a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs @@ -47,7 +47,7 @@ pub(super) fn check<'tcx>( let closure_expr = peel_blocks(cx.tcx.hir_body(body).value); let mut applicability = Applicability::MachineApplicable; - let arg_snip = snippet_with_applicability(cx, closure_arg.span, "_", &mut applicability); + let arg_snip = snippet_with_applicability(cx, closure_arg.ty.span, "_", &mut applicability); let recv_snip = snippet_with_applicability(cx, recv.span, "_", &mut applicability); let body_snip = snippet_with_applicability(cx, closure_expr.span, "..", &mut applicability); let inner = match body_snip.strip_prefix('{').and_then(|s| s.strip_suffix('}')) { diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs index 7c7211e971c8a..983a992b87fb5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs @@ -39,9 +39,8 @@ pub(super) fn check<'tcx>( // suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()` let mut applicability = Applicability::MachineApplicable; let any_search_snippet = if search_method == sym::find - && let ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind - && let closure_body = cx.tcx.hir_body(body) - && let Some(closure_arg) = closure_body.params.first() + && let ExprKind::Closure(&hir::Closure { fn_decl, .. }) = search_arg.kind + && let Some(closure_arg) = fn_decl.inputs.first() { if let PatKind::Ref(..) = closure_arg.pat.kind { Some(search_snippet.replacen('&', "", 1)) diff --git a/src/tools/clippy/clippy_lints/src/methods/some_filter.rs b/src/tools/clippy/clippy_lints/src/methods/some_filter.rs index f3db0fa165af3..b468195890c81 100644 --- a/src/tools/clippy/clippy_lints/src/methods/some_filter.rs +++ b/src/tools/clippy/clippy_lints/src/methods/some_filter.rs @@ -18,10 +18,8 @@ pub(super) fn check<'tcx>( ) { let (condition, value) = if let Some(value) = as_some_expr(cx, recv) && let ExprKind::Closure(c) = arg.kind - && let Body { - params: [p], - value: condition, - } = cx.tcx.hir_body(c.body) + && let [p] = c.fn_decl.inputs + && let Body { value: condition } = cx.tcx.hir_body(c.body) && pat_is_wild(cx, &p.pat.kind, arg) && msrv.meets(cx, msrvs::BOOL_THEN_SOME) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 31f21492dfedd..31f09cdd93fe5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -24,11 +24,11 @@ pub(super) fn check<'tcx>( return; } - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind { + if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = arg.kind { let body = cx.tcx.hir_body(body); - let arg_id = body.params[0].pat.hir_id; + let arg_id = fn_decl.inputs[0].pat.hir_id; let mutates_arg = mutated_variables(body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id)); - let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value); + let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, fn_decl.inputs[0].pat, body.value); let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value); @@ -42,7 +42,7 @@ pub(super) fn check<'tcx>( ControlFlow::Continue(Descend::Yes) } }); - let in_ty = cx.typeck_results().node_type(body.params[0].hir_id); + let in_ty = cx.typeck_results().node_type(fn_decl.inputs[0].hir_id); let sugg = if !found_filtering { // Check if the closure is .filter_map(|x| Some(x)) if kind.is_filter_map() diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index c7207bb4dd4bc..aedf84c471b5c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -123,7 +123,7 @@ fn check_fold_with_op( op: hir::BinOpKind, replacement: Replacement, ) -> bool { - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind + if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = acc.kind // Extract the body of the closure passed to fold && let closure_body = cx.tcx.hir_body(body) && let closure_expr = peel_blocks(closure_body.value) @@ -133,7 +133,7 @@ fn check_fold_with_op( && bin_op.node == op // Extract the names of the two arguments to the closure - && let [param_a, param_b] = closure_body.params + && let [param_a, param_b] = fn_decl.inputs && let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind && let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind @@ -333,9 +333,9 @@ fn check_option_fold<'tcx>( _ => return, } && cx.typeck_results().expr_ty(option_expr).is_diag_item(cx, sym::Option) - && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind + && let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = acc.kind && let closure_body = cx.tcx.hir_body(body) - && let [param_acc, param_item] = closure_body.params + && let [param_acc, param_item] = fn_decl.inputs // The suggestion rewrites source spans, so bail out when any part // comes from a different syntax context. && recv.span.ctxt() == ctxt diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 3a60548feeb25..980bfe8563170 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -35,7 +35,7 @@ pub(super) fn check<'tcx>( let body = cx.tcx.hir_body(body); let body_expr = &body.value; - if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) { + if usage::BindingUsageFinder::are_params_used(cx, fn_decl, body) || is_from_proc_macro(cx, expr) { return false; } @@ -49,8 +49,8 @@ pub(super) fn check<'tcx>( }; let mut applicability = Applicability::MachineApplicable; - if body - .params + if fn_decl + .inputs .iter() // bindings are checked to be unused above .any(|param| !matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild)) diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs index dff23e1cce061..588ea0ed1765a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs @@ -50,10 +50,10 @@ fn closure_bool_constant(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option let ExprKind::Closure(closure) = expr.kind else { return None; }; - let body = cx.tcx.hir_body(closure.body); - let [_] = body.params else { + let [_] = closure.fn_decl.inputs else { return None; }; + let body = cx.tcx.hir_body(closure.body); bool_constant(cx, body.value) } @@ -158,7 +158,7 @@ pub(super) fn check<'tcx>( && let closure_body = cx.tcx.hir_body(map_closure.body) && let closure_body_value = closure_body.value.peel_blocks() && let ExprKind::Binary(op, l, r) = closure_body_value.kind - && let [param] = closure_body.params + && let [param] = map_closure.fn_decl.inputs && let PatKind::Binding(_, hir_id, _, _) = param.pat.kind // checking that map_or is one of the following: // .map_or(false, |x| x == y) diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs index 48333cd2d85f3..dbbaeee13835b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -249,9 +249,9 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>) -> Option< .instantiate_identity() .skip_norm_wip() .is_slice() - && let ExprKind::Closure(&Closure { body, .. }) = arg.kind + && let ExprKind::Closure(&Closure { fn_decl, body, .. }) = arg.kind && let closure_body = cx.tcx.hir_body(body) - && let &[Param { pat: l_pat, .. }, Param { pat: r_pat, .. }] = closure_body.params + && let &[Param { pat: l_pat, .. }, Param { pat: r_pat, .. }] = fn_decl.inputs && let Some(binding_map) = mapping_of_mirrored_pats(l_pat, r_pat) && let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind && method_path.ident.name == sym::cmp diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_unwrap_unchecked.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_unwrap_unchecked.rs index af7fd4d7bce14..c02218a5684aa 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_unwrap_unchecked.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_unwrap_unchecked.rs @@ -5,7 +5,7 @@ use clippy_utils::{is_from_proc_macro, last_path_segment, over}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Body, Expr, ExprKind, PatKind, Safety}; +use rustc_hir::{Expr, ExprKind, PatKind, Safety, FnDecl}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -134,14 +134,14 @@ fn same_functions_modulo_safety<'tcx>( unchecked_def_id: DefId, unwrapped_ret_ty: Ty<'tcx>, ) -> bool { - let hir_body = |def_id: DefId| -> Option<&'tcx Body<'tcx>> { cx.tcx.hir_maybe_body_owned_by(def_id.as_local()?) }; + let hir_decl = |def_id: DefId| -> Option<&'tcx FnDecl<'tcx>> { cx.tcx.hir_fn_decl_by_hir_id(cx.tcx.local_def_id_to_hir_id(def_id.as_local()?)) }; let fn_sig = |def_id| cx.tcx.fn_sig(def_id).skip_binder().skip_binder(); - if match (hir_body(checked_def_id), hir_body(unchecked_def_id)) { + if match (hir_decl(checked_def_id), hir_decl(unchecked_def_id)) { // For local functions, we can get the parameter names. In that case, we want to make sure // that the latter are equal between the checked and unchecked versions. - (Some(checked_body), Some(unchecked_body)) => { - over(checked_body.params, unchecked_body.params, |p1, p2| { + (Some(checked_decl), Some(unchecked_decl)) => { + over(checked_decl.inputs, unchecked_decl.inputs, |p1, p2| { // We only allow simple params (plain bindings) for now, to stay on the safer side. if let PatKind::Binding(bm1, _, ident1, None) = p1.pat.kind && let PatKind::Binding(bm2, _, ident2, None) = p2.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index 057bb3a3a538d..e08fa259365fa 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -146,13 +146,12 @@ fn check_qpath(cx: &LateContext<'_>, qpath: hir::QPath<'_>, hir_id: hir::HirId) fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { match arg.kind { - hir::ExprKind::Closure(&hir::Closure { body, .. }) + hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) // If it's a closure, we need to check what is called. - if let closure_body = cx.tcx.hir_body(body) - && let [param] = closure_body.params + if let [param] = fn_decl.inputs && let hir::PatKind::Binding(_, local_id, ..) = strip_pat_refs(param.pat).kind => { - let closure_expr = peel_blocks(closure_body.value); + let closure_expr = peel_blocks(cx.tcx.hir_body(body).value); match closure_expr.kind { hir::ExprKind::MethodCall(method, obj, [], _) => { if method.ident.name == sym::clone diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index ee546528020ac..6f5d7bc11a023 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -173,15 +173,6 @@ impl LateLintPass<'_> for MinIdentChars { if self.min_chars_threshold == 0 { return; } - if let TraitItemKind::Fn(_, TraitFn::Required(idents)) = i.kind { - for &ident in idents { - if let Some(ident) = ident - && let Some(missing) = self.check_sym(ident.name) - { - self.emit(cx, ident, missing); - } - } - } if let Some(missing) = self.check_sym(i.ident.name) && !(matches!(i.kind, TraitItemKind::Fn(_, TraitFn::Provided(_))) && cx.tcx.codegen_fn_attrs(i.owner_id.def_id).contains_extern_indicator()) @@ -200,10 +191,10 @@ impl LateLintPass<'_> for MinIdentChars { trait_item_def_id: Ok(trait_item), .. } = i.impl_kind - && let ImplItemKind::Fn(_, body) = i.kind + && let ImplItemKind::Fn(sig, _) = i.kind { let mut named_params_count = 0; - for (trait_ident, param) in iter::zip(cx.tcx.fn_arg_idents(trait_item), cx.tcx.hir_body(body).params) { + for (trait_ident, param) in iter::zip(cx.tcx.fn_arg_idents(trait_item), sig.decl.inputs) { if let PatKind::Binding(_, _, ident, _) = param.pat.kind { named_params_count += 1; if trait_ident.is_none_or(|trait_ident| ident.name != trait_ident.name || self.lint_trait_impl) diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 7e413f8b6a35b..c20cf5775ebe4 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -110,8 +110,8 @@ impl<'tcx> MutableKeyType<'tcx> { fn check_sig(&mut self, cx: &LateContext<'tcx>, fn_def_id: LocalDefId, decl: &hir::FnDecl<'tcx>) { let fn_sig = cx.tcx.fn_sig(fn_def_id).instantiate_identity().skip_norm_wip(); - for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) { - self.check_ty_(cx, hir_ty.span, *ty); + for (hir_param, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) { + self.check_ty_(cx, hir_param.ty.span, *ty); } self.check_ty_( cx, diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs index 13a3c99274d5f..4ace73b37dee5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs +++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs @@ -95,7 +95,7 @@ fn check_expr(cx: &LateContext<'_>, expr: &Expr<'_>, outer_span: Span) { if fn_decl .inputs .iter() - .any(|input| matches!(input.kind, TyKind::Infer(..))) + .any(|input| matches!(input.ty.kind, TyKind::Infer(..))) { applicability = Applicability::MaybeIncorrect; } @@ -121,7 +121,7 @@ fn check_expr(cx: &LateContext<'_>, expr: &Expr<'_>, outer_span: Span) { ) }; - let body_param_sugg = snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability); + let body_param_sugg = snippet_with_applicability(cx, fn_decl.inputs[0].pat.span, "..", &mut applicability); let for_each_rev_sugg = snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability); let (body_value_sugg, is_macro_call) = snippet_with_context(cx, body.value.span, for_each_recv.span.ctxt(), "..", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index ce5040372c3cc..c67ede2b4fde0 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -69,22 +69,21 @@ impl NeedlessPassByRefMut<'_> { fn should_skip<'tcx>( cx: &LateContext<'tcx>, - input: rustc_hir::Ty<'tcx>, + input: &rustc_hir::Param<'tcx>, ty: Ty<'_>, - arg: &rustc_hir::Param<'_>, ) -> bool { // We check if this a `&mut`. `ref_mutability` returns `None` if it's not a reference. if !matches!(ty.ref_mutability(), Some(Mutability::Mut)) { return true; } - if is_self(arg) { + if is_self(input) { // Interestingly enough, `self` arguments make `is_from_proc_macro` return `true`, hence why // we return early here. return false; } - if let PatKind::Binding(.., name, _) = arg.pat.kind + if let PatKind::Binding(.., name, _) = input.pat.kind // If it's a potentially unused variable, we don't check it. && (name.name == kw::Underscore || name.as_str().starts_with('_')) { @@ -92,7 +91,7 @@ fn should_skip<'tcx>( } // All spans generated from a proc-macro invocation are the same... - is_from_proc_macro(cx, &input) + is_from_proc_macro(cx, input.ty) } fn check_closures<'tcx>( @@ -101,20 +100,18 @@ fn check_closures<'tcx>( checked_closures: &mut FxHashSet, closures: FxIndexSet, ) { - for closure in closures { - if !checked_closures.insert(closure) { + for id in closures { + if !checked_closures.insert(id) { continue; } ctx.prev_bind = None; ctx.prev_move_to_closure.clear(); - if let Some(body) = cx + if let Node::Expr(Expr { kind: ExprKind::Closure(closure), .. }) = cx .tcx - .hir_node_by_def_id(closure) - .associated_body() - .map(|(_, body_id)| cx.tcx.hir_body(body_id)) + .hir_node_by_def_id(id) { - euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx) - .consume_body(body) + euv::ExprUseVisitor::for_clippy(cx, id, &mut *ctx) + .consume_body(closure.fn_decl, cx.tcx.hir_body(closure.body)) .into_ok(); } } @@ -179,8 +176,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { .inputs .iter() .zip(fn_sig.inputs()) - .zip(body.params) - .filter(|&((&input, &ty), arg)| !should_skip(cx, input, ty, arg)) + .filter(|&(input, &ty)| !should_skip(cx, &input, ty)) .peekable(); if it.peek().is_none() { return; @@ -197,7 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { tcx: cx.tcx, }; euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx) - .consume_body(body) + .consume_body(decl, body) .into_ok(); let mut checked_closures = FxHashSet::default(); @@ -222,15 +218,15 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { } ctx.generate_mutably_used_ids_from_aliases() }; - for ((&input, &_), arg) in it { + for (input, &_) in it { // Only take `&mut` arguments. - if let PatKind::Binding(_, canonical_id, ..) = arg.pat.kind + if let PatKind::Binding(_, canonical_id, ..) = input.pat.kind && !mutably_used_vars.contains(&canonical_id) { self.fn_def_ids_to_maybe_unused_mut .entry(fn_def_id) .or_default() - .push(input); + .push(*input.ty); } } } diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 2420ef889ee74..4deb7124c910b 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { let MovedVariablesCtxt { moved_vars } = { let mut ctx = MovedVariablesCtxt::default(); euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx) - .consume_body(body) + .consume_body(decl, body) .into_ok(); ctx }; @@ -149,14 +149,14 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { let fn_sig = cx.tcx.fn_sig(fn_def_id).instantiate_identity().skip_norm_wip(); let fn_sig = cx.tcx.liberate_late_bound_regions(fn_def_id.to_def_id(), fn_sig); - for (idx, ((input, &ty), arg)) in decl.inputs.iter().zip(fn_sig.inputs()).zip(body.params).enumerate() { + for (idx, (input, &ty)) in decl.inputs.iter().zip(fn_sig.inputs()).enumerate() { // All spans generated from a proc-macro invocation are the same... - if span == input.span { + if span == input.ty.span { return; } // Ignore `self`s and params whose variable name starts with an underscore - if let PatKind::Binding(.., ident, _) = arg.pat.kind { + if let PatKind::Binding(.., ident, _) = input.pat.kind { if idx == 0 && ident.name == kw::SelfLower { continue; } @@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ) }; - if !is_self(arg) + if !is_self(input) && !ty.is_mutable_ptr() && !is_copy(cx, ty) && ty.is_sized(cx.tcx, cx.typing_env()) @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { }) && !implements_borrow_trait && !all_borrowable_trait - && let PatKind::Binding(BindingMode(_, Mutability::Not), canonical_id, ..) = arg.pat.kind + && let PatKind::Binding(BindingMode(_, Mutability::Not), canonical_id, ..) = input.pat.kind && !moved_vars.contains(&canonical_id) { // Dereference suggestion @@ -220,8 +220,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } if ty.is_diag_item(cx, sym::Vec) - && let Some(clone_spans) = get_spans(cx, body, idx, &[(sym::clone, ".to_owned()")]) - && let TyKind::Path(QPath::Resolved(_, path)) = input.kind + && let Some(clone_spans) = get_spans(cx, decl, body, idx, &[(sym::clone, ".to_owned()")]) + && let TyKind::Path(QPath::Resolved(_, path)) = input.ty.kind && let Some(elem_ty) = path .segments .iter() @@ -240,7 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { { let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); diag.span_suggestion( - input.span, + input.ty.span, "consider changing the type to", slice_ty, Applicability::Unspecified, @@ -264,10 +264,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if ty.is_lang_item(cx, LangItem::String) && let Some(clone_spans) = - get_spans(cx, body, idx, &[(sym::clone, ".to_string()"), (sym::as_str, "")]) + get_spans(cx, decl, body, idx, &[(sym::clone, ".to_string()"), (sym::as_str, "")]) { diag.span_suggestion( - input.span, + input.ty.span, "consider changing the type to", "&str", Applicability::Unspecified, @@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } diag.span_suggestion_verbose( - peel_hir_ty_options(cx, input).span.shrink_to_lo(), + peel_hir_ty_options(cx, input.ty).span.shrink_to_lo(), "consider taking a reference instead", '&', Applicability::MaybeIncorrect, @@ -299,8 +299,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { span_lint_hir_and_then( cx, NEEDLESS_PASS_BY_VALUE, - arg.hir_id, - input.span, + input.ty.hir_id, + input.ty.span, "this argument is passed by value, but not consumed in the function body", sugg, ); @@ -343,11 +343,12 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { fn get_spans<'tcx>( cx: &LateContext<'tcx>, + decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, idx: usize, replacements: &[(Symbol, &'static str)], ) -> Option)>> { - if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(body.params[idx].pat).kind { + if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(decl.inputs[idx].pat).kind { extract_clone_suggestions(cx, binding_id, replacements, body) } else { Some(vec![]) diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index 32cf04908911f..1e686c58d53a3 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs @@ -6,7 +6,7 @@ use clippy_utils::{is_from_proc_macro, is_lint_allowed, last_path_segment, std_o use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{Block, Body, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Stmt, StmtKind, UnOp}; +use rustc_hir::{Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Stmt, StmtKind, UnOp, FnDecl}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty::{TyCtxt, TypeckResults}; use rustc_span::sym; @@ -168,12 +168,12 @@ impl LateLintPass<'_> for NonCanonicalImpls { .iter() .map(|id| cx.tcx.hir_impl_item(*id)) .filter_map(|assoc| { - if let ImplItemKind::Fn(_, body_id) = assoc.kind + if let ImplItemKind::Fn(sig, body_id) = assoc.kind && let body = cx.tcx.hir_body(body_id) && let ExprKind::Block(block, ..) = body.value.kind && !block.span.in_external_macro(cx.sess().source_map()) { - Some((assoc, body, block)) + Some((assoc, sig.decl, body, block)) } else { None } @@ -186,7 +186,7 @@ impl LateLintPass<'_> for NonCanonicalImpls { if let Some(copy_trait) = self.copy_trait && implements_trait(cx, trait_impl.self_ty(), copy_trait, &[]) { - for (assoc, body, _) in assoc_fns { + for (assoc, _, body, _) in assoc_fns { check_clone_on_copy(cx, assoc, body.value); } } @@ -198,10 +198,10 @@ impl LateLintPass<'_> for NonCanonicalImpls { && lhs == rhs && let Some(ord_trait) = self.ord_trait && implements_trait(cx, trait_impl.self_ty(), ord_trait, &[]) - && let Some((assoc, body, block)) = - assoc_fns.find(|(assoc, _, _)| assoc.ident.name == sym::partial_cmp) + && let Some((assoc, decl, _, block)) = + assoc_fns.find(|(assoc, _, _, _)| assoc.ident.name == sym::partial_cmp) { - check_partial_ord_on_ord(cx, assoc, item, body, block); + check_partial_ord_on_ord(cx, assoc, item, decl, block); } }, } @@ -292,7 +292,7 @@ fn check_partial_ord_on_ord<'tcx>( cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>, item: &Item<'_>, - body: &Body<'_>, + decl: &FnDecl<'_>, block: &Block<'tcx>, ) { // If the `cmp` call likely needs to be fully qualified in the suggestion @@ -326,7 +326,7 @@ fn check_partial_ord_on_ord<'tcx>( item.span, "non-canonical implementation of `partial_cmp` on an `Ord` type", |diag| { - let [_, other] = body.params else { + let [_, other] = decl.inputs else { return; }; let Some(std_or_core) = std_or_core(cx) else { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 744b521a56129..6cebe36bb2c1e 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{ Body, Expr, ExprKind, HirId, HirIdMap, ImplItem, ImplItemImplKind, ImplItemKind, Node, PatKind, TraitItem, - TraitItemKind, + TraitItemKind, Item, ItemKind, }; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::{self, ConstKind, GenericArgKind, GenericArgsRef}; @@ -311,8 +311,8 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { } // `skip_params` is either `0` or `1` to skip the `self` parameter in trait functions. // It can't be renamed, and it can't be removed without removing it from multiple functions. - let (fn_id, fn_kind, skip_params) = match cx.tcx.parent_hir_node(body.value.hir_id) { - Node::Item(i) => (i.owner_id.to_def_id(), FnKind::Fn, 0), + let (fn_id, fn_kind, skip_params, decl) = match cx.tcx.parent_hir_node(body.value.hir_id) { + Node::Item(Item { owner_id, kind: ItemKind::Fn { sig, ..}, .. }) => (owner_id.to_def_id(), FnKind::Fn, 0, sig.decl), Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(ref sig, _), owner_id, @@ -321,6 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { owner_id.to_def_id(), FnKind::TraitFn, usize::from(sig.decl.implicit_self().has_implicit_self()), + sig.decl ), Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(ref sig, _), @@ -339,14 +340,15 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { std::ptr::from_ref(cx.tcx.erase_and_anonymize_regions(trait_ref.args)) as usize ), usize::from(sig.decl.implicit_self().has_implicit_self()), + sig.decl, ) } else { - (owner_id.to_def_id(), FnKind::Fn, 0) + (owner_id.to_def_id(), FnKind::Fn, 0, sig.decl) } }, _ => return, }; - body.params + decl.inputs .iter() .enumerate() .skip(skip_params) diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 4c541ead3d395..3fc04223af005 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -131,7 +131,6 @@ impl PassByRefOrValue { } let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); - let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir_body(id)); // Gather all the lifetimes found in the output type which may affect whether // `TRIVIALLY_COPY_PASS_BY_REF` should be linted. @@ -149,7 +148,7 @@ impl PassByRefOrValue { { // All spans generated from a proc-macro invocation are the same... match span { - Some(s) if s == input.span => continue, + Some(s) if s == input.ty.span => continue, _ => (), } @@ -171,7 +170,7 @@ impl PassByRefOrValue { if is_copy(cx, ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size <= self.ref_min_size - && let hir::TyKind::Ref(_, decl_ty, ..) = input.kind + && let hir::TyKind::Ref(_, decl_ty, ..) = input.ty.kind { if let Some(typeck) = cx.typeck_results // Don't lint if a raw pointer is created. @@ -186,7 +185,7 @@ impl PassByRefOrValue { { continue; } - let value_type = if fn_body.and_then(|body| body.params.get(index)).is_some_and(is_self) { + let value_type = if decl.inputs.get(index).is_some_and(is_self) { "self".into() } else { snippet(cx, decl_ty.span, "_").into() @@ -194,7 +193,7 @@ impl PassByRefOrValue { span_lint_and_sugg( cx, TRIVIALLY_COPY_PASS_BY_REF, - input.span, + input.ty.span, format!( "this argument ({size} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", self.ref_min_size @@ -208,7 +207,7 @@ impl PassByRefOrValue { ty::Adt(_, _) | ty::Array(_, _) | ty::Tuple(_) => { // if function has a body and parameter is annotated with mut, ignore - if let Some(param) = fn_body.and_then(|body| body.params.get(index)) { + if let Some(param) = decl.inputs.get(index) { match param.pat.kind { PatKind::Binding(BindingMode::NONE, _, _, _) => {}, _ => continue, @@ -217,20 +216,20 @@ impl PassByRefOrValue { let ty = cx.tcx.instantiate_bound_regions_with_erased(ty); if is_copy(cx, ty) - && !is_self_ty(input) + && !is_self_ty(input.ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size > self.value_max_size { span_lint_and_sugg( cx, LARGE_TYPES_PASSED_BY_VALUE, - input.span, + input.ty.span, format!( "this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", self.value_max_size ), "consider passing by reference instead", - format!("&{}", snippet(cx, input.span, "_")), + format!("&{}", snippet(cx, input.ty.span, "_")), Applicability::MaybeIncorrect, ); } diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 84a3cd7816500..ac01ccacec405 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -117,12 +117,12 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { &mut self, cx: &LateContext<'tcx>, _: intravisit::FnKind<'tcx>, - _: &'tcx FnDecl<'_>, - body: &'tcx Body<'_>, + decl: &'tcx FnDecl<'_>, + _: &'tcx Body<'_>, _: Span, _: LocalDefId, ) { - for param in body.params { + for param in decl.inputs { apply_lint(cx, param.pat, DerefPossible::Impossible); } } diff --git a/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs b/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs index bc0fac8684cf1..c013cc092d1dd 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs @@ -20,7 +20,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option< .decl .inputs .iter() - .flat_map(get_lifetimes) + .flat_map(|p| get_lifetimes(&p.ty)) .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region) .map(|(_, mutability, span)| (mutability == Some(Mutability::Not)).then_some(span)) .collect(); diff --git a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs index b5fcc10f613ee..b2faeac56e1aa 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs @@ -9,7 +9,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{ self as hir, AnonConst, BindingMode, Body, Expr, ExprKind, FnSig, GenericArg, HirId, HirIdMap, Lifetime, - Mutability, Node, OwnerId, Param, PatKind, QPath, TyKind, + Mutability, Node, OwnerId, Param, PatKind, QPath, TyKind, FnDecl, }; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::traits::{Obligation, ObligationCause}; @@ -41,10 +41,10 @@ pub(super) fn check_body<'tcx>( .instantiate_identity() .skip_norm_wip() .skip_binder(); - let lint_args: Vec<_> = check_fn_args(cx, sig, decl.inputs, body.params) + let lint_args: Vec<_> = check_fn_args(cx, sig, decl.inputs) .filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not) .collect(); - let results = check_ptr_arg_usage(cx, body, &lint_args); + let results = check_ptr_arg_usage(cx, decl, body, &lint_args); for (result, args) in iter::zip(&results, &lint_args).filter(|(r, _)| !r.skip) { span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, args.build_msg(), |diag| { @@ -78,7 +78,6 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item_id: OwnerId, s .skip_norm_wip() .skip_binder(), sig.decl.inputs, - &[], ) .filter(|arg| arg.mutability() == Mutability::Not) { @@ -199,22 +198,21 @@ impl<'tcx> DerefTy<'tcx> { fn check_fn_args<'cx, 'tcx: 'cx>( cx: &'cx LateContext<'tcx>, fn_sig: ty::FnSig<'tcx>, - hir_tys: &'tcx [hir::Ty<'tcx>], params: &'tcx [Param<'tcx>], ) -> impl Iterator> + 'cx { - iter::zip(fn_sig.inputs(), hir_tys) + iter::zip(fn_sig.inputs(), params) .enumerate() - .filter_map(move |(i, (ty, hir_ty))| { + .filter_map(move |(i, (ty, param))| { if let ty::Ref(_, ty, mutability) = *ty.kind() && let ty::Adt(adt, args) = *ty.kind() - && let TyKind::Ref(lt, inner_ty, _) = hir_ty.kind + && let TyKind::Ref(lt, inner_ty, _) = param.ty.kind && let TyKind::Path(QPath::Resolved(None, path)) = inner_ty.kind // Check that the name as typed matches the actual name of the type. // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec` && let [.., name] = path.segments && cx.tcx.item_name(adt.did()) == name.ident.name { - let emission_id = params.get(i).map_or(hir_ty.hir_id, |param| param.hir_id); + let emission_id = params.get(i).map_or(param.ty.hir_id, |param| param.hir_id); let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) { Some(sym::Vec) => ( [(sym::clone, ".to_owned()")].as_slice(), @@ -272,11 +270,11 @@ fn check_fn_args<'cx, 'tcx: 'cx>( cx, PTR_ARG, emission_id, - hir_ty.span, + param.ty.span, "using a reference to `Cow` is not recommended", |diag| { diag.span_suggestion( - hir_ty.span, + param.ty.span, "change this to", match ty.span().get_text(cx) { Some(s) => format!("&{}{s}", mutability.prefix_str()), @@ -294,7 +292,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( return Some(PtrArg { idx: i, emission_id, - span: hir_ty.span, + span: param.ty.span, ty_name: name.ident.name, method_renames, ref_prefix: RefPrefix { lt: *lt, mutability }, @@ -306,7 +304,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( } #[expect(clippy::too_many_lines)] -fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[PtrArg<'tcx>]) -> Vec { +fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, body: &Body<'tcx>, args: &[PtrArg<'tcx>]) -> Vec { struct V<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, /// Map from a local id to which argument it came from (index into `Self::args` and @@ -425,7 +423,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[ .iter() .enumerate() .filter_map(|(i, arg)| { - let param = &body.params[arg.idx]; + let param = &decl.inputs[arg.idx]; match param.pat.kind { PatKind::Binding(BindingMode::NONE, id, ident, None) if !is_lint_allowed(cx, PTR_ARG, param.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 25c137dec7375..247b99c1fef9a 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir}; use clippy_utils::get_parent_expr; use clippy_utils::sugg::Sugg; -use hir::Param; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; @@ -87,7 +86,6 @@ fn find_innermost_closure<'tcx>( &'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, ty::Asyncness, - &'tcx [Param<'tcx>], CaptureBy, )> { let mut data = None; @@ -121,7 +119,6 @@ fn find_innermost_closure<'tcx>( unwrapped_body_value, closure.fn_decl, asyncness, - body.params, capture_clause, )); steps -= 1; @@ -181,10 +178,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { // We don't want to suggest replacing `x!()()` with `x!()`. && recv.span.ctxt().outer_expn() == expr.span.ctxt().outer_expn() && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr) - && let Some((mut body, fn_decl, coroutine_kind, params, capture_clause)) = + && let Some((mut body, fn_decl, coroutine_kind, capture_clause)) = find_innermost_closure(cx, recv, call_depth) // outside macros we lint properly. Inside macros, we lint only ||() style closures. - && (!matches!(expr.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(_, _)) || params.is_empty()) + && (!matches!(expr.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(_, _)) || fn_decl.inputs.is_empty()) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/replace_box.rs b/src/tools/clippy/clippy_lints/src/replace_box.rs index c07aeec804f57..f7705b0b9b04d 100644 --- a/src/tools/clippy/clippy_lints/src/replace_box.rs +++ b/src/tools/clippy/clippy_lints/src/replace_box.rs @@ -61,7 +61,10 @@ impl ReplaceBox { consumed_locals: &mut self.consumed_locals, }, ) - .consume_body(cx.tcx.hir_body(body_id)) + .consume_body( + cx.tcx.hir_fn_decl_by_hir_id(cx.tcx.hir_body_owner(body_id)).unwrap(), + cx.tcx.hir_body(body_id) + ) .into_ok(); } diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 427cf180adf2c..a03b3b251acee 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -139,7 +139,9 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { let HirId { owner, local_id } = id; // get (or insert) the list of items for this owner and symbol - let (ref mut data, scope_owner) = *self.bindings.last_mut().unwrap(); + let Some((data, scope_owner)) = self.bindings.last_mut() else { + return + }; let items_with_name = data.entry(ident.name).or_default(); // check other bindings with the same name, most recently seen first @@ -149,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { return; } - if is_shadow(cx, scope_owner, prev, local_id) { + if is_shadow(cx, *scope_owner, prev, local_id) { let prev_hir_id = HirId { owner, local_id: prev }; lint_shadow(cx, pat, prev_hir_id, ident.span); // only lint against the "nearest" shadowed binding @@ -160,10 +162,18 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { items_with_name.push(local_id); } + //TODO add fn decl to signature of `check_body` and `visit_body` fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { let owner_id = cx.tcx.hir_body_owner_def_id(body.id()); if !matches!(cx.tcx.hir_body_owner_kind(owner_id), BodyOwnerKind::Closure) { self.bindings.push((FxHashMap::default(), owner_id)); + + //TODO ugly + if let Some(decl) = cx.tcx.hir_fn_decl_by_hir_id(cx.tcx.hir_body_owner(body.id())) { + for input in decl.inputs { + self.check_pat(cx, input.pat); + } + } } } diff --git a/src/tools/clippy/clippy_lints/src/single_option_map.rs b/src/tools/clippy/clippy_lints/src/single_option_map.rs index 3ecb389fec896..39379744fee64 100644 --- a/src/tools/clippy/clippy_lints/src/single_option_map.rs +++ b/src/tools/clippy/clippy_lints/src/single_option_map.rs @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for SingleOptionMap { && !matches!(args[0].kind, ExprKind::Path(_)) { if let ExprKind::Closure(closure) = args[0].kind { - let Body { params: [..], value } = cx.tcx.hir_body(closure.body); + let Body { value } = cx.tcx.hir_body(closure.body); if let ExprKind::Call(func, f_args) = value.kind && matches!(func.kind, ExprKind::Path(_)) && f_args.iter().all(|arg| matches!(arg.kind, ExprKind::Path(_))) diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs index 5f29ea35beaf1..4003d4d829c17 100644 --- a/src/tools/clippy/clippy_lints/src/string_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs @@ -140,7 +140,7 @@ fn get_char_span<'tcx>(cx: &'_ LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Optio fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<'_>, msrv: Msrv) { if let ExprKind::Closure(closure) = method_arg.kind && let body = cx.tcx.hir_body(closure.body) - && let Some(PatKind::Binding(_, binding, ..)) = body.params.first().map(|p| p.pat.kind) + && let Some(PatKind::Binding(_, binding, ..)) = closure.fn_decl.inputs.first().map(|p| p.pat.kind) { let mut set_char_spans: Vec = Vec::new(); diff --git a/src/tools/clippy/clippy_lints/src/toplevel_ref_arg.rs b/src/tools/clippy/clippy_lints/src/toplevel_ref_arg.rs index d4a91de3af047..1b9081e65b40e 100644 --- a/src/tools/clippy/clippy_lints/src/toplevel_ref_arg.rs +++ b/src/tools/clippy/clippy_lints/src/toplevel_ref_arg.rs @@ -54,15 +54,15 @@ impl<'tcx> LateLintPass<'tcx> for ToplevelRefArg { cx: &LateContext<'tcx>, k: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, - body: &'tcx Body<'_>, + _: &'tcx Body<'_>, _: Span, _: LocalDefId, ) { if !matches!(k, FnKind::Closure) { - for arg in iter_input_pats(decl, body) { + for arg in iter_input_pats(decl) { if let PatKind::Binding(BindingMode(ByRef::Yes(..), _), ..) = arg.pat.kind && is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) - && !arg.span.in_external_macro(cx.tcx.sess.source_map()) + && !arg.ty.span.in_external_macro(cx.tcx.sess.source_map()) { span_lint_hir( cx, diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index d493ceae0e9b0..949b9de7d311f 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -559,8 +559,8 @@ impl Types { return; } - for input in decl.inputs { - self.check_ty(cx, input, context); + for param in decl.inputs { + self.check_ty(cx, param.ty, context); } if let FnRetTy::Return(ty) = decl.output { diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 1e2d9ab27c3e6..f2a172cf7683c 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -59,17 +59,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { let assoc_item = cx.tcx.associated_item(impl_item.owner_id); if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind && assoc_item.is_method() - && let ImplItemKind::Fn(.., body_id) = &impl_item.kind + && let ImplItemKind::Fn(sig, body_id) = &impl_item.kind && (!cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api) + && let [self_param, ..] = sig.decl.inputs && let body = cx.tcx.hir_body(*body_id) - && let [self_param, ..] = body.params && !is_local_used(cx, body, self_param.pat.hir_id) && !is_todo_unimplemented_stub(cx, body.value) { span_lint_and_help( cx, UNUSED_SELF, - self_param.span, + self_param.param_span, "unused `self` argument", None, "consider refactoring to an associated function", diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 7b4250c6078f2..cc8c9ec821ba7 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } else { None }; - let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty); + let impl_inputs_outputs = decl.inputs.iter().map(|p| p.ty).chain(output_hir_ty); // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature. // diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 828fb1d3313b4..e2c3cb9ae2aac 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -403,8 +403,8 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { }, match fn_ptr.decl.output { FnRetTy::DefaultReturn(_) => { - if let [.., ty] = fn_ptr.decl.inputs { - ty_search_pat(ty).1 + if let [.., p] = fn_ptr.decl.inputs { + ty_search_pat(p.ty).1 } else { Pat::Str("(") } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 4ef0a795b4766..152cea006b45f 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -278,7 +278,7 @@ impl HirEqInterExpr<'_, '_, '_> { } fn eq_fn_decl(&mut self, left: &FnDecl<'_>, right: &FnDecl<'_>) -> bool { - over(left.inputs, right.inputs, |l, r| self.eq_ty(l, r)) + over(left.inputs, right.inputs, |l, r| self.eq_ty(l.ty, r.ty)) && (match (left.output, right.output) { (FnRetTy::DefaultReturn(_), FnRetTy::DefaultReturn(_)) => true, (FnRetTy::Return(l_ty), FnRetTy::Return(r_ty)) => self.eq_ty(l_ty, r_ty), @@ -1630,7 +1630,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { fn_ptr.safety.hash(&mut self.s); fn_ptr.abi.hash(&mut self.s); for arg in fn_ptr.decl.inputs { - self.hash_ty(arg); + self.hash_ty(arg.ty); } mem::discriminant(&fn_ptr.decl.output).hash(&mut self.s); match fn_ptr.decl.output { @@ -1662,6 +1662,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { | TyKind::Never | TyKind::InferDelegation(..) | TyKind::OpaqueDef(_) + | TyKind::CVarArgs | TyKind::TraitAscription(_) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index cc73396f72246..5e2c3f596f684 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1551,8 +1551,8 @@ pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool { false } -pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator> { - (0..decl.inputs.len()).map(move |i| &body.params[i]) +pub fn iter_input_pats<'tcx>(decl: &FnDecl<'tcx>) -> impl Iterator> { + decl.inputs.into_iter() } /// Checks if a given expression is a match expression expanded from the `?` @@ -1814,8 +1814,8 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// * `|x| { let y = x; ...; let z = y; return z }` /// /// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead. -fn is_body_identity_function<'hir>(cx: &LateContext<'_>, func: &Body<'hir>) -> bool { - let [param] = func.params else { +fn is_body_identity_function<'hir>(cx: &LateContext<'_>, decl: &FnDecl<'hir>, func: &Body<'hir>) -> bool { + let [param] = decl.inputs else { return false; }; @@ -1973,9 +1973,9 @@ pub fn is_expr_identity_of_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr< pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Closure(&Closure { body, fn_decl, .. }) - if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) => + if fn_decl.inputs.iter().all(|param| matches!(param.ty.kind, TyKind::Infer(()))) => { - is_body_identity_function(cx, cx.tcx.hir_body(body)) + is_body_identity_function(cx, fn_decl, cx.tcx.hir_body(body)) }, ExprKind::Path(QPath::Resolved(_, path)) if path.segments.iter().all(|seg| seg.infer_args) @@ -1997,7 +1997,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) /// errors. pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match expr.kind { - ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir_body(body)), + ExprKind::Closure(&Closure { fn_decl, body, .. }) => is_body_identity_function(cx, fn_decl, cx.tcx.hir_body(body)), _ => expr.basic_res().is_diag_item(cx, sym::convert_identity), } } diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index d05ae0b5c45b5..22e49ee492ccf 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -815,7 +815,7 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti let closure_body = cx.tcx.hir_body(body); // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`) // a type annotation is present if param `kind` is different from `TyKind::Infer` - let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, ty, ..) = fn_decl.inputs[0].kind { + let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, ty, ..) = fn_decl.inputs[0].ty.kind { matches!(ty.kind, TyKind::Ref(..)) } else { false @@ -824,7 +824,7 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti let mut visitor = DerefDelegate { cx, closure_span: closure.span, - closure_arg_id: closure_body.params[0].pat.hir_id, + closure_arg_id: fn_decl.inputs[0].pat.hir_id, closure_arg_is_type_annotated_double_ref, next_pos: closure.span.lo(), checked_borrows: FxHashSet::default(), @@ -833,7 +833,7 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti }; ExprUseVisitor::for_clippy(cx, def_id, &mut visitor) - .consume_body(closure_body) + .consume_body(fn_decl, closure_body) .into_ok(); if !visitor.suggestion_start.is_empty() { diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 0613d8d7453af..49927a0acb83b 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -724,7 +724,7 @@ impl<'tcx> ExprFnSig<'tcx> { } }, Self::Closure(decl, sig) => Some(( - decl.and_then(|decl| decl.inputs.get(i)), + decl.and_then(|decl| decl.inputs.get(i).map(|p| p.ty)), sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), )), Self::Trait(inputs, _, _) => Some((None, inputs.map_bound(|ty| ty.tuple_fields()[i]))), diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index 0cb4faadda628..71026fb8a8c80 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -209,10 +209,10 @@ fn param_certainty(cx: &LateContext<'_>, param: &Param<'_>) -> Certainty { return Certainty::Uncertain; }; let inputs = fn_decl.inputs; - let body_params = cx.tcx.hir_body_owned_by(owner_did).params; - std::iter::zip(body_params, inputs) - .find(|(p, _)| p.hir_id == param.hir_id) - .map_or(Certainty::Uncertain, |(_, ty)| type_certainty(cx, ty).clear_def_id()) + inputs + .iter() + .find(|p| p.hir_id == param.hir_id) + .map_or(Certainty::Uncertain, |p| type_certainty(cx, p.ty).clear_def_id()) } fn path_segment_certainty( diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index bc575701f6ee3..778fd6571a0f5 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -87,9 +87,9 @@ pub struct ParamBindingIdCollector { pub binding_hir_ids: Vec, } impl<'tcx> ParamBindingIdCollector { - fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec { + fn collect_binding_hir_ids(decl: &'tcx hir::FnDecl<'tcx>) -> Vec { let mut hir_ids: Vec = Vec::new(); - for param in body.params { + for param in decl.inputs { let mut finder = ParamBindingIdCollector { binding_hir_ids: Vec::new(), }; @@ -115,10 +115,10 @@ pub struct BindingUsageFinder<'a, 'tcx> { binding_ids: Vec, } impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> { - pub fn are_params_used(cx: &'a LateContext<'tcx>, body: &'tcx hir::Body<'tcx>) -> bool { + pub fn are_params_used(cx: &'a LateContext<'tcx>, decl: &hir::FnDecl<'_>, body: &'tcx hir::Body<'tcx>) -> bool { let mut finder = BindingUsageFinder { cx, - binding_ids: ParamBindingIdCollector::collect_binding_hir_ids(body), + binding_ids: ParamBindingIdCollector::collect_binding_hir_ids(decl), }; finder.visit_body(body).is_break() } diff --git a/src/tools/clippy/tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.stderr b/src/tools/clippy/tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.stderr index b483a21f37b47..d0b5ac04da8ef 100644 --- a/src/tools/clippy/tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.stderr +++ b/src/tools/clippy/tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.stderr @@ -1,17 +1,17 @@ error: this identifier consists of only a single character - --> tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.rs:4:10 + --> tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.rs:4:8 | LL | fn f(g: i32); - | ^ + | ^ | = note: `-D clippy::min-ident-chars` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::min_ident_chars)]` error: this identifier consists of only a single character - --> tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.rs:4:8 + --> tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.rs:4:10 | LL | fn f(g: i32); - | ^ + | ^ error: this identifier consists of only a single character --> tests/ui-toml/min_ident_chars_trait_impl/min_ident_chars.rs:12:10 diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr index 07082bbc82936..bfa2113d62a24 100644 --- a/src/tools/clippy/tests/ui/min_ident_chars.stderr +++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr @@ -220,16 +220,16 @@ LL | trait D { | ^ error: this identifier consists of only a single character - --> tests/ui/min_ident_chars.rs:151:10 + --> tests/ui/min_ident_chars.rs:151:8 | LL | fn f(g: i32); - | ^ + | ^ error: this identifier consists of only a single character - --> tests/ui/min_ident_chars.rs:151:8 + --> tests/ui/min_ident_chars.rs:151:10 | LL | fn f(g: i32); - | ^ + | ^ error: this identifier consists of only a single character --> tests/ui/min_ident_chars.rs:156:8 @@ -280,16 +280,16 @@ LL | trait A { | ^ error: this identifier consists of only a single character - --> tests/ui/min_ident_chars.rs:180:14 + --> tests/ui/min_ident_chars.rs:180:12 | LL | fn f(h: [u32; 0]); - | ^ + | ^ error: this identifier consists of only a single character - --> tests/ui/min_ident_chars.rs:180:12 + --> tests/ui/min_ident_chars.rs:180:14 | LL | fn f(h: [u32; 0]); - | ^ + | ^ error: this identifier consists of only a single character --> tests/ui/min_ident_chars.rs:192:41 diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 420b01102e41e..571a9ff920040 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -85,15 +85,16 @@ hir-stats Ty 720 (NN.N%) 15 48 hir-stats - Ptr 48 (NN.N%) 1 hir-stats - Ref 48 (NN.N%) 1 hir-stats - Path 624 (NN.N%) 13 -hir-stats Generics 560 (NN.N%) 10 56 -hir-stats Pat 400 (NN.N%) 5 80 +hir-stats Pat 560 (NN.N%) 7 80 hir-stats - Struct 80 (NN.N%) 1 hir-stats - Wild 80 (NN.N%) 1 -hir-stats - Binding 240 (NN.N%) 3 +hir-stats - Binding 400 (NN.N%) 5 +hir-stats Generics 560 (NN.N%) 10 56 hir-stats GenericParam 400 (NN.N%) 5 80 hir-stats Block 288 (NN.N%) 6 48 hir-stats GenericBound 256 (NN.N%) 4 64 hir-stats - Trait 256 (NN.N%) 4 +hir-stats Param 160 (NN.N%) 4 40 hir-stats Attribute 160 (NN.N%) 4 40 hir-stats Variant 144 (NN.N%) 2 72 hir-stats GenericArgs 144 (NN.N%) 3 48 @@ -107,8 +108,6 @@ hir-stats Arm 80 (NN.N%) 2 40 hir-stats WherePredicate 72 (NN.N%) 3 24 hir-stats - BoundPredicate 72 (NN.N%) 3 hir-stats InlineAsm 72 (NN.N%) 1 72 -hir-stats Body 72 (NN.N%) 3 24 -hir-stats Param 64 (NN.N%) 2 32 hir-stats Local 64 (NN.N%) 1 64 hir-stats GenericArg 64 (NN.N%) 4 16 hir-stats - Type 16 (NN.N%) 1 @@ -116,9 +115,10 @@ hir-stats - Lifetime 48 (NN.N%) 3 hir-stats ExprField 40 (NN.N%) 1 40 hir-stats Mod 32 (NN.N%) 1 32 hir-stats Lifetime 28 (NN.N%) 1 28 +hir-stats Body 24 (NN.N%) 3 8 hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_592 172 +hir-stats Total 8_800 176 hir-stats ================================================================ diff --git a/tests/ui/thir-print/c-variadic.stdout b/tests/ui/thir-print/c-variadic.stdout index 466825e4dc116..b7e431e761a56 100644 --- a/tests/ui/thir-print/c-variadic.stdout +++ b/tests/ui/thir-print/c-variadic.stdout @@ -17,7 +17,7 @@ params: [ } Param { ty: std::ffi::VaList<'{erased}> - ty_span: None + ty_span: Some($DIR/c-variadic.rs:4:37: 4:40 (#0)) self_kind: None hir_id: Some(HirId(DefId(0:3 ~ c_variadic[a5de]::foo).3)) param: Some( From 6fa06b012e4d6f73f3b548ff836b332cc629e834 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 10:29:55 +0200 Subject: [PATCH 02/12] Remove `Param::ty_span` field --- compiler/rustc_ast_lowering/src/delegation/mod.rs | 2 -- compiler/rustc_ast_lowering/src/expr.rs | 1 - compiler/rustc_ast_lowering/src/item.rs | 2 -- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_borrowck/src/diagnostics/move_errors.rs | 2 +- compiler/rustc_hir/src/hir.rs | 3 +-- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_typeck/src/check.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 8 ++++---- compiler/rustc_hir_typeck/src/gather_locals.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 8 ++++---- .../src/error_reporting/infer/need_type_info.rs | 4 ++-- .../infer/nice_region_error/placeholder_error.rs | 2 +- .../src/error_reporting/infer/suggest.rs | 4 ++-- .../src/error_reporting/traits/suggestions.rs | 4 ++-- .../rustc_trait_selection/src/traits/dyn_compatibility.rs | 4 ++-- src/tools/clippy/clippy_lints/src/from_over_into.rs | 2 +- .../clippy/clippy_lints/src/manual_is_ascii_check.rs | 6 +++--- tests/ui/stats/input-stats.stderr | 4 ++-- tests/ui/traits/bound/not-on-bare-trait.stderr | 4 ++-- 20 files changed, 30 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs index c90e57ce7142e..0cc7d8a415c25 100644 --- a/compiler/rustc_ast_lowering/src/delegation/mod.rs +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -130,7 +130,6 @@ impl<'hir> LoweringContext<'_, 'hir> { )), span, }), - ty_span: param.ty_span, param_span: param.param_span, } })); @@ -230,7 +229,6 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Param { hir_id, pat, - ty_span: span, param_span: span, ty: self.arena.alloc(hir::Ty { #[allow(deprecated)] diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f2933559d6ca2..4e8966b474ba2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -897,7 +897,6 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: self.next_id(), pat, ty: input_ty, - ty_span: self.lower_span(span), param_span: self.lower_span(span), }; let params = arena_vec![self; param]; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 985b4d7d53b52..e943acb8d84f9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1249,7 +1249,6 @@ impl<'hir> LoweringContext<'_, 'hir> { span: self.lower_span(param.ty.span), hir_id, }), - ty_span: self.lower_span(param.ty.span), param_span: self.lower_span(param.span), } } @@ -1441,7 +1440,6 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: parameter.hir_id, pat: new_parameter_pat, ty: parameter.ty, - ty_span: self.lower_span(parameter.ty_span), param_span: self.lower_span(parameter.param_span), }; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2d6f38305ebb7..5ab93953410eb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1977,7 +1977,6 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: hir_param.hir_id, pat: hir_param.pat, ty: self.arena.alloc(ty), - ty_span: hir_param.ty_span, param_span: hir_param.param_span, } }, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 6db001e8334f5..563c33e750606 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -847,7 +847,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { hir::Node::Param(param) => { // Instead of pointing at the path where we access the value within a // closure, we point at the type of the outer `fn` argument. - param.ty_span + param.ty.span } hir::Node::LetStmt(stmt) => match (stmt.ty, stmt.init) { // We point at the type of the outer let-binding. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 68f3ec26f9516..f00c01474ce5d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3733,7 +3733,6 @@ pub struct Param<'hir> { pub hir_id: HirId, pub pat: &'hir Pat<'hir>, pub ty: &'hir Ty<'hir>, - pub ty_span: Span, pub param_span: Span, } @@ -5290,7 +5289,7 @@ mod size_asserts { static_assert_size!(Item<'_>, 88); static_assert_size!(ItemKind<'_>, 64); static_assert_size!(LetStmt<'_>, 64); - static_assert_size!(Param<'_>, 40); + static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 80); static_assert_size!(PatKind<'_>, 56); static_assert_size!(Path<'_>, 40); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 7293fb6254569..ed62b8d044796 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -546,7 +546,7 @@ pub trait Visitor<'v>: Sized { } pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result { - let Param { hir_id, pat, ty, ty_span: _, param_span: _ } = param; + let Param { hir_id, pat, ty, param_span: _ } = param; try_visit!(visitor.visit_ty_unambig(*ty)); try_visit!(visitor.visit_id(*hir_id)); visitor.visit_pat(pat) diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 759f1a581afb8..36933939d6813 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -92,7 +92,7 @@ pub(super) fn check_fn<'a, 'tcx>( if !params_can_be_unsized || fn_sig.abi() == rustc_abi::ExternAbi::RustTail { fcx.require_type_is_sized( param_ty, - param.ty_span, + param.ty.span, // ty.span == binding_span iff this is a closure parameter with no type ascription, // or if it's an implicit `self` parameter ObligationCauseCode::SizedArgumentType( diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 9827e1be5dee3..f40d78461c749 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -785,8 +785,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { primary_span = init.span; post_message = " value"; } - hir::Node::Param(hir::Param { ty_span, .. }) => { - primary_span = *ty_span; + hir::Node::Param(hir::Param { ty, .. }) => { + primary_span = ty.span; post_message = " parameter type"; } _ => {} @@ -880,7 +880,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) // The pattern we have is an fn argument. - && let hir::Node::Param(hir::Param { ty_span, .. }) = + && let hir::Node::Param(hir::Param { ty, .. }) = self.tcx.parent_hir_node(pat.hir_id) && let item = self.tcx.hir_get_parent_item(pat.hir_id) && let item = self.tcx.hir_owner_node(item) @@ -894,7 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .inputs .iter() .filter_map(|param| match param.ty.kind { - hir::TyKind::Ref(lt, inner_ty, mutbl) if param.ty.span == *ty_span => Some((lt, inner_ty, mutbl)), + hir::TyKind::Ref(lt, inner_ty, mutbl) if param.ty.span == ty.span => Some((lt, inner_ty, mutbl)), _ => None, }) .next() diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 21954203a705a..8ff3a1935e422 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { pub(crate) fn gather_from_param(fcx: &'a FnCtxt<'a, 'tcx>, param: &'tcx hir::Param<'tcx>) { let mut visitor = GatherLocalsVisitor { fcx, - outermost_fn_param_pat: Some((param.ty_span, param.hir_id)), + outermost_fn_param_pat: Some((param.ty.span, param.hir_id)), }; visitor.visit_pat(param.pat); } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 16c51ca625dcd..88f0b031749c8 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1425,8 +1425,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match binding_parent { - hir::Node::Param(hir::Param { ty_span, pat, .. }) - if pat.span != *ty_span + hir::Node::Param(hir::Param { ty, pat, .. }) + if pat.span != ty.span && pinned.is_pinned() && !tcx.features().pin_ergonomics() => { @@ -1435,12 +1435,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Check that there is explicit type (ie this is not a closure param with inferred type) // so we don't suggest moving something to the type that does not exist - hir::Node::Param(hir::Param { ty_span, pat, .. }) if pat.span != *ty_span => { + hir::Node::Param(hir::Param { ty, pat, .. }) if pat.span != ty.span => { err.multipart_suggestion( format!("to take parameter `{binding}` by reference, move `&{pin_and_mut}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), - (ty_span.shrink_to_lo(), format!("&{}", pinned.prefix_str(mutbl))), + (ty.span.shrink_to_lo(), format!("&{}", pinned.prefix_str(mutbl))), ], Applicability::MachineApplicable ); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 843b04ca65bae..ef9eb5e6e70d5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1384,9 +1384,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { for param in decl.inputs { debug!( "param: span {:?}, ty_span {:?}, pat.span {:?}", - param.param_span, param.ty_span, param.pat.span + param.param_span, param.ty.span, param.pat.span ); - if param.ty_span != param.pat.span { + if param.ty.span != param.pat.span { debug!("skipping param: has explicit type"); continue; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 76462cf6f4f21..4b4c9c7067b8e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -474,7 +474,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { .zip(input_tys.iter()) .filter_map(|(param, ty)| { // ty_span == pat.span means no explicit type annotation was written. - if param.ty_span == param.pat.span + if param.ty.span == param.pat.span && ty.is_suggestable(self.tcx(), false) { Some((param.pat.span.shrink_to_hi(), format!(": {ty}"))) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 561ea43272943..148e5623c4900 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -771,7 +771,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { // If the expected region is late bound, the found region is not, and users are asking compiler // to infer the type, we can suggest adding `: &_`. - if param_hir.pat.span == param_hir.ty_span { + if param_hir.pat.span == param_hir.ty.span { // for `|x|`, `|_|`, `|x: impl Foo|` let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) @@ -786,7 +786,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { else { return; }; - let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty_span) + let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty.span) else { return; }; 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 aecacf4f63692..17e424d4aac86 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4215,7 +4215,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } Node::Param(param) => { err.span_suggestion_verbose( - param.ty_span.shrink_to_lo(), + param.ty.span.shrink_to_lo(), "function arguments must have a statically known size, borrowed types \ always have a known size", "&", @@ -5771,7 +5771,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); let assocs_in_this_method = self.probe_assoc_types_at_expr( &type_diffs, - param.ty_span, + param.ty.span, prev_ty, param.hir_id, param_env, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 97d96ab784ba7..e56b188946fbb 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -541,9 +541,9 @@ fn virtual_call_violations_for_method<'tcx>( } hir::TraitFn::Provided(_body_id) if let Some(p) = sig.decl.inputs.get(0) - && p.param_span.eq_ctxt(p.ty_span) => + && p.param_span.eq_ctxt(p.ty.span) => { - Some(p.param_span.to(p.ty_span)) + Some(p.param_span.to(p.ty.span)) } _ => None, } diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 00c02bc6db93e..79fa04a032ee6 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -216,7 +216,7 @@ fn convert_to_from( (impl_item.ident.span, String::from("from")), // fn into([mut] self: U) -> T -> fn into([mut] val: T) -> T // ~~~~~~~ ~~~~~~ - (self_ident.span.to(self_param.ty_span), format!("val: {from}")), + (self_ident.span.to(self_param.ty.span), format!("val: {from}")), ]; if let FnRetTy::Return(_) = sig.decl.output { diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index 8d9a45f2bf4ed..8ca7cc0c4d02b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -136,12 +136,12 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { fn get_ty_sugg<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'_>) -> Option<(Span, Ty<'tcx>)> { let local_hid = arg.res_local_id()?; - if let Node::Param(Param { ty_span, param_span, .. }) = cx.tcx.parent_hir_node(local_hid) + if let Node::Param(Param { ty, param_span, .. }) = cx.tcx.parent_hir_node(local_hid) // `ty_span` and `span` are the same for inferred type, thus a type suggestion must be given - && ty_span == param_span + && ty.span == *param_span { let arg_type = cx.typeck_results().expr_ty(arg); - return Some((*ty_span, arg_type)); + return Some((ty.span, arg_type)); } None } diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 571a9ff920040..79b14585939bc 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -94,11 +94,11 @@ hir-stats GenericParam 400 (NN.N%) 5 80 hir-stats Block 288 (NN.N%) 6 48 hir-stats GenericBound 256 (NN.N%) 4 64 hir-stats - Trait 256 (NN.N%) 4 -hir-stats Param 160 (NN.N%) 4 40 hir-stats Attribute 160 (NN.N%) 4 40 hir-stats Variant 144 (NN.N%) 2 72 hir-stats GenericArgs 144 (NN.N%) 3 48 hir-stats FieldDef 144 (NN.N%) 2 72 +hir-stats Param 128 (NN.N%) 4 32 hir-stats FnDecl 120 (NN.N%) 3 40 hir-stats Stmt 96 (NN.N%) 3 32 hir-stats - Expr 32 (NN.N%) 1 @@ -120,5 +120,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_800 176 +hir-stats Total 8_768 176 hir-stats ================================================================ diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 72226391f583d..f05c7c36ca70a 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -30,10 +30,10 @@ LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait.rs:13:12 + --> $DIR/not-on-bare-trait.rs:13:13 | LL | fn bar(_x: (dyn Foo + Send)) { - | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` = help: unsized fn params are gated as an unstable feature From 0b50324133527b883f379ec390546429d66a446d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 12:40:06 +0200 Subject: [PATCH 03/12] Simplify pretty printing of parameters --- compiler/rustc_hir_pretty/src/lib.rs | 86 +++++++------------------ tests/pretty/hir-fn-params.pp | 4 +- tests/pretty/hir-fn-variadic.pp | 4 +- tests/ui/unpretty/exhaustive.hir.stdout | 4 +- 4 files changed, 28 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 6ad58bf39dc25..8893217ad890e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -47,7 +47,6 @@ pub enum Nested { ImplItem(hir::ImplItemId), ForeignItem(hir::ForeignItemId), Body(hir::BodyId), - BodyParamPat(hir::HirId, usize), } pub trait PpAnn { @@ -64,7 +63,6 @@ impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> { Nested::ImplItem(id) => state.print_impl_item(self.hir_impl_item(id)), Nested::ForeignItem(id) => state.print_foreign_item(self.hir_foreign_item(id)), Nested::Body(id) => state.print_expr(self.hir_body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(self.hir_fn_decl(id).inputs[i].pat), } } } @@ -419,7 +417,7 @@ impl<'a> State<'a> { self.pclose(); } hir::TyKind::FnPtr(f) => { - self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_idents); + self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params); } hir::TyKind::UnsafeBinder(unsafe_binder) => { self.print_unsafe_binder(unsafe_binder); @@ -493,7 +491,7 @@ impl<'a> State<'a> { } self.word("})"); } - hir::TyKind::CVarArgs => unreachable!("Filtered out before calling `print_type`"), + hir::TyKind::CVarArgs => {} } self.end(ib) } @@ -512,16 +510,9 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_attrs(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(sig, arg_idents, generics) => { + hir::ForeignItemKind::Fn(sig, _, generics) => { let (cb, ib) = self.head(""); - self.print_fn( - sig.header, - Some(item.ident.name), - generics, - sig.decl, - arg_idents, - None, - ); + self.print_fn(sig.header, Some(item.ident.name), generics, sig.decl); self.end(ib); self.word(";"); self.end(cb) @@ -653,14 +644,7 @@ impl<'a> State<'a> { } hir::ItemKind::Fn { ident, sig, generics, body, .. } => { let (cb, ib) = self.head(""); - self.print_fn( - sig.header, - Some(ident.name), - generics, - sig.decl, - &[], - Some(item.hir_id()), - ); + self.print_fn(sig.header, Some(ident.name), generics, sig.decl); self.word(" "); self.end(ib); self.end(cb); @@ -976,15 +960,8 @@ impl<'a> State<'a> { } } - fn print_method_sig( - &mut self, - ident: Ident, - m: &hir::FnSig<'_>, - generics: &hir::Generics<'_>, - arg_idents: &[Option], - body_id: Option, - ) { - self.print_fn(m.header, Some(ident.name), generics, m.decl, arg_idents, body_id); + fn print_method_sig(&mut self, ident: Ident, m: &hir::FnSig<'_>, generics: &hir::Generics<'_>) { + self.print_fn(m.header, Some(ident.name), generics, m.decl); } fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) { @@ -996,13 +973,13 @@ impl<'a> State<'a> { hir::TraitItemKind::Const(ty, default) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => { - self.print_method_sig(ti.ident, sig, ti.generics, arg_idents, None); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(_)) => { + self.print_method_sig(ti.ident, sig, ti.generics); self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let (cb, ib) = self.head(""); - self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(ti.hir_id())); + self.print_method_sig(ti.ident, sig, ti.generics); self.nbsp(); self.end(ib); self.end(cb); @@ -1027,7 +1004,7 @@ impl<'a> State<'a> { } hir::ImplItemKind::Fn(ref sig, body) => { let (cb, ib) = self.head(""); - self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(ii.hir_id())); + self.print_method_sig(ii.ident, sig, ii.generics); self.nbsp(); self.end(ib); self.end(cb); @@ -1693,7 +1670,7 @@ impl<'a> State<'a> { self.print_constness(constness); self.print_capture_clause(capture_clause); - self.print_closure_params(fn_decl, expr.hir_id); + self.print_closure_params(fn_decl); self.space(); // This is a bare expression. @@ -2280,8 +2257,6 @@ impl<'a> State<'a> { name: Option, generics: &hir::Generics<'_>, decl: &hir::FnDecl<'_>, - arg_idents: &[Option], - body_id: Option, ) { self.print_fn_header_info(header); @@ -2292,30 +2267,16 @@ impl<'a> State<'a> { self.print_generic_params(generics.params); self.popen(); - // Make sure we aren't supplied *both* `arg_idents` and `body_id`. - assert!(arg_idents.is_empty() || body_id.is_none()); let mut i = 0; - let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| { - if Some(i) == decl.splatted().map(usize::from) { - s.word("#[rustc_splat]"); - } + let mut print_arg = |s: &mut Self, param: &hir::Param<'_>| { + s.print_attrs(s.attrs(param.hir_id)); if i == 0 && decl.implicit_self().has_implicit_self() { s.print_implicit_self(&decl.implicit_self()); } else { - if let Some(arg_ident) = arg_idents.get(i) { - if let Some(arg_ident) = arg_ident { - s.word(arg_ident.to_string()); - s.word(":"); - s.space(); - } - } else if let Some(body_id) = body_id { - s.ann.nested(s, Nested::BodyParamPat(body_id, i)); - s.word(":"); - s.space(); - } - if let Some(ty) = ty { - s.print_type(ty); - } + s.print_pat(param.pat); + s.word(":"); + s.space(); + s.print_type(param.ty); } i += 1; }; @@ -2324,7 +2285,7 @@ impl<'a> State<'a> { decl.inputs.iter().filter(|param| !matches!(param.ty.kind, hir::TyKind::CVarArgs)), |s, param| { let ib = s.ibox(INDENT_UNIT); - print_arg(s, Some(param.ty)); + print_arg(s, param); s.end(ib); }, ); @@ -2332,7 +2293,7 @@ impl<'a> State<'a> { if decl.inputs.len() != 1 { self.word(", "); } - print_arg(self, None); + print_arg(self, decl.inputs.last().unwrap()); self.word("..."); } self.pclose(); @@ -2341,13 +2302,13 @@ impl<'a> State<'a> { self.print_where_clause(generics) } - fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::HirId) { + fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>) { self.word("|"); let mut i = 0; self.commasep(Inconsistent, decl.inputs, |s, param| { let ib = s.ibox(INDENT_UNIT); - s.ann.nested(s, Nested::BodyParamPat(body_id, i)); + s.print_pat(param.pat); i += 1; if let hir::TyKind::Infer(()) = param.ty.kind { @@ -2606,7 +2567,6 @@ impl<'a> State<'a> { decl: &hir::FnDecl<'_>, name: Option, generic_params: &[hir::GenericParam<'_>], - arg_idents: &[Option], ) { let ib = self.ibox(INDENT_UNIT); self.print_formal_generic_params(generic_params); @@ -2621,8 +2581,6 @@ impl<'a> State<'a> { name, generics, decl, - arg_idents, - None, ); self.end(ib); } diff --git a/tests/pretty/hir-fn-params.pp b/tests/pretty/hir-fn-params.pp index 15373bba24d3f..82ecb09f61f72 100644 --- a/tests/pretty/hir-fn-params.pp +++ b/tests/pretty/hir-fn-params.pp @@ -26,12 +26,12 @@ // because they had similar problems. But the pretty-printing tests currently // can't contain compile errors. -fn bare_fn(x: fn(u32, _: u32, a: u32)) { } +fn bare_fn(x: fn(_: u32, _: u32, a: u32)) { } extern "C" { unsafe fn foreign_fn(_: u32, a: u32); } trait T { - fn trait_fn(u32, _: u32, a: u32); + fn trait_fn(_: u32, _: u32, a: u32); } diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index cdf61d0cb1158..d7860d24da31c 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -15,8 +15,8 @@ fn main() { fn g1(_: extern "C" fn(_: u8, va: ...)) { } fn g2(_: extern "C" fn(_: u8, _: ...)) { } - fn g3(_: extern "C" fn(u8, va: ...)) { } - fn g4(_: extern "C" fn(u8, _: ...)) { } + fn g3(_: extern "C" fn(_: u8, va: ...)) { } + fn g4(_: extern "C" fn(_: u8, _: ...)) { } fn g5(_: extern "C" fn(va: ...)) { } fn g6(_: extern "C" fn(_: ...)) { } diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 025314709cf6c..f0bca58ea6826 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -517,7 +517,7 @@ mod items { } mod patterns { /// PatKind::Missing - fn pat_missing() { let _: for fn(u32, T, &'_ str); } + fn pat_missing() { let _: for fn(_: u32, _: T, _: &'_ str); } /// PatKind::Wild fn pat_wild() { let _; } /// PatKind::Ident @@ -624,7 +624,7 @@ mod types { fn ty_bare_fn() { let _: fn(); let _: fn() -> (); - let _: fn(T); + let _: fn(_: T); let _: fn(t: T); let _: fn(); let _: for<'a> fn(); From 35785654cc2a28fb24e8472f6b5e858b461582e6 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 13:19:00 +0200 Subject: [PATCH 04/12] Simplify cleaning of parameters in rustdoc --- src/librustdoc/clean/mod.rs | 81 +++++---------------- tests/rustdoc-html/constant/assoc-consts.rs | 2 +- tests/rustdoc-html/fn-pointer-arg-name.rs | 4 +- 3 files changed, 22 insertions(+), 65 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 85cee5eb427c0..fe2bc513dea3c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -50,7 +50,7 @@ use rustc_middle::ty::{ self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_span::hygiene::{AstPass, MacroKind}; -use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::symbol::{Symbol, kw}; use rustc_span::{ExpnKind, bug, span_bug}; use rustc_trait_selection::traits::wf::object_region_bounds; use tracing::{debug, instrument}; @@ -1104,8 +1104,7 @@ fn clean_fn_or_proc_macro<'tcx>( match macro_kind { Some(kind) => clean_proc_macro(item, name, kind, cx.tcx), None => { - let mut func = - clean_function(cx, sig, generics, ParamsSrc::Body, item.owner_id.to_def_id()); + let mut func = clean_function(cx, sig, generics, item.owner_id.to_def_id()); clean_fn_decl_legacy_const_generics(&mut func, attrs); FunctionItem(func) } @@ -1134,16 +1133,10 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[rustc_attr_ } } -enum ParamsSrc<'tcx> { - Body, - Idents(&'tcx [Option]), -} - fn clean_function<'tcx>( cx: &mut DocContext<'tcx>, sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'tcx>, - params: ParamsSrc<'tcx>, def_id: DefId, ) -> Box { let (generics, decl) = enter_impl_trait(cx, |cx| { @@ -1159,13 +1152,7 @@ fn clean_function<'tcx>( let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); clean_poly_fn_sig(cx, Some(def_id), sig) } else { - let params = match params { - ParamsSrc::Body => clean_params_via_body(cx, sig.decl), - // Let's not perpetuate anon params from Rust 2015; use `_` for them. - ParamsSrc::Idents(idents) => clean_params(cx, sig.decl, idents, |ident| { - Some(ident.map_or(kw::Underscore, |ident| ident.name)) - }), - }; + let params = clean_params(cx, sig.decl, false); clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params) }; (generics, decl) @@ -1173,34 +1160,21 @@ fn clean_function<'tcx>( Box::new(Function { decl, generics }) } -fn clean_params<'tcx>( - cx: &mut DocContext<'tcx>, +fn clean_params( + cx: &mut DocContext<'_>, decl: &hir::FnDecl<'_>, - idents: &[Option], - postprocess: impl Fn(Option) -> Option, + remove_missing: bool, ) -> Vec { decl.inputs .iter() .filter(|param| !matches!(param.ty.kind, hir::TyKind::CVarArgs)) .enumerate() .map(|(i, param)| Parameter { - name: postprocess(idents[i]), - type_: clean_ty(param.ty, cx), - is_const: false, - is_splat: decl.splatted().is_some_and(|j| j as usize == i), - }) - .collect() -} - -fn clean_params_via_body<'tcx>( - cx: &mut DocContext<'tcx>, - decl: &hir::FnDecl<'tcx>, -) -> Vec { - decl.inputs - .iter() - .enumerate() - .map(|(i, param)| Parameter { - name: Some(name_from_pat(param.pat)), + name: if remove_missing && matches!(param.pat.kind, hir::PatKind::Missing) { + None + } else { + Some(name_from_pat(param.pat)) + }, type_: clean_ty(param.ty, cx), is_const: false, is_splat: decl.splatted().is_some_and(|j| j as usize == i), @@ -1303,17 +1277,11 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(_)) => { - let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body, local_did); + let m = clean_function(cx, sig, trait_item.generics, local_did); MethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => { - let m = clean_function( - cx, - sig, - trait_item.generics, - ParamsSrc::Idents(idents), - local_did, - ); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(_)) => { + let m = clean_function(cx, sig, trait_item.generics, local_did); RequiredMethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } hir::TraitItemKind::Type(bounds, Some(default)) => { @@ -1354,7 +1322,7 @@ pub(crate) fn clean_impl_item<'tcx>( type_: clean_ty(ty, cx), })), hir::ImplItemKind::Fn(ref sig, _) => { - let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body, local_did); + let m = clean_function(cx, sig, impl_.generics, local_did); let defaultness = match impl_.impl_kind { hir::ImplItemImplKind::Inherent { .. } => hir::Defaultness::Final, hir::ImplItemImplKind::Trait { defaultness, .. } => defaultness, @@ -2744,17 +2712,7 @@ fn clean_bare_fn_ty<'tcx>( .filter(|p| !is_elided_lifetime(p)) .map(|x| clean_generic_param(cx, None, x)) .collect(); - // Since it's more conventional stylistically, elide the name of all params called `_` - // unless there's at least one interestingly named param in which case don't elide any - // name since mixing named and unnamed params is less legible. - let filter = |ident: Option| { - ident.map(|ident| ident.name).filter(|&ident| ident != kw::Underscore) - }; - let fallback = - bare_fn.param_idents.iter().copied().find_map(filter).map(|_| kw::Underscore); - let params = clean_params(cx, bare_fn.decl, bare_fn.param_idents, |ident| { - filter(ident).or(fallback) - }); + let params = clean_params(cx, bare_fn.decl, true); let decl = clean_fn_decl_with_params(cx, bare_fn.decl, None, params); (generic_params, decl) }); @@ -3389,10 +3347,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem( - clean_function(cx, &sig, generics, ParamsSrc::Idents(idents), def_id), - sig.header.safety(), - ), + hir::ForeignItemKind::Fn(sig, _, generics) => { + ForeignFunctionItem(clean_function(cx, &sig, generics, def_id), sig.header.safety()) + } hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: None }, safety, diff --git a/tests/rustdoc-html/constant/assoc-consts.rs b/tests/rustdoc-html/constant/assoc-consts.rs index 0994ec7517e3e..a52835068bf3e 100644 --- a/tests/rustdoc-html/constant/assoc-consts.rs +++ b/tests/rustdoc-html/constant/assoc-consts.rs @@ -45,7 +45,7 @@ pub fn f(_: &(ToString + 'static)) {} impl Bar { //@ has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \ - // "const F: fn(&(dyn ToString + 'static))" + // "const F: fn(_: &(dyn ToString + 'static))" pub const F: fn(_: &(ToString + 'static)) = f; } diff --git a/tests/rustdoc-html/fn-pointer-arg-name.rs b/tests/rustdoc-html/fn-pointer-arg-name.rs index 0ee1964511a1d..6bf35472d66a5 100644 --- a/tests/rustdoc-html/fn-pointer-arg-name.rs +++ b/tests/rustdoc-html/fn-pointer-arg-name.rs @@ -5,9 +5,9 @@ pub fn f(callback: fn(len: usize, foo: u32)) {} //@ has foo/fn.g.html -//@ has - '//pre[@class="rust item-decl"]' 'pub fn g(_: fn(usize, u32))' +//@ has - '//pre[@class="rust item-decl"]' 'pub fn g(_: fn(usize, _: u32))' pub fn g(_: fn(usize, _: u32)) {} //@ has foo/fn.mixed.html -//@ has - '//pre[@class="rust item-decl"]' 'pub fn mixed(_: fn(_: usize, foo: u32))' +//@ has - '//pre[@class="rust item-decl"]' 'pub fn mixed(_: fn(usize, foo: u32))' pub fn mixed(_: fn(usize, foo: u32)) {} From 1508014fbe66875f56e5eb0a01a7646ef9600415 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 13:20:25 +0200 Subject: [PATCH 05/12] Remove the now unused `FnPtrTy::param_idents` --- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_hir/src/hir.rs | 3 --- 2 files changed, 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5ab93953410eb..a3ccd4b583bee 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1572,7 +1572,6 @@ impl<'hir> LoweringContext<'_, 'hir> { DiscardParams::Yes, params, ), - param_idents: self.lower_fn_params_to_idents(&f.decl), })); return hir::Ty { kind, span: self.lower_span(t.span), hir_id }; } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f00c01474ce5d..6c858444d685c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3411,9 +3411,6 @@ pub struct FnPtrTy<'hir> { pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, - // `Option` because bare fn parameter identifiers are optional. We also end up - // with `None` in some error cases, e.g. invalid parameter patterns. - pub param_idents: &'hir [Option], } #[derive(Debug, Clone, Copy, StableHash)] From a00a6094c98050847f3dc10ae60d600292e64d5d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 13:40:54 +0200 Subject: [PATCH 06/12] Simplify parameter span in `virtual_call_violations_for_method` --- .../src/traits/dyn_compatibility.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e56b188946fbb..be5906eb2d673 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -520,7 +520,7 @@ fn virtual_call_violations_for_method<'tcx>( if receiver_ty != tcx.types.self_param { if !receiver_is_dispatchable(tcx, method, receiver_ty) { let span_n_lt = if let Some(hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, trait_fn), + kind: hir::TraitItemKind::Fn(sig, _), .. })) = tcx.hir_get_if_local(method.def_id).as_ref() { @@ -533,21 +533,7 @@ fn virtual_call_violations_for_method<'tcx>( _ => sym::empty, }; // Get the `Span` for all of `self: Ty`, not just `Ty`. - match trait_fn { - hir::TraitFn::Required([Some(name), ..]) - if name.span.eq_ctxt(sig.decl.inputs[0].ty.span) => - { - Some(name.span.to(sig.decl.inputs[0].ty.span)) - } - hir::TraitFn::Provided(_body_id) - if let Some(p) = sig.decl.inputs.get(0) - && p.param_span.eq_ctxt(p.ty.span) => - { - Some(p.param_span.to(p.ty.span)) - } - _ => None, - } - .map(|sp| (sp, lt)) + sig.decl.inputs.get(0).map(|p| (p.param_span.to(p.ty.span), lt)) } else { None }; From 4b86f0b43d37fabdc2334ffc5838e777956da1a8 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 13:45:18 +0200 Subject: [PATCH 07/12] Remove now unreachable branches in `fn_arg_idents` --- compiler/rustc_middle/src/hir/mod.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index c6aa73098109c..d8b719fe0f18f 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -479,16 +479,6 @@ pub fn provide(providers: &mut Providers) { let node = tcx.hir_node_by_def_id(def_id); if let Some(decl) = node.fn_decl() { tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(decl)) - } else if let Node::TraitItem(&TraitItem { - kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), - .. - }) - | Node::ForeignItem(&ForeignItem { - kind: ForeignItemKind::Fn(_, idents, _), - .. - }) = node - { - idents } else { span_bug!( tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)), From d35171cf7ab7d78e2298aabb3e9189df489f3e5b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 14:11:51 +0200 Subject: [PATCH 08/12] Simplify `get_hir_param_info` --- compiler/rustc_hir/src/hir.rs | 18 +++ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 119 ++++-------------- .../extern-fn-arg-names.stderr | 2 +- tests/ui/c-variadic/variadic-ffi-1.stderr | 4 +- tests/ui/delegation/glob-glob-conflict.stderr | 4 +- .../self-mapping-arguments-errors.stderr | 4 +- .../ui/delegation/self-mapping-output.stderr | 12 +- tests/ui/error-codes/E0060.stderr | 2 +- tests/ui/fn/param-mismatch-foreign.stderr | 2 +- tests/ui/fn/param-mismatch-trait-fn.stderr | 2 +- .../relate-bound-region-ice-144033.stderr | 2 +- tests/ui/methods/issues/issue-61525.stderr | 2 +- tests/ui/mismatched_types/issue-26480.stderr | 2 +- tests/ui/suggestions/suggest-null-ptr.stderr | 8 +- ...missing-associated-type-restriction.stderr | 2 +- tests/ui/traits/issue-52893.stderr | 2 +- 16 files changed, 68 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6c858444d685c..824acf002b5da 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3733,6 +3733,24 @@ pub struct Param<'hir> { pub param_span: Span, } +impl<'hir> Param<'hir> { + pub fn display(&self, idx: usize) -> impl '_ + fmt::Display { + struct D<'a>(&'a Param<'a>, usize); + impl fmt::Display for D<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // A "unique" param name is one that (a) exists, and (b) is guaranteed to be unique + // among the parameters, i.e. `_` does not count. + if let PatKind::Binding(_, _, ident, _) = self.0.pat.kind { + write!(f, "`{ident}`") + } else { + write!(f, "parameter #{}", self.1 + 1) + } + } + } + D(self, idx) + } +} + /// Error type for splatted argument index errors. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SplattedArgIndexError { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c5b444ec5083e..16151e2126409 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1,5 +1,5 @@ +use std::iter; use std::ops::Deref; -use std::{fmt, iter}; use itertools::Itertools; use rustc_ast as ast; @@ -1736,7 +1736,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { struct MismatchedParam<'a> { idx: ExpectedIdx, generic: GenericIdx, - param: &'a FnParam<'a>, + param: &'a hir::Param<'a>, deps: SmallVec<[ExpectedIdx; 4]>, } @@ -1759,7 +1759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }), Some((None, expected_param)) => { // Still mark the mismatched parameter - spans.push_span_label(expected_param.span(), ""); + spans.push_span_label(expected_param.param_span, ""); } None => { if tuple_arguments.is_splatted() { @@ -1792,7 +1792,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } else { // Still mark mismatched parameters - spans.push_span_label(param.span(), ""); + spans.push_span_label(param.param_span, ""); None } }, @@ -1830,7 +1830,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { params_with_generics[dep].1.display(dep.as_usize()).to_string() }) { spans.push_span_label( - param.param.span(), + param.param.param_span, format!( "this parameter needs to match the {} type of {deps_list}", self.deeply_resolve_ignoring_regions( @@ -1841,7 +1841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { // Still mark mismatched parameters - spans.push_span_label(param.param.span(), ""); + spans.push_span_label(param.param.param_span, ""); } } // Highlight each parameter being depended on for a generic type. @@ -1853,7 +1853,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param.param.display(param.idx.as_usize()).to_string() }) { spans.push_span_label( - param.span(), + param.param_span, format!( "{deps_list} need{} to match the {} type of this parameter", pluralize!((deps.len() != 1) as u32), @@ -2057,36 +2057,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns the parameters of a function, with their generic parameters if those are the full /// type of that parameter. - /// - /// Returns `None` if the body is not a named function (e.g. a closure). fn get_hir_param_info( &self, def_id: DefId, is_method: bool, - ) -> Option<(IndexVec, FnParam<'_>)>, &hir::Generics<'_>)> + ) -> Option<(IndexVec, &'_ hir::Param<'_>)>, &hir::Generics<'_>)> { - let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? { + let (sig, generics) = match self.tcx.hir_get_if_local(def_id)? { hir::Node::TraitItem(&hir::TraitItem { generics, - kind: hir::TraitItemKind::Fn(sig, trait_fn), + kind: hir::TraitItemKind::Fn(sig, _), .. - }) => match trait_fn { - hir::TraitFn::Required(params) => (sig, generics, None, Some(params)), - hir::TraitFn::Provided(body) => (sig, generics, Some(body), None), - }, - hir::Node::ImplItem(&hir::ImplItem { + }) + | hir::Node::ImplItem(&hir::ImplItem { generics, - kind: hir::ImplItemKind::Fn(sig, body), + kind: hir::ImplItemKind::Fn(sig, _), .. }) | hir::Node::Item(&hir::Item { - kind: hir::ItemKind::Fn { sig, generics, body, .. }, - .. - }) => (sig, generics, Some(body), None), - hir::Node::ForeignItem(&hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(sig, params, generics), + kind: hir::ItemKind::Fn { sig, generics, .. }, .. + }) + | hir::Node::ForeignItem(&hir::ForeignItem { + kind: hir::ForeignItemKind::Fn(sig, _, generics), .. - }) => (sig, generics, None, Some(params)), + }) => (sig, generics), _ => return None, }; @@ -2112,25 +2106,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }); - match (body_id, params) { - (Some(_), Some(_)) | (None, None) => unreachable!(), - (Some(_body), None) => { - let params = sig.decl.inputs; - let params = params - .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?; - debug_assert_eq!(params.len(), fn_inputs.len()); - Some((fn_inputs.zip(params.iter().map(FnParam::Param)).collect(), generics)) - } - (None, Some(params)) => { - let params = params - .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?; - debug_assert_eq!(params.len(), fn_inputs.len()); - Some(( - fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(), - generics, - )) - } - } + + let params = sig + .decl + .inputs + .get(is_method as usize..sig.decl.inputs.len() - sig.decl.c_variadic() as usize)?; + debug_assert_eq!(params.len(), fn_inputs.len()); + Some((fn_inputs.zip(params).collect(), generics)) } } @@ -2154,57 +2136,6 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { } } -#[derive(Clone, Copy)] -enum FnParam<'hir> { - Param(&'hir hir::Param<'hir>), - Ident(Option), -} - -impl FnParam<'_> { - fn span(&self) -> Span { - match self { - Self::Param(param) => param.param_span, - Self::Ident(ident) => { - if let Some(ident) = ident { - ident.span - } else { - DUMMY_SP - } - } - } - } - - fn display(&self, idx: usize) -> impl '_ + fmt::Display { - struct D<'a>(FnParam<'a>, usize); - impl fmt::Display for D<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // 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::Ident(ident) - if let Some(ident) = ident - && ident.name != kw::Underscore => - { - Some(ident.name) - } - _ => None, - }; - if let Some(unique_name) = unique_name { - write!(f, "`{unique_name}`") - } else { - write!(f, "parameter #{}", self.1 + 1) - } - } - } - D(*self, idx) - } -} - struct FnCallDiagCtxt<'a, 'tcx> { arg_matching_ctxt: ArgMatchingCtxt<'a, 'tcx>, errors: Vec>, diff --git a/tests/ui/argument-suggestions/extern-fn-arg-names.stderr b/tests/ui/argument-suggestions/extern-fn-arg-names.stderr index e4183e6d519ef..8204d53733aad 100644 --- a/tests/ui/argument-suggestions/extern-fn-arg-names.stderr +++ b/tests/ui/argument-suggestions/extern-fn-arg-names.stderr @@ -14,7 +14,7 @@ note: function defined here --> $DIR/extern-fn-arg-names.rs:2:8 | LL | fn dstfn(src: i32, dst: err); - | ^^^^^ --- + | ^^^^^ -------- help: provide the argument | LL | dstfn(1, /* dst */); diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr index b7182887cfb78..e600bea41246e 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.stderr +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -20,7 +20,7 @@ note: function defined here --> $DIR/variadic-ffi-1.rs:22:8 | LL | fn foo(f: isize, x: u8, ...); - | ^^^ - - + | ^^^ -------- ----- help: provide the arguments | LL | foo(/* isize */, /* u8 */); @@ -36,7 +36,7 @@ note: function defined here --> $DIR/variadic-ffi-1.rs:22:8 | LL | fn foo(f: isize, x: u8, ...); - | ^^^ - + | ^^^ ----- help: provide the argument | LL | foo(1, /* u8 */); diff --git a/tests/ui/delegation/glob-glob-conflict.stderr b/tests/ui/delegation/glob-glob-conflict.stderr index 73831c9e48e33..3aa36a417e283 100644 --- a/tests/ui/delegation/glob-glob-conflict.stderr +++ b/tests/ui/delegation/glob-glob-conflict.stderr @@ -34,7 +34,7 @@ note: method defined here --> $DIR/glob-glob-conflict.rs:7:8 | LL | fn method(&self) -> u8; - | ^^^^^^ ---- + | ^^^^^^ ----- help: provide the argument | LL | reuse Trait2::*(/* value */); @@ -59,7 +59,7 @@ note: method defined here --> $DIR/glob-glob-conflict.rs:4:8 | LL | fn method(&self) -> u8; - | ^^^^^^ ---- + | ^^^^^^ ----- help: provide the argument | LL | reuse Trait1::*(/* value */); diff --git a/tests/ui/delegation/self-mapping-arguments-errors.stderr b/tests/ui/delegation/self-mapping-arguments-errors.stderr index cd38ad84aeabf..829351f906f9f 100644 --- a/tests/ui/delegation/self-mapping-arguments-errors.stderr +++ b/tests/ui/delegation/self-mapping-arguments-errors.stderr @@ -58,7 +58,7 @@ note: method defined here --> $DIR/self-mapping-arguments-errors.rs:5:12 | LL | fn add(self, other: Self) -> Self; - | ^^^ ----- + | ^^^ ----------- help: provide the argument | LL ~ }({ @@ -110,7 +110,7 @@ note: method defined here --> $DIR/self-mapping-arguments-errors.rs:34:12 | LL | fn add(self, other: Box) -> Self; - | ^^^ ----- + | ^^^ ---------------- help: store this in the heap by calling `Box::new` | LL | reuse impl MyAdd for W { Box::new(self.0) } diff --git a/tests/ui/delegation/self-mapping-output.stderr b/tests/ui/delegation/self-mapping-output.stderr index 86ce822a1821c..9d79d848039b1 100644 --- a/tests/ui/delegation/self-mapping-output.stderr +++ b/tests/ui/delegation/self-mapping-output.stderr @@ -132,7 +132,7 @@ note: method defined here --> $DIR/self-mapping-output.rs:199:12 | LL | fn method(&self) -> (); - | ^^^^^^ ---- + | ^^^^^^ ----- help: consider borrowing here | LL | reuse Trait::method { &self.0 } @@ -188,7 +188,7 @@ note: method defined here --> $DIR/self-mapping-output.rs:199:12 | LL | fn method(&self) -> (); - | ^^^^^^ ---- + | ^^^^^^ ----- help: consider borrowing here | LL | reuse Trait::method { &self.0 } @@ -245,7 +245,7 @@ note: method defined here --> $DIR/self-mapping-output.rs:237:12 | LL | fn method(&self) -> Self; - | ^^^^^^ ---- + | ^^^^^^ ----- error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:256:29 @@ -293,7 +293,7 @@ note: method defined here --> $DIR/self-mapping-output.rs:237:12 | LL | fn method(&self) -> Self; - | ^^^^^^ ---- + | ^^^^^^ ----- error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:268:29 @@ -341,7 +341,7 @@ note: method defined here --> $DIR/self-mapping-output.rs:282:12 | LL | fn method(&self) -> Self; - | ^^^^^^ ---- + | ^^^^^^ ----- error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:310:31 @@ -358,7 +358,7 @@ note: method defined here --> $DIR/self-mapping-output.rs:282:12 | LL | fn method(&self) -> Self; - | ^^^^^^ ---- + | ^^^^^^ ----- error[E0616]: field `0` of struct `private::W` is private --> $DIR/self-mapping-output.rs:336:36 diff --git a/tests/ui/error-codes/E0060.stderr b/tests/ui/error-codes/E0060.stderr index 7065b623ad325..9bb5e6edbfef6 100644 --- a/tests/ui/error-codes/E0060.stderr +++ b/tests/ui/error-codes/E0060.stderr @@ -8,7 +8,7 @@ note: function defined here --> $DIR/E0060.rs:2:8 | LL | fn printf(_: *const u8, ...) -> u32; - | ^^^^^^ - + | ^^^^^^ ------------ help: provide the argument | LL | unsafe { printf(/* *const u8 */); } diff --git a/tests/ui/fn/param-mismatch-foreign.stderr b/tests/ui/fn/param-mismatch-foreign.stderr index 835e0a3343e9a..ae994bb658f25 100644 --- a/tests/ui/fn/param-mismatch-foreign.stderr +++ b/tests/ui/fn/param-mismatch-foreign.stderr @@ -8,7 +8,7 @@ note: function defined here --> $DIR/param-mismatch-foreign.rs:2:8 | LL | fn foo(x: i32, y: u32, z: i32); - | ^^^ - + | ^^^ ------ help: provide the argument | LL | foo(1i32, /* u32 */, 2i32); diff --git a/tests/ui/fn/param-mismatch-trait-fn.stderr b/tests/ui/fn/param-mismatch-trait-fn.stderr index 28e1bcaaf49dc..6f0f703f26b79 100644 --- a/tests/ui/fn/param-mismatch-trait-fn.stderr +++ b/tests/ui/fn/param-mismatch-trait-fn.stderr @@ -13,7 +13,7 @@ note: associated function defined here --> $DIR/param-mismatch-trait-fn.rs:2:8 | LL | fn same_type(_: T, _: T); - | ^^^^^^^^^ - - - this parameter needs to match the `[X; 1]` type of parameter #1 + | ^^^^^^^^^ - ---- ---- this parameter needs to match the `[X; 1]` type of parameter #1 | | | | | parameter #2 needs to match the `[X; 1]` type of this parameter | parameter #1 and parameter #2 both reference this parameter `T` diff --git a/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr b/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr index 6964e50fb79fb..fdf04f2b46ac5 100644 --- a/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr +++ b/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr @@ -45,7 +45,7 @@ note: method defined here --> $DIR/relate-bound-region-ice-144033.rs:6:8 | LL | fn bar(self, _: I) - | ^^^ - + | ^^^ ---- error: aborting due to 2 previous errors diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr index 13310c41f191d..cca178db9c886 100644 --- a/tests/ui/methods/issues/issue-61525.stderr +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -33,7 +33,7 @@ note: method defined here --> $DIR/issue-61525.rs:2:8 | LL | fn query(self, q: Q); - | ^^^^^ - + | ^^^^^ ---- error: aborting due to 2 previous errors diff --git a/tests/ui/mismatched_types/issue-26480.stderr b/tests/ui/mismatched_types/issue-26480.stderr index ec91caed5e940..8e2683850c5f1 100644 --- a/tests/ui/mismatched_types/issue-26480.stderr +++ b/tests/ui/mismatched_types/issue-26480.stderr @@ -15,7 +15,7 @@ note: function defined here --> $DIR/issue-26480.rs:2:8 | LL | fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64; - | ^^^^^ ----- + | ^^^^^ ---------- help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit | LL | ($arr.len() * size_of($arr[0])).try_into().unwrap()); diff --git a/tests/ui/suggestions/suggest-null-ptr.stderr b/tests/ui/suggestions/suggest-null-ptr.stderr index 5be33d47237d2..bdc625c49c5b1 100644 --- a/tests/ui/suggestions/suggest-null-ptr.stderr +++ b/tests/ui/suggestions/suggest-null-ptr.stderr @@ -12,7 +12,7 @@ note: function defined here --> $DIR/suggest-null-ptr.rs:7:8 | LL | fn foo(ptr: *const u8); - | ^^^ --- + | ^^^ -------------- help: if you meant to create a null pointer, use `std::ptr::null()` | LL - foo(0); @@ -33,7 +33,7 @@ note: function defined here --> $DIR/suggest-null-ptr.rs:9:8 | LL | fn foo_mut(ptr: *mut u8); - | ^^^^^^^ --- + | ^^^^^^^ ------------ help: if you meant to create a null pointer, use `std::ptr::null_mut()` | LL - foo_mut(0); @@ -54,7 +54,7 @@ note: function defined here --> $DIR/suggest-null-ptr.rs:11:8 | LL | fn usize(ptr: *const usize); - | ^^^^^ --- + | ^^^^^ ----------------- help: if you meant to create a null pointer, use `std::ptr::null()` | LL - usize(0); @@ -75,7 +75,7 @@ note: function defined here --> $DIR/suggest-null-ptr.rs:13:8 | LL | fn usize_mut(ptr: *mut usize); - | ^^^^^^^^^ --- + | ^^^^^^^^^ --------------- help: if you meant to create a null pointer, use `std::ptr::null_mut()` | LL - usize_mut(0); diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index df59a28c4b97b..965759b7dd18e 100644 --- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -94,7 +94,7 @@ note: method defined here --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8 | LL | fn funk(&self, _: Self::A); - | ^^^^ - + | ^^^^ ---------- help: consider constraining the associated type `>::A` to `{integer}` | LL | fn bar2>(x: T) { diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index 3c5df82fcdc87..68d496692cd72 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -22,7 +22,7 @@ note: method defined here --> $DIR/issue-52893.rs:11:8 | LL | fn push(self, other: T) -> Self::PushRes; - | ^^^^ ----- + | ^^^^ -------- error: aborting due to 1 previous error From 3bd4d76ad447d75989c8e1a84321305142cc02ee Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 14:37:17 +0200 Subject: [PATCH 09/12] Remove idents argument from `TraitFn::Required` --- compiler/rustc_ast_lowering/src/item.rs | 8 +----- compiler/rustc_hir/src/hir.rs | 12 ++++----- compiler/rustc_hir/src/intravisit.rs | 5 +--- compiler/rustc_hir/src/target_impls.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/collect/dump.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 25 +++++++------------ compiler/rustc_lint/src/nonstandard_style.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 4 +-- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- .../clippy/clippy_lints/src/attrs/mod.rs | 2 +- .../clippy_lints/src/excessive_bools.rs | 2 +- .../src/inline_fn_without_body.rs | 2 +- .../clippy/clippy_lints/src/lifetimes.rs | 24 ++++++------------ .../clippy/clippy_lints/src/types/mod.rs | 2 +- 19 files changed, 39 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e943acb8d84f9..9bb79bf0c4b9e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -850,7 +850,6 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(Fn { sig, ident, generics, body: None, define_opaque, .. }) => { // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. - let idents = self.lower_fn_params_to_idents(&sig.decl); let params = self.arena.alloc_from_iter(sig.decl.inputs.iter().map(|x| self.lower_param(x))); let (generics, sig) = self.lower_method_sig( @@ -870,12 +869,7 @@ impl<'hir> LoweringContext<'_, 'hir> { "only trait methods with default bodies can define opaque types", ); } - ( - *ident, - generics, - hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(idents)), - false, - ) + (*ident, generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required), false) } AssocItemKind::Fn(Fn { sig, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 824acf002b5da..2af96f8c6c840 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2978,7 +2978,7 @@ impl<'hir> TraitItem<'hir> { expect_const, (&'hir Ty<'hir>, Option>), TraitItemKind::Const(ty, rhs), (ty, *rhs); - expect_fn, (&FnSig<'hir>, &TraitFn<'hir>), + expect_fn, (&FnSig<'hir>, &TraitFn), TraitItemKind::Fn(ty, trfn), (ty, trfn); expect_type, (GenericBounds<'hir>, Option<&'hir Ty<'hir>>), @@ -2988,9 +2988,9 @@ impl<'hir> TraitItem<'hir> { /// Represents a trait method's body (or just argument names). #[derive(Debug, Clone, Copy, StableHash)] -pub enum TraitFn<'hir> { +pub enum TraitFn { /// No default body in the trait, just a signature. - Required(&'hir [Option]), + Required, /// Both signature and body are provided in the trait. Provided(BodyId), @@ -3002,7 +3002,7 @@ pub enum TraitItemKind<'hir> { /// An associated constant with an optional value (otherwise `impl`s must contain a value). Const(&'hir Ty<'hir>, Option>), /// An associated function with an optional body. - Fn(FnSig<'hir>, TraitFn<'hir>), + Fn(FnSig<'hir>, TraitFn), /// An associated type with (possibly empty) bounds and optional concrete /// type. Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>), @@ -5314,8 +5314,8 @@ mod size_asserts { static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); static_assert_size!(TraitImplHeader<'_>, 48); - static_assert_size!(TraitItem<'_>, 88); - static_assert_size!(TraitItemKind<'_>, 48); + static_assert_size!(TraitItem<'_>, 80); + static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); // tidy-alphabetical-end diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ed62b8d044796..7f2250bf44d26 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1311,11 +1311,8 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_const_item_rhs, default); } - TraitItemKind::Fn(ref sig, TraitFn::Required(param_idents)) => { + TraitItemKind::Fn(ref sig, TraitFn::Required) => { try_visit!(visitor.visit_fn_decl(sig.decl)); - for ident in param_idents.iter().copied() { - visit_opt!(visitor, visit_ident, ident); - } } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { try_visit!(visitor.visit_fn( diff --git a/compiler/rustc_hir/src/target_impls.rs b/compiler/rustc_hir/src/target_impls.rs index f98a6caaa5e66..87e7a443de622 100644 --- a/compiler/rustc_hir/src/target_impls.rs +++ b/compiler/rustc_hir/src/target_impls.rs @@ -29,7 +29,7 @@ impl From<&hir::TraitItem<'_>> for Target { fn from(trait_item: &hir::TraitItem<'_>) -> Target { match trait_item.kind { TraitItemKind::Const(..) => Target::AssocConst(AssocCtxt::Trait), - TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { + TraitItemKind::Fn(_, hir::TraitFn::Required) => { Target::Method(MethodKind::Trait { body: false }) } TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 76fd59577f248..05d1eaefc72c9 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -936,7 +936,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) - && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + && let (_, hir::TraitFn::Required) = trait_item.expect_fn() { // Skip opaques from RPIT in traits with no default body. } else { diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 9bf62e2846b9d..23560c5a4d1ca 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -60,7 +60,7 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = tcx.hir_expect_opaque_ty(id).origin && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) - && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + && let (_, hir::TraitFn::Required) = trait_item.expect_fn() { continue; } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8893217ad890e..e0595621cf8a6 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -973,7 +973,7 @@ impl<'a> State<'a> { hir::TraitItemKind::Const(ty, default) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(_)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required) => { self.print_method_sig(ti.ident, sig, ti.generics); self.word(";"); } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1ef029f6dc00e..7fd422ea2901e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -4457,25 +4457,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .as_local() .map(|def_id| self.tcx.hir_node_by_def_id(def_id)); if let Some(hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(fn_sig, method), + kind: hir::TraitItemKind::Fn(fn_sig, _), .. })) = id { - let self_first_arg = match method { - hir::TraitFn::Required([ident, ..]) => { - matches!(ident, Some(Ident { name: kw::SelfLower, .. })) - } - hir::TraitFn::Provided(_body_id) => { - fn_sig.decl.inputs.first().is_some_and(|param| { - matches!( - param.pat.kind, - hir::PatKind::Binding(_, _, ident, _) - if ident.name == kw::SelfLower - ) - }) - } - _ => false, - }; + let self_first_arg = + fn_sig.decl.inputs.first().is_some_and(|param| { + matches!( + param.pat.kind, + hir::PatKind::Binding(_, _, ident, _) + if ident.name == kw::SelfLower + ) + }); if !fn_sig.decl.implicit_self().has_implicit_self() && self_first_arg diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 5202ae61cedac..0f915aca524fd 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -418,7 +418,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 38dbf8d428a20..bc3e35a5f61d5 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1311,7 +1311,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> if let hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(parent) - && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + && let (_, hir::TraitFn::Required) = trait_item.expect_fn() { false } else { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 1bd2ca7792e7e..16eaaefb75262 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -146,7 +146,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::TraitItem(trait_method) => match trait_method.kind { hir::TraitItemKind::Const(_, ref default) => default.is_some(), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, - hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) + hir::TraitItemKind::Fn(_, hir::TraitFn::Required) | hir::TraitItemKind::Type(..) => false, }, Node::ImplItem(impl_item) => match impl_item.kind { @@ -267,7 +267,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::TraitItem(trait_method) => { match trait_method.kind { hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Required) => { // Keep going, nothing to get exported } hir::TraitItemKind::Const(_, Some(rhs)) => self.visit_const_item_rhs(rhs), diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 00e4e09adcfe5..791b437998d66 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1812,7 +1812,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { parent, in_trait_or_impl: Some(hir::RpitContext::Trait), } => match tcx.hir_node_by_def_id(parent).expect_trait_item().expect_fn().1 { - hir::TraitFn::Required(_) => false, + hir::TraitFn::Required => false, hir::TraitFn::Provided(..) => true, }, 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 17e424d4aac86..cbef1a978a407 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -7084,7 +7084,7 @@ impl<'tcx> TypeFolder> for ReplaceImplTraitFolder<'tcx> { pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( tcx: TyCtxt<'tcx>, sig: hir::FnSig<'tcx>, - body: hir::TraitFn<'tcx>, + body: hir::TraitFn, opaque_def_id: LocalDefId, add_bounds: &str, ) -> Option> { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fe2bc513dea3c..27eedb5e5156b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1280,7 +1280,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let m = clean_function(cx, sig, trait_item.generics, local_did); MethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(_)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required) => { let m = clean_function(cx, sig, trait_item.generics, local_did); RequiredMethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index 071b3b1df0786..ebc07109563dc 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -533,7 +533,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(_, kind) = item.kind { let body = match kind { - TraitFn::Required(_) => None, + TraitFn::Required => None, TraitFn::Provided(body) => Some(body), }; inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()), body); diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index 5ea0c2dbf5e61..da365eb53a20b 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -167,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'tcx>) { // functions with a body are already checked by `check_fn` - if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind + if let TraitItemKind::Fn(fn_sig, TraitFn::Required) = &trait_item.kind && fn_sig.header.abi == ExternAbi::Rust && fn_sig.decl.inputs.len() as u64 > self.max_fn_params_bools { diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 9ae34010f927e..9a5ee87f333b9 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -30,7 +30,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]); impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind + if let TraitItemKind::Fn(_, TraitFn::Required) = item.kind && let Some(attr_span) = find_attr!(cx .tcx .hir_attrs(item.hir_id()), diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index b46656ff5eee2..567ac187353a1 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -149,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { .. } = item.kind { - check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv, || { + check_fn_inner(cx, sig, Some(id), generics, item.span, true, self.msrv, || { is_from_proc_macro(cx, item) }); } else if let ItemKind::Impl(impl_) = &item.kind @@ -173,7 +173,6 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { cx, sig, Some(id), - None, item.generics, item.span, report_extra_lifetimes, @@ -185,15 +184,14 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(ref sig, ref body) = item.kind { - let (body, trait_sig) = match *body { - TraitFn::Required(sig) => (None, Some(sig)), - TraitFn::Provided(id) => (Some(id), None), + let body = match *body { + TraitFn::Required => None, + TraitFn::Provided(id) => Some(id), }; check_fn_inner( cx, sig, body, - trait_sig, item.generics, item.span, true, @@ -209,7 +207,6 @@ fn check_fn_inner<'tcx>( cx: &LateContext<'tcx>, sig: &'tcx FnSig<'_>, body: Option, - trait_sig: Option<&[Option]>, generics: &'tcx Generics<'_>, span: Span, report_extra_lifetimes: bool, @@ -266,7 +263,7 @@ fn check_fn_inner<'tcx>( } } - let elidable = could_use_elision(cx, sig.decl, body, trait_sig, generics.params, msrv); + let elidable = could_use_elision(cx, sig.decl, body, generics.params, msrv); let has_elidable_lts = elidable .as_ref() .is_some_and(|(_, usages)| !usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span))); @@ -294,7 +291,6 @@ fn could_use_elision<'tcx>( cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, body: Option, - trait_sig: Option<&[Option]>, named_generics: &'tcx [GenericParam<'_>], msrv: Msrv, ) -> Option<(Vec, Vec)> { @@ -330,18 +326,12 @@ fn could_use_elision<'tcx>( let input_lts = input_visitor.lts; let output_lts = output_visitor.lts; - if let Some(&[trait_sig]) = trait_sig - && non_elidable_self_type(cx, func, trait_sig, msrv) - { + let first_ident = func.inputs.first().and_then(|param| param.pat.simple_ident()); + if non_elidable_self_type(cx, func, first_ident, msrv) { return None; } if let Some(body_id) = body { - let first_ident = func.inputs.first().and_then(|param| param.pat.simple_ident()); - if non_elidable_self_type(cx, func, first_ident, msrv) { - return None; - } - let mut checker = BodyLifetimeChecker::new(cx); let body = cx.tcx.hir_body(body_id); if checker.visit_expr(body.value).is_break() { diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 949b9de7d311f..e4d2a3409d5c6 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -519,7 +519,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { TraitItemKind::Fn(ref sig, trait_method) => { // Check only methods without body // Methods with body are covered by check_fn. - if let TraitFn::Required(_) = trait_method { + if let TraitFn::Required = trait_method { self.check_fn_decl(cx, sig.decl, context); } }, From 6669a76e1752348c5447944472aff3968dea7ffd Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 14:42:05 +0200 Subject: [PATCH 10/12] Remove idents argument from `ForeignItemKind::Fn` --- compiler/rustc_ast_lowering/src/item.rs | 23 ++++++++----------- compiler/rustc_ast_lowering/src/lib.rs | 15 ------------ compiler/rustc_hir/src/hir.rs | 18 +++++++-------- compiler/rustc_hir/src/intravisit.rs | 5 +--- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/clauses_of.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_lint/src/lifetime_syntax.rs | 2 +- compiler/rustc_lint/src/runtime_symbols.rs | 2 +- .../rustc_lint/src/types/improper_ctypes.rs | 2 +- .../traits/fulfillment_errors.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 15 files changed, 29 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9bb79bf0c4b9e..cfdc84986bfa8 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -620,21 +620,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::Fn(Fn { sig, ident, generics, define_opaque, .. }) => { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; - let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| { + let (generics, decl) = self.lower_generics(generics, itctx, |this| { let params = this.arena.alloc_from_iter(fdec.inputs.iter().map(|x| this.lower_param(x))); - ( - // Disallow `impl Trait` in foreign items. - // Parameters are discarded because foreign functions don't have a body - this.lower_fn_decl( - fdec, - i.id, - FnDeclKind::ExternFn, - None, - DiscardParams::Yes, - params, - ), - this.lower_fn_params_to_idents(fdec), + // Disallow `impl Trait` in foreign items. + this.lower_fn_decl( + fdec, + i.id, + FnDeclKind::ExternFn, + None, + DiscardParams::Yes, + params, ) }); @@ -649,7 +645,6 @@ impl<'hir> LoweringContext<'_, 'hir> { ident, hir::ForeignItemKind::Fn( hir::FnSig { header, decl, span: self.lower_span(sig.span) }, - fn_args, generics, ), ) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a3ccd4b583bee..1dfdb9200fb4b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1894,21 +1894,6 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } - fn lower_fn_params_to_idents(&mut self, decl: &FnDecl) -> &'hir [Option] { - self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { - PatKind::Missing => None, - PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)), - PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))), - _ => { - self.dcx().span_delayed_bug( - param.pat.span, - "non-missing/ident/wild param pat must trigger an error", - ); - None - } - })) - } - /// Lowers a function declaration. /// /// `decl`: the unlowered (AST) function declaration. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2af96f8c6c840..d63a698906074 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4796,7 +4796,7 @@ pub enum ForeignItemKind<'hir> { /// `&[Option]` is used because of code paths shared with `TraitFn` /// and `FnPtrTy`. The sharing is due to all of these cases not allowing /// arbitrary patterns for parameters. - Fn(FnSig<'hir>, &'hir [Option], &'hir Generics<'hir>), + Fn(FnSig<'hir>, &'hir Generics<'hir>), /// A foreign static item (`static ext: u8`). Static(&'hir Ty<'hir>, Mutability, Safety), /// A foreign type. @@ -4852,7 +4852,7 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. }) | OwnerNode::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(fn_sig, _, _), .. + kind: ForeignItemKind::Fn(fn_sig, _), .. }) => Some(fn_sig), _ => None, } @@ -4864,7 +4864,7 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. }) | OwnerNode::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(fn_sig, _, _), .. + kind: ForeignItemKind::Fn(fn_sig, _), .. }) => Some(fn_sig.decl), _ => None, } @@ -5072,7 +5072,7 @@ impl<'hir> Node<'hir> { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. }) - | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => { + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _), .. }) => { Some(fn_sig.decl) } Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) => { @@ -5100,7 +5100,7 @@ impl<'hir> Node<'hir> { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. }) - | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => { + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _), .. }) => { Some(fn_sig) } _ => None, @@ -5193,9 +5193,7 @@ impl<'hir> Node<'hir> { pub fn generics(self) -> Option<&'hir Generics<'hir>> { match self { - Node::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(_, _, generics), .. - }) + Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(_, generics), .. }) | Node::TraitItem(TraitItem { generics, .. }) | Node::ImplItem(ImplItem { generics, .. }) => Some(generics), Node::Item(item) => item.kind.generics(), @@ -5293,8 +5291,8 @@ mod size_asserts { static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 48); static_assert_size!(FnDecl<'_>, 40); - static_assert_size!(ForeignItem<'_>, 88); - static_assert_size!(ForeignItemKind<'_>, 56); + static_assert_size!(ForeignItem<'_>, 72); + static_assert_size!(ForeignItemKind<'_>, 40); static_assert_size!(GenericArg<'_>, 16); static_assert_size!(GenericBound<'_>, 64); static_assert_size!(Generics<'_>, 56); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 7f2250bf44d26..fd980b9d24d17 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -691,12 +691,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ident(*ident)); match *kind { - ForeignItemKind::Fn(ref sig, param_idents, ref generics) => { + ForeignItemKind::Fn(ref sig, ref generics) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(sig.decl)); - for ident in param_idents.iter().copied() { - visit_opt!(visitor, visit_ident, ident); - } } ForeignItemKind::Static(ref typ, _, _) => { try_visit!(visitor.visit_ty_unambig(typ)); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 4b8468960831b..b4f93fa7e6e64 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1219,7 +1219,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn None, ), - ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => { + ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _), .. }) => { let abi = tcx.hir_get_foreign_abi(hir_id); compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety()) } diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index ae384a67ee6aa..69cce536fdb21 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -1097,7 +1097,7 @@ pub(super) fn const_conditions<'tcx>( _ => bug!("const_conditions called on wrong item: {def_id:?}"), }, Node::ForeignItem(item) => match item.kind { - hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false), + hir::ForeignItemKind::Fn(_, generics) => (generics, None, false), _ => bug!("const_conditions called on wrong item: {def_id:?}"), }, Node::OpaqueTy(opaque) => match opaque.origin { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 5a284d7451828..56be79c810ae7 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -713,7 +713,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { - hir::ForeignItemKind::Fn(_, _, generics) => { + hir::ForeignItemKind::Fn(_, generics) => { self.visit_early_late(item.hir_id(), generics, |this| { intravisit::walk_foreign_item(this, item); }) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 8754430aaa99e..d95e38923b52e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -214,7 +214,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ Node::OpaqueTy(..) => tcx.type_of_opaque(def_id).instantiate_identity().skip_norm_wip(), Node::ForeignItem(foreign_item) => match foreign_item.kind { - ForeignItemKind::Fn(_, _, _generics) => { + ForeignItemKind::Fn(_, _generics) => { new_bound_fn_def(foreign_item.hir_id(), def_id.to_def_id()) } ForeignItemKind::Static(ty, _, _) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index e0595621cf8a6..10e1e052ee123 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -510,7 +510,7 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_attrs(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(sig, _, generics) => { + hir::ForeignItemKind::Fn(sig, generics) => { let (cb, ib) = self.head(""); self.print_fn(sig.header, Some(item.ident.name), generics, sig.decl); self.end(ib); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 16151e2126409..f28e929bcfc5e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2078,7 +2078,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::ItemKind::Fn { sig, generics, .. }, .. }) | hir::Node::ForeignItem(&hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(sig, _, generics), + kind: hir::ForeignItemKind::Fn(sig, generics), .. }) => (sig, generics), _ => return None, diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 5f747fdd63b34..74c6755384166 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for LifetimeSyntax { #[instrument(skip_all)] fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, fi: &'tcx hir::ForeignItem<'tcx>) { match fi.kind { - hir::ForeignItemKind::Fn(fn_sig, _idents, _generics) => check_fn_like(cx, fn_sig.decl), + hir::ForeignItemKind::Fn(fn_sig, _generics) => check_fn_like(cx, fn_sig.decl), hir::ForeignItemKind::Static(..) => {} hir::ForeignItemKind::Type => {} } diff --git a/compiler/rustc_lint/src/runtime_symbols.rs b/compiler/rustc_lint/src/runtime_symbols.rs index f0e186c34ca0f..89ca2394cbc43 100644 --- a/compiler/rustc_lint/src/runtime_symbols.rs +++ b/compiler/rustc_lint/src/runtime_symbols.rs @@ -122,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for RuntimeSymbols { let symbol_name = cx.tcx.symbol_name(instance); match item.kind { - ForeignItemKind::Fn(fn_sig, _idents, _generics) => { + ForeignItemKind::Fn(fn_sig, _generics) => { check_fn(cx, &symbol_name.name, fn_sig, did); } ForeignItemKind::Static(..) => { diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index c90c71b0b7cb9..a8ede88956826 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -1247,7 +1247,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesLint { let abi = cx.tcx.hir_get_foreign_abi(it.hir_id()); match it.kind { - hir::ForeignItemKind::Fn(sig, _, _) => { + hir::ForeignItemKind::Fn(sig, _) => { // fnptrs are a special case, they always need to be treated as // "the element rendered unsafe" because their unsafety doesn't affect // their surroundings, and their type is often declared inline diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index f2537c7379c0b..dab598149221c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3855,7 +3855,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { kind: hir::TraitItemKind::Fn(ref sig, _), .. }) | Node::ForeignItem(&hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(ref sig, _, _), + kind: hir::ForeignItemKind::Fn(ref sig, _), .. }) => ( sig.span, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 27eedb5e5156b..6f46c5288170f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3347,7 +3347,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(sig, _, generics) => { + hir::ForeignItemKind::Fn(sig, generics) => { ForeignFunctionItem(clean_function(cx, &sig, generics, def_id), sig.header.safety()) } hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( From ffe78bb8b41d35ca0651e47a4c8683d0a023751a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 16:16:43 +0200 Subject: [PATCH 11/12] Move `fn_has_body` to `FnDeclFlags` --- .../rustc_ast_lowering/src/delegation/mod.rs | 4 +-- compiler/rustc_ast_lowering/src/expr.rs | 3 +-- .../rustc_ast_lowering/src/expr/closure.rs | 21 +++------------- compiler/rustc_ast_lowering/src/item.rs | 25 +++++++------------ compiler/rustc_ast_lowering/src/lib.rs | 22 ++++------------ compiler/rustc_hir/src/hir.rs | 21 ++++++++++++++-- compiler/rustc_hir/src/intravisit.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 2 +- compiler/rustc_passes/src/dead.rs | 2 +- 10 files changed, 44 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs index 0cc7d8a415c25..4a560f1582562 100644 --- a/compiler/rustc_ast_lowering/src/delegation/mod.rs +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -171,8 +171,8 @@ impl<'hir> LoweringContext<'_, 'hir> { .set_lifetime_elision_allowed(true) .set_c_variadic(c_variadic) .set_splatted(splatted, inputs.len()) - .unwrap(), - fn_has_body: true, + .unwrap() + .set_has_body(true), }) } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 4e8966b474ba2..7071c45500742 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -912,8 +912,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_decl = self.arena.alloc(hir::FnDecl { inputs, output, - fn_decl_kind: hir::FnDeclFlags::default(), - fn_has_body: true, + fn_decl_kind: hir::FnDeclFlags::default().set_has_body(true), }); let (_, body) = self.lower_body(move |this| { diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index 37ec9d0f129e8..5283de8de9901 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -6,8 +6,8 @@ use rustc_hir::HirId; use rustc_span::{Span, span_bug}; use super::{LoweringContext, MoveExprState}; +use crate::FnDeclKind; use crate::diagnostics::{ClosureCannotBeStatic, CoroutineTooManyParameters}; -use crate::{DiscardParams, FnDeclKind}; impl<'hir> LoweringContext<'_, 'hir> { // Entry point for `ExprKind::Closure`. Plain closures go through @@ -205,14 +205,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl( - decl, - closure_id, - FnDeclKind::Closure, - None, - DiscardParams::No, - params, - ); + let fn_decl = self.lower_fn_decl(decl, closure_id, FnDeclKind::Closure, None, true, params); let c = self.arena.alloc(hir::Closure { def_id: closure_def_id, @@ -332,14 +325,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl( - &decl, - closure_id, - FnDeclKind::Closure, - None, - DiscardParams::No, - parameters, - ); + let fn_decl = + self.lower_fn_decl(&decl, closure_id, FnDeclKind::Closure, None, true, parameters); if let Const::Yes(span) = constness { self.dcx().span_err(span, "const coroutines are not supported"); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cfdc84986bfa8..1a895787c42d1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -19,8 +19,8 @@ use super::diagnostics::{ }; use super::stability::{enabled_names, gate_unstable_abi}; use super::{ - DiscardParams, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, - LoweringContext, ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, + FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, + RelaxedBoundForbiddenReason, RelaxedBoundPolicy, }; use crate::diagnostics::{ConstComptimeFn, ResolvingRestrictionKind, RestrictionAncestorOnly}; @@ -283,7 +283,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id, FnDeclKind::Fn, coroutine_marker, - if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, + body.is_some(), params, ) }); @@ -624,14 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let params = this.arena.alloc_from_iter(fdec.inputs.iter().map(|x| this.lower_param(x))); // Disallow `impl Trait` in foreign items. - this.lower_fn_decl( - fdec, - i.id, - FnDeclKind::ExternFn, - None, - DiscardParams::Yes, - params, - ) + this.lower_fn_decl(fdec, i.id, FnDeclKind::ExternFn, None, false, params) }); // Unmarked safety in unsafe block defaults to unsafe. @@ -855,7 +848,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sig.header.coroutine_marker, attrs, // Parameters are discarded for functions without a body - DiscardParams::Yes, + false, params, ); if define_opaque.is_some() { @@ -892,7 +885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { FnDeclKind::Trait, sig.header.coroutine_marker, attrs, - DiscardParams::No, + true, params, ); self.lower_define_opaque(hir_id, &define_opaque); @@ -1104,7 +1097,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_marker, attrs, - if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, + body.is_some(), params, ); self.lower_define_opaque(hir_id, &define_opaque); @@ -1555,13 +1548,13 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: FnDeclKind, coroutine_marker: Option, attrs: &[rustc_attr_ir::Attribute], - discard_params: DiscardParams, + has_body: bool, inputs: &'hir [hir::Param<'hir>], ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(&sig.decl, node_id, kind, coroutine_marker, discard_params, inputs) + this.lower_fn_decl(&sig.decl, node_id, kind, coroutine_marker, has_body, inputs) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1dfdb9200fb4b..44911ecb4f84b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -808,14 +808,6 @@ enum GenericArgsMode { Silence, } -#[derive(Debug, Copy, Clone)] -enum DiscardParams { - /// Should be used for functions without a body. Lowers the attributes on the parameter and then discards them. - Yes, - /// Should be used for functions with a body. Does not lower the attributes, as lowering of the parameters is done by `lower_body`. - No, -} - impl<'hir> LoweringContext<'_, 'hir> { fn create_def( &mut self, @@ -1569,7 +1561,7 @@ impl<'hir> LoweringContext<'_, 'hir> { t.id, FnDeclKind::Pointer, None, - DiscardParams::Yes, + false, params, ), })); @@ -1916,7 +1908,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_node_id: NodeId, kind: FnDeclKind, coro: Option, - discard_params: DiscardParams, + has_body: bool, hir_inputs: &'hir [hir::Param<'hir>], ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -2038,14 +2030,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ) .set_c_variadic(c_variadic) .set_splatted(splatted, inputs.len()) - .unwrap(); + .unwrap() + .set_has_body(has_body); - self.arena.alloc(hir::FnDecl { - inputs, - output, - fn_decl_kind, - fn_has_body: matches!(discard_params, DiscardParams::No), - }) + self.arena.alloc(hir::FnDecl { inputs, output, fn_decl_kind }) } // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }` diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d63a698906074..2bcb0f9df8516 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3809,6 +3809,9 @@ impl FnDeclFlags { /// Bitflag for lifetime elision. const LIFETIME_ELISION_ALLOWED_FLAG: u8 = 1 << 4; + /// Bitflag for whether there is a body associated with this function + const HAS_BODY: u8 = 1 << 5; + /// Marker index for "no splatted argument". /// Must have the same value as `FnSigKind::NO_SPLATTED_ARG_INDEX` and `rustc_ast::FnDecl::NO_SPLATTED_ARG_INDEX`. const NO_SPLATTED_ARG_INDEX: u8 = u8::MAX; @@ -3927,6 +3930,22 @@ impl FnDeclFlags { pub fn splatted(self) -> Option { if self.splatted == Self::NO_SPLATTED_ARG_INDEX { None } else { Some(self.splatted) } } + + pub fn has_body(self) -> bool { + (self.flags & Self::HAS_BODY) != 0 + } + + /// Set whether this fn decl is associated with a body + #[must_use = "this method does not modify the receiver"] + pub fn set_has_body(mut self, allowed: bool) -> Self { + if allowed { + self.flags |= Self::HAS_BODY; + } else { + self.flags &= !Self::HAS_BODY; + } + + self + } } /// Represents the header (not the body) of a function declaration. @@ -3936,7 +3955,6 @@ pub struct FnDecl<'hir> { pub output: FnRetTy<'hir>, /// The packed function declaration attributes. pub fn_decl_kind: FnDeclFlags, - pub fn_has_body: bool, } impl<'hir> FnDecl<'hir> { @@ -3981,7 +3999,6 @@ impl<'hir> FnDecl<'hir> { inputs: &[], output: FnRetTy::DefaultReturn(span), fn_decl_kind: FnDeclFlags::default().set_lifetime_elision_allowed(true), - fn_has_body: true, } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index fd980b9d24d17..313ebcec72e72 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1235,7 +1235,7 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>( visitor: &mut V, function_declaration: &'v FnDecl<'v>, ) -> V::Result { - let FnDecl { inputs, output, fn_decl_kind: _, fn_has_body: _ } = function_declaration; + let FnDecl { inputs, output, fn_decl_kind: _ } = function_declaration; walk_list!(visitor, visit_param, *inputs); visitor.visit_fn_ret_ty(output) } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 56be79c810ae7..9ba106c57ed73 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -436,7 +436,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } fn visit_fn_decl(&mut self, decl: &'tcx FnDecl<'tcx>) -> Self::Result { - if !decl.fn_has_body { + if !decl.fn_decl_kind.has_body() { intravisit::walk_fn_decl(self, decl); } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 8faf4b1247acf..3c1a9e3841583 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -380,7 +380,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } fn visit_fn_decl(&mut self, fd: &'tcx FnDecl<'tcx>) -> Self::Result { - if fd.fn_has_body { + if fd.fn_decl_kind.has_body() { intravisit::walk_fn_decl(self, fd); } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b7cfeda66adac..9a7ec2e14a97a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -692,7 +692,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { type Result = ControlFlow; fn visit_fn_decl(&mut self, decl: &'tcx FnDecl<'tcx>) -> Self::Result { - if !decl.fn_has_body { + if !decl.fn_decl_kind.has_body() { intravisit::walk_fn_decl(self, decl)?; } ControlFlow::Continue(()) From e21450a3f649464d4e87e406b2510125ba1a7e2d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 17:14:57 +0200 Subject: [PATCH 12/12] Specialize `lower_body` into `lower_body_with_params` --- .../rustc_ast_lowering/src/delegation/mod.rs | 6 ++--- compiler/rustc_ast_lowering/src/expr.rs | 4 +-- .../rustc_ast_lowering/src/expr/closure.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 27 ++++++++++--------- compiler/rustc_ast_lowering/src/pat.rs | 13 +++------ 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs index 4a560f1582562..bc590d7e2dd15 100644 --- a/compiler/rustc_ast_lowering/src/delegation/mod.rs +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -278,7 +278,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut call_expr_id = HirId::INVALID; let mut unused_target_expr = false; - let (params, block_id) = self.lower_body(|this| { + let (params, block_id) = self.lower_body_with_params(|this| { let &DelegationResolution { param_info, span, is_method, .. } = res; let ParamInfo { param_count, c_variadic, .. } = param_info; let param_count = param_count - c_variadic as usize; @@ -597,7 +597,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.lower_ident(delegation.ident); - let (_params, body_id) = self.lower_body(|this| { + let body_id = self.lower_body(|this| { let path = this.lower_qpath( delegation.id, &delegation.qself, @@ -626,7 +626,7 @@ impl<'hir> LoweringContext<'_, 'hir> { targeted_by_break: false, }); - (&[], this.mk_expr(hir::ExprKind::Block(block, None), span)) + this.mk_expr(hir::ExprKind::Block(block, None), span) }); let generics = hir::Generics::empty(); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 7071c45500742..e29f79cd3d97d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -915,7 +915,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_kind: hir::FnDeclFlags::default().set_has_body(true), }); - let (_, body) = self.lower_body(move |this| { + let body = self.lower_body(move |this| { this.coroutine_kind = Some(coroutine_kind); let old_ctx = this.task_context; @@ -925,7 +925,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = body(this); this.task_context = old_ctx; - (inputs, res) + res }); let explicit_captures: &'hir [hir::ExplicitCapture] = match coroutine_source { diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index 5283de8de9901..7a583e9d7746b 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -304,7 +304,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (parameters, body) = self.with_new_scopes(fn_decl_span, |this| { // Transform `async |x: u8| -> X { ... }` into // `|x: u8| || -> X { ... }`. - let body_id = this.lower_body(|this| { + let body_id = this.lower_body_with_params(|this| { let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( &decl, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1a895787c42d1..8b8c8ea48fd26 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -320,8 +320,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ItemKind::GlobalAsm(asm) => { let asm = self.lower_inline_asm(span, asm); - let (_, fake_body) = - self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); + let fake_body = + self.lower_body(|this| this.expr(span, hir::ExprKind::InlineAsm(asm))); hir::ItemKind::GlobalAsm { asm, fake_body } } ItemKind::TyAlias(TyAlias { ident, generics, after_where_clause, ty, .. }) => { @@ -1206,6 +1206,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_body( + &mut self, + f: impl FnOnce(&mut Self) -> hir::Expr<'hir>, + ) -> hir::BodyId { + self.lower_body_with_params(|c| (&[], f(c))).1 + } + + pub(super) fn lower_body_with_params( &mut self, f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>), ) -> (&'hir [hir::Param<'hir>], hir::BodyId) { @@ -1241,7 +1248,7 @@ impl<'hir> LoweringContext<'_, 'hir> { contract: Option<&FnContract>, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> (&'hir [hir::Param<'hir>], hir::BodyId) { - self.lower_body(|this| { + self.lower_body_with_params(|this| { let params = this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x))); @@ -1264,16 +1271,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId { - self.lower_body(|this| { - ( - &[], - match expr { - Some(expr) => this.lower_expr_mut(expr), - None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")), - }, - ) + self.lower_body(|this| match expr { + Some(expr) => this.lower_expr_mut(expr), + None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")), }) - .1 } /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or @@ -1321,7 +1322,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return self.lower_fn_body_block(decl, body, contract); }; // FIXME(contracts): Support contracts on async fn. - self.lower_body(|this| { + self.lower_body_with_params(|this| { let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( decl, |this| this.lower_block_expr(body), diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index eb13e8b4e084b..9bbe48c477568 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -488,7 +488,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let anon_const = self.with_new_scopes(span, |this| { let def_id = this.local_def_id(e.id); let hir_id = this.lower_node_id(e.id); - let (_, body) = this.lower_body(|this| { + let body = this.lower_body(|this| { // Need to use a custom function as we can't just subtract `1` from a `char`. let kind = hir::ExprKind::Path(this.make_lang_item_qpath( LangItem::RangeSub, @@ -497,14 +497,7 @@ impl<'hir> LoweringContext<'_, 'hir> { )); let fn_def = this.arena.alloc(hir::Expr { hir_id: this.next_id(), kind, span }); let args = this.arena.alloc([this.lower_expr_mut(&e.value)]); - ( - &[], - hir::Expr { - hir_id: this.next_id(), - kind: hir::ExprKind::Call(fn_def, args), - span, - }, - ) + hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Call(fn_def, args), span } }); hir::AnonConst { def_id, hir_id, body, span } }); @@ -550,7 +543,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(hir::AnonConst { def_id, hir_id, - body: this.lower_body(|_this| (&[], path_expr)).1, + body: this.lower_body(|_this| path_expr), span, }) });