Skip to content

Commit 195dbfa

Browse files
authored
Auto merge of rust-lang#37014 - nnethercote:avoid-pat_to_string, r=arielb1
Avoid some `pat_to_string` calls. `ty_of_method_or_bare_fn` currently calls `pat_to_string` even when it doesn't need to. Fixing this avoids hundreds of large allocations (e.g. 171,600 bytes, in `mk_printer`) in several of rustc-benchmarks.
2 parents 49be16e + e5ffade commit 195dbfa

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

src/librustc_typeck/astconv.rs

+26-9
Original file line numberDiff line numberDiff line change
@@ -561,15 +561,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
561561
/// Returns the appropriate lifetime to use for any output lifetimes
562562
/// (if one exists) and a vector of the (pattern, number of lifetimes)
563563
/// corresponding to each input type/pattern.
564-
fn find_implied_output_region(&self,
565-
input_tys: &[Ty<'tcx>],
566-
input_pats: Vec<String>) -> ElidedLifetime
564+
fn find_implied_output_region<F>(&self,
565+
input_tys: &[Ty<'tcx>],
566+
input_pats: F) -> ElidedLifetime
567+
where F: FnOnce() -> Vec<String>
567568
{
568569
let tcx = self.tcx();
569570
let mut lifetimes_for_params = Vec::new();
570571
let mut possible_implied_output_region = None;
571572

572-
for (input_type, input_pat) in input_tys.iter().zip(input_pats) {
573+
for input_type in input_tys.iter() {
573574
let mut regions = FnvHashSet();
574575
let have_bound_regions = tcx.collect_regions(input_type, &mut regions);
575576

@@ -583,8 +584,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
583584
possible_implied_output_region = regions.iter().cloned().next();
584585
}
585586

587+
// Use a placeholder for `name` because computing it can be
588+
// expensive and we don't want to do it until we know it's
589+
// necessary.
586590
lifetimes_for_params.push(ElisionFailureInfo {
587-
name: input_pat,
591+
name: String::new(),
588592
lifetime_count: regions.len(),
589593
have_bound_regions: have_bound_regions
590594
});
@@ -593,6 +597,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
593597
if lifetimes_for_params.iter().map(|e| e.lifetime_count).sum::<usize>() == 1 {
594598
Ok(*possible_implied_output_region.unwrap())
595599
} else {
600+
// Fill in the expensive `name` fields now that we know they're
601+
// needed.
602+
for (info, input_pat) in lifetimes_for_params.iter_mut().zip(input_pats()) {
603+
info.name = input_pat;
604+
}
596605
Err(Some(lifetimes_for_params))
597606
}
598607
}
@@ -629,7 +638,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
629638
let inputs: Vec<_> = data.inputs.iter().map(|a_t| {
630639
self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
631640
}).collect();
632-
let input_params = vec![String::new(); inputs.len()];
641+
let inputs_len = inputs.len();
642+
let input_params = || vec![String::new(); inputs_len];
633643
let implied_output_region = self.find_implied_output_region(&inputs, input_params);
634644

635645
let (output, output_span) = match data.output {
@@ -1861,15 +1871,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
18611871
};
18621872
let arg_tys: Vec<Ty> =
18631873
arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
1864-
let arg_pats: Vec<String> =
1865-
arg_params.iter().map(|a| pprust::pat_to_string(&a.pat)).collect();
18661874

18671875
// Second, if there was exactly one lifetime (either a substitution or a
18681876
// reference) in the arguments, then any anonymous regions in the output
18691877
// have that lifetime.
18701878
let implied_output_region = match explicit_self_category {
18711879
ty::ExplicitSelfCategory::ByReference(region, _) => Ok(*region),
1872-
_ => self.find_implied_output_region(&arg_tys, arg_pats)
1880+
_ => {
1881+
// `pat_to_string` is expensive and
1882+
// `find_implied_output_region` only needs its result when
1883+
// there's an error. So we wrap it in a closure to avoid
1884+
// calling it until necessary.
1885+
let arg_pats = || {
1886+
arg_params.iter().map(|a| pprust::pat_to_string(&a.pat)).collect()
1887+
};
1888+
self.find_implied_output_region(&arg_tys, arg_pats)
1889+
}
18731890
};
18741891

18751892
let output_ty = match decl.output {

0 commit comments

Comments
 (0)