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.
This commit is contained in:
Niko Matsakis 2018-07-26 15:07:22 +03:00 committed by Felix S. Klock II
parent 490928f709
commit 68c2a39a72
3 changed files with 41 additions and 24 deletions

View file

@ -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<Ty<'tcx>>;
crate struct CreateResult<'tcx> {
crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
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<UniversalRegions<'tcx>>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
all_facts: &mut Option<AllFacts>,
) -> (Rc<UniversalRegionRelations<'tcx>>, 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<UniversalRegionRelations<'tcx>>, 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

View file

@ -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
);

View file

@ -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,
);
},
);