diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index a42ce3a2d3b..411bf5b55ed 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -38,7 +38,6 @@ mod universal_regions; use self::region_infer::RegionInferenceContext; use self::universal_regions::UniversalRegions; - /// Rewrites the regions in the MIR to use NLL variables, also /// scraping out the set of universal regions (e.g., region parameters) /// declared on the function. That set will need to be given to diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs index 32728145b29..05b61f25a39 100644 --- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::mir::Mir; +use rustc::mir::{Location, Mir}; use rustc::infer::region_constraints::Constraint; use rustc::infer::region_constraints::RegionConstraintData; use rustc::infer::region_constraints::{Verify, VerifyBound}; @@ -65,7 +65,11 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { givens, } = data; - let span = self.mir.source_info(locations.from_location).span; + let span = self.mir + .source_info(locations.from_location().unwrap_or(Location::START)) + .span; + + let at_location = locations.at_location().unwrap_or(Location::START); for constraint in constraints.keys() { debug!("generate: constraint: {:?}", constraint); @@ -83,8 +87,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { // reverse direction, because `regioncx` talks about // "outlives" (`>=`) whereas the region constraints // talk about `<=`. - self.regioncx - .add_outlives(span, b_vid, a_vid, locations.at_location); + self.regioncx.add_outlives(span, b_vid, a_vid, at_location); } for verify in verifys { @@ -109,7 +112,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { let lower_bound = self.to_region_vid(verify.region); - let point = locations.at_location; + let point = locations.at_location().unwrap_or(Location::START); let test = self.verify_bound_to_region_test(&verify.bound); @@ -149,14 +152,6 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { } fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid { - // Every region that we see in the constraints came from the - // MIR or from the parameter environment. If the former, it - // will be a region variable. If the latter, it will be in - // the set of universal regions *somewhere*. - if let ty::ReVar(vid) = r { - *vid - } else { - self.regioncx.to_region_vid(r) - } + self.regioncx.to_region_vid(r) } } 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 beb1a26ae70..2b1878c33e9 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 @@ -29,7 +29,7 @@ use rustc::traits::PredicateObligations; use rustc_data_structures::indexed_vec::Idx; -use super::{AtLocation, TypeChecker}; +use super::{Locations, TypeChecker}; impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { pub(super) fn equate_inputs_and_outputs( @@ -47,26 +47,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } = universal_regions; let infcx = self.infcx; - let start_position = Location { - block: START_BLOCK, - statement_index: 0, - }; - // 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, start_position); + let input_ty = self.normalize(&unnormalized_input_ty, Locations::All); let mir_input_ty = mir.local_decls[local].ty; - self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty); + self.equate_normalized_input_or_output(input_ty, mir_input_ty); } assert!( mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() || mir.yield_ty.is_none() && universal_regions.yield_ty.is_none() - ); + ); if let Some(mir_yield_ty) = mir.yield_ty { let ur_yield_ty = universal_regions.yield_ty.unwrap(); - self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty); + self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty); } // Return types are a bit more complex. They may contain existential `impl Trait` @@ -75,13 +70,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { "equate_inputs_and_outputs: unnormalized_output_ty={:?}", unnormalized_output_ty ); - let output_ty = self.normalize(&unnormalized_output_ty, start_position); + let output_ty = self.normalize(&unnormalized_output_ty, Locations::All); debug!( "equate_inputs_and_outputs: normalized output_ty={:?}", output_ty ); let mir_output_ty = mir.local_decls[RETURN_PLACE].ty; - let anon_type_map = self.fully_perform_op(start_position.at_self(), |cx| { + let anon_type_map = self.fully_perform_op(Locations::All, |cx| { let mut obligations = ObligationAccumulator::default(); let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types( @@ -148,7 +143,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // prove that `T: Iterator` where `T` is the type we // instantiated it with). if let Some(anon_type_map) = anon_type_map { - self.fully_perform_op(start_position.at_self(), |_cx| { + self.fully_perform_op(Locations::All, |_cx| { infcx.constrain_anon_types(&anon_type_map, universal_regions); Ok(InferOk { value: (), @@ -158,13 +153,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn equate_normalized_input_or_output(&mut self, location: Location, a: Ty<'tcx>, b: Ty<'tcx>) { + fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b); - if let Err(terr) = self.eq_types(a, b, location.at_self()) { + if let Err(terr) = self.eq_types(a, b, Locations::All) { span_mirbug!( self, - location, + Location::START, "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`", a, b, 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 a21b9196bad..ec98a0a02c0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -619,16 +619,35 @@ pub struct OutlivesSet<'tcx> { } #[derive(Copy, Clone, Debug)] -pub struct Locations { - /// The location in the MIR that generated these constraints. - /// This is intended for error reporting and diagnosis; the - /// constraints may *take effect* at a distinct spot. - pub from_location: Location, +pub enum Locations { + All, + Pair { + /// The location in the MIR that generated these constraints. + /// This is intended for error reporting and diagnosis; the + /// constraints may *take effect* at a distinct spot. + from_location: Location, - /// The constraints must be met at this location. In terms of the - /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field - /// is the `P` value. - pub at_location: Location, + /// The constraints must be met at this location. In terms of the + /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field + /// is the `P` value. + at_location: Location, + } +} + +impl Locations { + pub fn from_location(&self) -> Option { + match self { + Locations::All => None, + Locations::Pair { from_location, .. } => Some(*from_location), + } + } + + pub fn at_location(&self) -> Option { + match self { + Locations::All => None, + Locations::Pair { at_location, .. } => Some(*at_location), + } + } } impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { @@ -770,7 +789,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { "check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty ); - if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) { + if let Err(terr) = self.eq_types(ty, local_ty, Locations::All) { span_mirbug!( self, stmt, @@ -820,7 +839,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let place_ty = location.ty(mir, tcx).to_ty(tcx); let rv_ty = value.ty(mir, tcx); - let locations = Locations { + let locations = Locations::Pair { from_location: term_location, at_location: target.start_location(), }; @@ -839,7 +858,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // *both* blocks, so we need to ensure that it holds // at both locations. if let Some(unwind) = unwind { - let locations = Locations { + let locations = Locations::Pair { from_location: term_location, at_location: unwind.start_location(), }; @@ -971,7 +990,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match *destination { Some((ref dest, target_block)) => { let dest_ty = dest.ty(mir, tcx).to_ty(tcx); - let locations = Locations { + let locations = Locations::Pair { from_location: term_location, at_location: target_block.start_location(), }; @@ -1375,7 +1394,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }; let operand_ty = operand.ty(mir, tcx); if let Err(terr) = - self.sub_types(operand_ty, field_ty, location.at_successor_within_block()) + self.sub_types(operand_ty, field_ty, location.at_self()) { span_mirbug!( self, @@ -1514,12 +1533,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn normalize(&mut self, value: &T, location: Location) -> T + fn normalize(&mut self, value: &T, location: impl ToLocations) -> T where T: fmt::Debug + TypeFoldable<'tcx>, { debug!("normalize(value={:?}, location={:?})", value, location); - self.fully_perform_op(location.at_self(), |this| { + self.fully_perform_op(location.to_locations(), |this| { let Normalized { value, obligations } = this.infcx .at(&this.misc(this.last_span), this.param_env) .normalize(value) @@ -1585,16 +1604,32 @@ trait AtLocation { impl AtLocation for Location { fn at_self(self) -> Locations { - Locations { + Locations::Pair { from_location: self, at_location: self, } } fn at_successor_within_block(self) -> Locations { - Locations { + Locations::Pair { from_location: self, at_location: self.successor_within_block(), } } } + +trait ToLocations: fmt::Debug + Copy { + fn to_locations(self) -> Locations; +} + +impl ToLocations for Locations { + fn to_locations(self) -> Locations { + self + } +} + +impl ToLocations for Location { + fn to_locations(self) -> Locations { + self.at_self() + } +}