Skip to content
/ rust Public
forked from rust-lang/rust

Commit b909c36

Browse files
committed
Remove allocations in FnCtxt checks.
1 parent 7daf4cf commit b909c36

File tree

1 file changed

+77
-95
lines changed
  • compiler/rustc_hir_typeck/src/fn_ctxt

1 file changed

+77
-95
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+77-95
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath};
1313
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
1414
use rustc_hir_analysis::check::potentially_plural_count;
1515
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
16-
use rustc_index::IndexVec;
16+
use rustc_index::{Idx, IndexVec};
1717
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
1818
use rustc_middle::ty::adjustment::AllowTwoPhase;
1919
use rustc_middle::ty::error::TypeError;
@@ -2374,22 +2374,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23742374

23752375
let check_for_matched_generics = || {
23762376
if matched_inputs.iter().any(|x| x.is_some())
2377-
&& params_with_generics.iter().any(|x| x.1.is_some())
2377+
&& params_with_generics.iter().any(|(x, _)| x.is_some())
23782378
{
2379-
for &(idx, generic, _) in &params_with_generics {
2379+
for (idx, (generic, _)) in params_with_generics.iter_enumerated() {
23802380
// Param has to have a generic and be matched to be relevant
2381-
if matched_inputs[idx.into()].is_none() {
2381+
if matched_inputs[idx].is_none() {
23822382
continue;
23832383
}
23842384

23852385
let Some(generic) = generic else {
23862386
continue;
23872387
};
23882388

2389-
for unmatching_idx in idx + 1..params_with_generics.len() {
2390-
if matched_inputs[unmatching_idx.into()].is_none()
2389+
for unmatching_idx in
2390+
idx.plus(1)..ExpectedIdx::from_usize(params_with_generics.len())
2391+
{
2392+
if matched_inputs[unmatching_idx].is_none()
23912393
&& let Some(unmatched_idx_param_generic) =
2392-
params_with_generics[unmatching_idx].1
2394+
params_with_generics[unmatching_idx].0
23932395
&& unmatched_idx_param_generic.name.ident()
23942396
== generic.name.ident()
23952397
{
@@ -2404,40 +2406,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24042406

24052407
let check_for_matched_generics = check_for_matched_generics();
24062408

2407-
for &(idx, generic_param, param) in
2408-
params_with_generics.iter().filter(|&(idx, _, _)| {
2409+
for (idx, &(generic_param, param)) in
2410+
params_with_generics.iter_enumerated().filter(|&(idx, _)| {
24092411
check_for_matched_generics
2410-
|| expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
2412+
|| expected_idx
2413+
.is_none_or(|expected_idx| expected_idx == idx.as_usize())
24112414
})
24122415
{
24132416
let Some(generic_param) = generic_param else {
24142417
spans.push_span_label(param.span, "");
24152418
continue;
24162419
};
24172420

2418-
let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics
2419-
.iter()
2420-
.filter(|(other_idx, other_generic_param, _)| {
2421-
if *other_idx == idx {
2422-
return false;
2423-
}
2424-
let Some(other_generic_param) = other_generic_param else {
2425-
return false;
2426-
};
2427-
if matched_inputs[idx.into()].is_none()
2428-
&& matched_inputs[(*other_idx).into()].is_none()
2429-
{
2430-
return false;
2431-
}
2432-
if matched_inputs[idx.into()].is_some()
2433-
&& matched_inputs[(*other_idx).into()].is_some()
2434-
{
2435-
return false;
2436-
}
2437-
other_generic_param.name.ident() == generic_param.name.ident()
2438-
})
2439-
.map(|&(other_idx, _, other_param)| (other_idx, other_param))
2440-
.collect();
2421+
let other_params_matched: Vec<(ExpectedIdx, &hir::Param<'_>)> =
2422+
params_with_generics
2423+
.iter_enumerated()
2424+
.filter(|&(other_idx, &(other_generic_param, _))| {
2425+
if other_idx == idx {
2426+
return false;
2427+
}
2428+
let Some(other_generic_param) = other_generic_param else {
2429+
return false;
2430+
};
2431+
if matched_inputs[idx].is_none()
2432+
&& matched_inputs[other_idx].is_none()
2433+
{
2434+
return false;
2435+
}
2436+
if matched_inputs[idx].is_some()
2437+
&& matched_inputs[other_idx].is_some()
2438+
{
2439+
return false;
2440+
}
2441+
other_generic_param.name.ident() == generic_param.name.ident()
2442+
})
2443+
.map(|(other_idx, &(_, other_param))| (other_idx, other_param))
2444+
.collect();
24412445

24422446
if !other_params_matched.is_empty() {
24432447
let other_param_matched_names: Vec<String> = other_params_matched
@@ -2447,16 +2451,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24472451
{
24482452
format!("`{ident}`")
24492453
} else {
2450-
format!("parameter #{}", idx + 1)
2454+
format!("parameter #{}", idx.as_u32() + 1)
24512455
}
24522456
})
24532457
.collect();
24542458

24552459
let matched_ty = self
2456-
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
2460+
.resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
24572461
.sort_string(self.tcx);
24582462

2459-
if matched_inputs[idx.into()].is_some() {
2463+
if matched_inputs[idx].is_some() {
24602464
spans.push_span_label(
24612465
param.span,
24622466
format!(
@@ -2502,19 +2506,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25022506
})
25032507
{
25042508
let param_idents_matching: Vec<String> = params_with_generics
2505-
.iter()
2506-
.filter(|(_, generic, _)| {
2509+
.iter_enumerated()
2510+
.filter(|&(_, &(generic, _))| {
25072511
if let Some(generic) = generic {
25082512
generic.name.ident() == generic_param.name.ident()
25092513
} else {
25102514
false
25112515
}
25122516
})
2513-
.map(|(idx, _, param)| {
2517+
.map(|(idx, &(_, param))| {
25142518
if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind {
25152519
format!("`{ident}`")
25162520
} else {
2517-
format!("parameter #{}", idx + 1)
2521+
format!("parameter #{}", idx.as_u32() + 1)
25182522
}
25192523
})
25202524
.collect();
@@ -2607,45 +2611,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26072611

26082612
if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method) {
26092613
debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2610-
for &(idx, generic_param, _) in &params_with_generics {
2611-
if matched_inputs[idx.into()].is_none() {
2614+
for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
2615+
if matched_inputs[idx].is_none() {
26122616
continue;
26132617
}
26142618

2615-
let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.into()) else {
2619+
let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
2620+
else {
26162621
continue;
26172622
};
26182623

26192624
let Some(generic_param) = generic_param else {
26202625
continue;
26212626
};
26222627

2623-
let mut idxs_matched: Vec<usize> = vec![];
2624-
for &(other_idx, _, _) in
2625-
params_with_generics.iter().filter(|&&(other_idx, other_generic_param, _)| {
2628+
let idxs_matched = params_with_generics
2629+
.iter_enumerated()
2630+
.filter(|&(other_idx, (other_generic_param, _))| {
26262631
if other_idx == idx {
26272632
return false;
26282633
}
26292634
let Some(other_generic_param) = other_generic_param else {
26302635
return false;
26312636
};
2632-
if matched_inputs[other_idx.into()].is_some() {
2637+
if matched_inputs[other_idx].is_some() {
26332638
return false;
26342639
}
26352640
other_generic_param.name.ident() == generic_param.name.ident()
26362641
})
2637-
{
2638-
idxs_matched.push(other_idx);
2639-
}
2642+
.count();
26402643

2641-
if idxs_matched.is_empty() {
2644+
if idxs_matched == 0 {
26422645
continue;
26432646
}
26442647

26452648
let expected_display_type = self
26462649
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
26472650
.sort_string(self.tcx);
2648-
let label = if idxs_matched.len() == params_with_generics.len() - 1 {
2651+
let label = if idxs_matched == params_with_generics.len() - 1 {
26492652
format!(
26502653
"expected all arguments to be this {} type because they need to match the type of this parameter",
26512654
expected_display_type
@@ -2664,60 +2667,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26642667
}
26652668

26662669
/// Returns the parameters of a function, with their generic parameters if those are the full
2667-
/// type of that parameter. Returns `None` if the function body is unavailable (eg is an instrinsic).
2670+
/// type of that parameter. Returns `None` if the function has no generics or the body is
2671+
/// unavailable (eg is an instrinsic).
26682672
fn get_hir_params_with_generics(
26692673
&self,
26702674
def_id: DefId,
26712675
is_method: bool,
2672-
) -> Option<Vec<(usize, Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
2676+
) -> Option<IndexVec<ExpectedIdx, (Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
26732677
let fn_node = self.tcx.hir().get_if_local(def_id)?;
26742678
let fn_decl = fn_node.fn_decl()?;
2679+
let generic_params = fn_node.generics()?.params;
26752680

2676-
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
2677-
.inputs
2678-
.into_iter()
2679-
.skip(if is_method { 1 } else { 0 })
2680-
.map(|param| {
2681-
if let hir::TyKind::Path(QPath::Resolved(
2682-
_,
2683-
hir::Path { res: Res::Def(_, res_def_id), .. },
2684-
)) = param.kind
2685-
{
2686-
fn_node
2687-
.generics()
2688-
.into_iter()
2689-
.flat_map(|generics| generics.params)
2690-
.find(|param| &param.def_id.to_def_id() == res_def_id)
2691-
} else {
2692-
None
2693-
}
2694-
})
2695-
.collect();
2681+
// Remove both the receiver and variadic arguments. Neither can have an unmatched generic
2682+
// parameter.
2683+
let params = self.tcx.hir().body(fn_node.body_id()?).params;
2684+
let params = params.get(is_method as usize..params.len() - fn_decl.c_variadic as usize)?;
2685+
let fn_inputs = fn_decl.inputs.get(is_method as usize..)?;
2686+
debug_assert_eq!(params.len(), fn_inputs.len());
26962687

2697-
let mut params: Vec<&hir::Param<'_>> = self
2698-
.tcx
2699-
.hir()
2700-
.body(fn_node.body_id()?)
2701-
.params
2702-
.into_iter()
2703-
.skip(if is_method { 1 } else { 0 })
2704-
.collect();
2705-
2706-
// The surrounding code expects variadic functions to not have a parameter representing
2707-
// the "..." parameter. This is already true of the FnDecl but not of the body params, so
2708-
// we drop it if it exists.
2709-
2710-
if fn_decl.c_variadic {
2711-
params.pop();
2712-
}
2713-
2714-
debug_assert_eq!(params.len(), generic_params.len());
27152688
Some(
2716-
generic_params
2689+
fn_inputs
27172690
.into_iter()
2691+
.map(|param| {
2692+
if let hir::TyKind::Path(QPath::Resolved(
2693+
_,
2694+
&hir::Path { res: Res::Def(_, res_def_id), .. },
2695+
)) = param.kind
2696+
{
2697+
generic_params.iter().find(|param| param.def_id.to_def_id() == res_def_id)
2698+
} else {
2699+
None
2700+
}
2701+
})
27182702
.zip(params)
2719-
.enumerate()
2720-
.map(|(a, (b, c))| (a, b, c))
27212703
.collect(),
27222704
)
27232705
}

0 commit comments

Comments
 (0)