From 68c2a39a720163db2e6b586aad2fb7d96040beda Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 26 Jul 2018 15:07:22 +0300 Subject: [PATCH] free RegionBoundPairs earlier and avoid normalizing twice Normalization results are memoized, so this may not be worth it, but it seems easy enough to do. --- .../nll/type_check/free_region_relations.rs | 25 +++++++++++++-- .../nll/type_check/input_output.rs | 31 +++++++------------ .../borrow_check/nll/type_check/mod.rs | 9 ++++-- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs index 26a694a30a27..e4b1aacd34f7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs @@ -53,6 +53,18 @@ crate struct UniversalRegionRelations<'tcx> { /// our special inference variable there, we would mess that up. type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>; +/// As part of computing the free region relations, we also have to +/// normalize the input-output types, which we then need later. So we +/// return those. This vector consists of first the input types and +/// then the output type as the last element. +type NormalizedInputsAndOutput<'tcx> = Vec>; + +crate struct CreateResult<'tcx> { + crate universal_region_relations: Rc>, + crate region_bound_pairs: RegionBoundPairs<'tcx>, + crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, +} + crate fn create( infcx: &InferCtxt<'_, '_, 'tcx>, mir_def_id: DefId, @@ -62,7 +74,7 @@ crate fn create( universal_regions: &Rc>, constraints: &mut MirTypeckRegionConstraints<'tcx>, all_facts: &mut Option, -) -> (Rc>, RegionBoundPairs<'tcx>) { +) -> CreateResult<'tcx> { let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap(); UniversalRegionRelationsBuilder { infcx, @@ -215,7 +227,7 @@ struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> { } impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { - crate fn create(mut self) -> (Rc>, RegionBoundPairs<'tcx>) { + crate fn create(mut self) -> CreateResult<'tcx> { let unnormalized_input_output_tys = self .universal_regions .unnormalized_input_tys @@ -231,6 +243,8 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { // the `region_bound_pairs` and so forth. // - After this is done, we'll process the constraints, once // the `relations` is built. + let mut normalized_inputs_and_output = + Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1); let constraint_sets: Vec<_> = unnormalized_input_output_tys .flat_map(|ty| { debug!("build: input_or_output={:?}", ty); @@ -240,6 +254,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { .fully_perform(self.infcx) .unwrap_or_else(|_| bug!("failed to normalize {:?}", ty)); self.add_implied_bounds(ty); + normalized_inputs_and_output.push(ty); constraints }) .collect(); @@ -280,7 +295,11 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { ).convert_all(&data); } - (Rc::new(self.relations), self.region_bound_pairs) + CreateResult { + universal_region_relations: Rc::new(self.relations), + region_bound_pairs: self.region_bound_pairs, + normalized_inputs_and_output, + } } /// Update the type of a single local, which should represent diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index 8571ac3235c3..af4266701678 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -39,22 +39,24 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { mir_def_id: DefId, universal_regions: &UniversalRegions<'tcx>, universal_region_relations: &UniversalRegionRelations<'tcx>, + normalized_inputs_and_output: &[Ty<'tcx>], ) { let tcx = self.infcx.tcx; - let &UniversalRegions { - unnormalized_output_ty, - unnormalized_input_tys, - .. - } = universal_regions; + let (&normalized_output_ty, normalized_input_tys) = + normalized_inputs_and_output.split_last().unwrap(); let infcx = self.infcx; // Equate expected input tys with those in the MIR. let argument_locals = (1..).map(Local::new); - for (&unnormalized_input_ty, local) in unnormalized_input_tys.iter().zip(argument_locals) { - let input_ty = self.normalize(unnormalized_input_ty, Locations::All); + for (&normalized_input_ty, local) in normalized_input_tys.iter().zip(argument_locals) { + debug!( + "equate_inputs_and_outputs: normalized_input_ty = {:?}", + normalized_input_ty + ); + let mir_input_ty = mir.local_decls[local].ty; - self.equate_normalized_input_or_output(input_ty, mir_input_ty); + self.equate_normalized_input_or_output(normalized_input_ty, mir_input_ty); } assert!( @@ -68,15 +70,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // Return types are a bit more complex. They may contain existential `impl Trait` // types. - debug!( - "equate_inputs_and_outputs: unnormalized_output_ty={:?}", - unnormalized_output_ty - ); - let output_ty = self.normalize(unnormalized_output_ty, Locations::All); - debug!( - "equate_inputs_and_outputs: normalized output_ty={:?}", - output_ty - ); let param_env = self.param_env; let mir_output_ty = mir.local_decls[RETURN_PLACE].ty; let anon_type_map = @@ -92,7 +85,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { mir_def_id, dummy_body_id, param_env, - &output_ty, + &normalized_output_ty, )); debug!( "equate_inputs_and_outputs: instantiated output_ty={:?}", @@ -146,7 +139,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self, Location::START, "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`", - output_ty, + normalized_output_ty, mir_output_ty, terr ); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index eb18a56523eb..a18e2368bf72 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -17,7 +17,7 @@ use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint}; use borrow_check::nll::facts::AllFacts; use borrow_check::nll::region_infer::values::{RegionValueElements, LivenessValues}; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; -use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations; +use borrow_check::nll::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; use borrow_check::nll::universal_regions::UniversalRegions; use borrow_check::nll::LocalWithRegion; use borrow_check::nll::ToRegionVid; @@ -132,7 +132,11 @@ pub(crate) fn type_check<'gcx, 'tcx>( type_tests: Vec::default(), }; - let (universal_region_relations, region_bound_pairs) = free_region_relations::create( + let CreateResult { + universal_region_relations, + region_bound_pairs, + normalized_inputs_and_output, + } = free_region_relations::create( infcx, mir_def_id, param_env, @@ -168,6 +172,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( mir_def_id, universal_regions, &universal_region_relations, + &normalized_inputs_and_output, ); }, );