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
// 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};
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);
// 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 {
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);
}
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)
}
}
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(
} = 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`
"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(
// 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: (),
}
}
- 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,
}
#[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,
-
- /// 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,
+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.
+ at_location: Location,
+ }
+}
+
+impl Locations {
+ pub fn from_location(&self) -> Option<Location> {
+ match self {
+ Locations::All => None,
+ Locations::Pair { from_location, .. } => Some(*from_location),
+ }
+ }
+
+ pub fn at_location(&self) -> Option<Location> {
+ match self {
+ Locations::All => None,
+ Locations::Pair { at_location, .. } => Some(*at_location),
+ }
+ }
}
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,
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(),
};
// *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(),
};
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(),
};
};
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,
}
}
- fn normalize<T>(&mut self, value: &T, location: Location) -> T
+ fn normalize<T>(&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)
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()
+ }
+}