use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
-use crate::transform::{MirPass, MirSource};
use either::Either;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::mir::interpret::{InterpError::BoundsCheck, ConstValue};
use rustc::mir::tcx::PlaceTy;
-use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
+use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
use rustc::mir::*;
use rustc::traits::query::type_op;
use rustc::traits::query::type_op::custom::CustomTypeOp;
pub(crate) fn type_check<'gcx, 'tcx>(
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'gcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
universal_regions: &Rc<UniversalRegions<'tcx>>,
location_table: &LocationTable,
param_env,
mir,
®ion_bound_pairs,
- Some(implicit_region_bound),
- Some(&mut borrowck_context),
- Some(&universal_region_relations),
- |cx| {
+ implicit_region_bound,
+ &mut borrowck_context,
+ &universal_region_relations,
+ |mut cx| {
cx.equate_inputs_and_outputs(mir, universal_regions, &normalized_inputs_and_output);
- liveness::generate(cx, mir, elements, flow_inits, move_data, location_table);
+ liveness::generate(&mut cx, mir, elements, flow_inits, move_data, location_table);
- cx.borrowck_context
- .as_mut()
- .map(|bcx| translate_outlives_facts(bcx));
+ translate_outlives_facts(cx.borrowck_context);
},
);
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
mir_def_id: DefId,
param_env: ty::ParamEnv<'gcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- implicit_region_bound: Option<ty::Region<'tcx>>,
- borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
- universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
+ implicit_region_bound: ty::Region<'tcx>,
+ borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
+ universal_region_relations: &'a UniversalRegionRelations<'tcx>,
mut extra: impl FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>) -> R,
) -> R where {
let mut checker = TypeChecker::new(
);
let errors_reported = {
let mut verifier = TypeVerifier::new(&mut checker, mir);
- verifier.visit_mir(mir);
+ verifier.visit_body(mir);
verifier.errors_reported
};
/// is a problem.
struct TypeVerifier<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
- mir: &'b Mir<'tcx>,
+ mir: &'b Body<'tcx>,
last_span: Span,
mir_def_id: DefId,
errors_reported: bool,
}
}
- fn visit_mir(&mut self, mir: &Mir<'tcx>) {
+ fn visit_body(&mut self, mir: &Body<'tcx>) {
self.sanitize_type(&"return type", mir.return_ty());
for local_decl in &mir.local_decls {
self.sanitize_type(local_decl, local_decl.ty);
if self.errors_reported {
return;
}
- self.super_mir(mir);
+ self.super_body(mir);
}
}
impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
- fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Mir<'tcx>) -> Self {
+ fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Body<'tcx>) -> Self {
TypeVerifier {
mir,
mir_def_id: cx.mir_def_id,
context: PlaceContext,
) -> PlaceTy<'tcx> {
debug!("sanitize_place: {:?}", place);
- let place_ty = match place {
- Place::Base(PlaceBase::Local(index)) =>
- PlaceTy::from_ty(self.mir.local_decls[*index].ty),
- Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
- let sty = self.sanitize_type(place, sty);
- let check_err =
- |verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
- place: &Place<'tcx>,
- ty,
- sty| {
- if let Err(terr) = verifier.cx.eq_types(
- sty,
- ty,
- location.to_locations(),
- ConstraintCategory::Boring,
- ) {
- span_mirbug!(
- verifier,
- place,
- "bad promoted type ({:?}: {:?}): {:?}",
- ty,
- sty,
- terr
- );
+
+ place.iterate(|place_base, place_projection| {
+ let mut place_ty = match place_base {
+ PlaceBase::Local(index) =>
+ PlaceTy::from_ty(self.mir.local_decls[*index].ty),
+ PlaceBase::Static(box Static { kind, ty: sty }) => {
+ let sty = self.sanitize_type(place, sty);
+ let check_err =
+ |verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
+ place: &Place<'tcx>,
+ ty,
+ sty| {
+ if let Err(terr) = verifier.cx.eq_types(
+ sty,
+ ty,
+ location.to_locations(),
+ ConstraintCategory::Boring,
+ ) {
+ span_mirbug!(
+ verifier,
+ place,
+ "bad promoted type ({:?}: {:?}): {:?}",
+ ty,
+ sty,
+ terr
+ );
+ };
};
- };
- match kind {
- StaticKind::Promoted(promoted) => {
- if !self.errors_reported {
- let promoted_mir = &self.mir.promoted[*promoted];
- self.sanitize_promoted(promoted_mir, location);
-
- let promoted_ty = promoted_mir.return_ty();
- check_err(self, place, promoted_ty, sty);
+ match kind {
+ StaticKind::Promoted(promoted) => {
+ if !self.errors_reported {
+ let promoted_mir = &self.mir.promoted[*promoted];
+ self.sanitize_promoted(promoted_mir, location);
+
+ let promoted_ty = promoted_mir.return_ty();
+ check_err(self, place, promoted_ty, sty);
+ }
}
- }
- StaticKind::Static(def_id) => {
- let ty = self.tcx().type_of(*def_id);
- let ty = self.cx.normalize(ty, location);
+ StaticKind::Static(def_id) => {
+ let ty = self.tcx().type_of(*def_id);
+ let ty = self.cx.normalize(ty, location);
- check_err(self, place, ty, sty);
+ check_err(self, place, ty, sty);
+ }
}
+ PlaceTy::from_ty(sty)
+ }
+ };
+
+ // FIXME use place_projection.is_empty() when is available
+ if let Place::Base(_) = place {
+ if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+ let tcx = self.tcx();
+ let trait_ref = ty::TraitRef {
+ def_id: tcx.lang_items().copy_trait().unwrap(),
+ substs: tcx.mk_substs_trait(place_ty.ty, &[]),
+ };
+
+ // In order to have a Copy operand, the type T of the
+ // value must be Copy. Note that we prove that T: Copy,
+ // rather than using the `is_copy_modulo_regions`
+ // test. This is important because
+ // `is_copy_modulo_regions` ignores the resulting region
+ // obligations and assumes they pass. This can result in
+ // bounds from Copy impls being unsoundly ignored (e.g.,
+ // #29149). Note that we decide to use Copy before knowing
+ // whether the bounds fully apply: in effect, the rule is
+ // that if a value of some type could implement Copy, then
+ // it must.
+ self.cx.prove_trait_ref(
+ trait_ref,
+ location.to_locations(),
+ ConstraintCategory::CopyBound,
+ );
}
- PlaceTy::from_ty(sty)
}
- Place::Projection(ref proj) => {
- let base_context = if context.is_mutating_use() {
- PlaceContext::MutatingUse(MutatingUseContext::Projection)
- } else {
- PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
- };
- let base_ty = self.sanitize_place(&proj.base, location, base_context);
- if base_ty.variant_index.is_none() {
- if base_ty.ty.references_error() {
+
+ for proj in place_projection {
+ if place_ty.variant_index.is_none() {
+ if place_ty.ty.references_error() {
assert!(self.errors_reported);
return PlaceTy::from_ty(self.tcx().types.err);
}
}
- self.sanitize_projection(base_ty, &proj.elem, place, location)
+ place_ty = self.sanitize_projection(place_ty, &proj.elem, place, location)
}
- };
- if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
- let tcx = self.tcx();
- let trait_ref = ty::TraitRef {
- def_id: tcx.lang_items().copy_trait().unwrap(),
- substs: tcx.mk_substs_trait(place_ty.ty, &[]),
- };
- // In order to have a Copy operand, the type T of the
- // value must be Copy. Note that we prove that T: Copy,
- // rather than using the `is_copy_modulo_regions`
- // test. This is important because
- // `is_copy_modulo_regions` ignores the resulting region
- // obligations and assumes they pass. This can result in
- // bounds from Copy impls being unsoundly ignored (e.g.,
- // #29149). Note that we decide to use Copy before knowing
- // whether the bounds fully apply: in effect, the rule is
- // that if a value of some type could implement Copy, then
- // it must.
- self.cx.prove_trait_ref(
- trait_ref,
- location.to_locations(),
- ConstraintCategory::CopyBound,
- );
- }
- place_ty
+ place_ty
+ })
}
- fn sanitize_promoted(&mut self, promoted_mir: &'b Mir<'tcx>, location: Location) {
+ fn sanitize_promoted(&mut self, promoted_mir: &'b Body<'tcx>, location: Location) {
// Determine the constraints from the promoted MIR by running the type
// checker on the promoted MIR, then transfer the constraints back to
// the main MIR, changing the locations to the provided location.
let all_facts = &mut None;
let mut constraints = Default::default();
let mut closure_bounds = Default::default();
- if let Some(ref mut bcx) = self.cx.borrowck_context {
- // Don't try to add borrow_region facts for the promoted MIR
- mem::swap(bcx.all_facts, all_facts);
-
- // Use a new sets of constraints and closure bounds so that we can
- // modify their locations.
- mem::swap(&mut bcx.constraints.outlives_constraints, &mut constraints);
- mem::swap(&mut bcx.constraints.closure_bounds_mapping, &mut closure_bounds);
- };
+ // Don't try to add borrow_region facts for the promoted MIR
+ mem::swap(self.cx.borrowck_context.all_facts, all_facts);
+
+ // Use a new sets of constraints and closure bounds so that we can
+ // modify their locations.
+ mem::swap(
+ &mut self.cx.borrowck_context.constraints.outlives_constraints,
+ &mut constraints
+ );
+ mem::swap(
+ &mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
+ &mut closure_bounds
+ );
- self.visit_mir(promoted_mir);
+ self.visit_body(promoted_mir);
if !self.errors_reported {
// if verifier failed, don't do further checks to avoid ICEs
self.mir = parent_mir;
// Merge the outlives constraints back in, at the given location.
- if let Some(ref mut base_bcx) = self.cx.borrowck_context {
- mem::swap(base_bcx.all_facts, all_facts);
- mem::swap(&mut base_bcx.constraints.outlives_constraints, &mut constraints);
- mem::swap(&mut base_bcx.constraints.closure_bounds_mapping, &mut closure_bounds);
-
- let locations = location.to_locations();
- for constraint in constraints.iter() {
- let mut constraint = *constraint;
- constraint.locations = locations;
- if let ConstraintCategory::Return
- | ConstraintCategory::UseAsConst
- | ConstraintCategory::UseAsStatic = constraint.category
- {
- // "Returning" from a promoted is an assigment to a
- // temporary from the user's point of view.
- constraint.category = ConstraintCategory::Boring;
- }
- base_bcx.constraints.outlives_constraints.push(constraint)
- }
+ mem::swap(self.cx.borrowck_context.all_facts, all_facts);
+ mem::swap(
+ &mut self.cx.borrowck_context.constraints.outlives_constraints,
+ &mut constraints
+ );
+ mem::swap(
+ &mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
+ &mut closure_bounds
+ );
- if !closure_bounds.is_empty() {
- let combined_bounds_mapping = closure_bounds
- .into_iter()
- .flat_map(|(_, value)| value)
- .collect();
- let existing = base_bcx
- .constraints
- .closure_bounds_mapping
- .insert(location, combined_bounds_mapping);
- assert!(
- existing.is_none(),
- "Multiple promoteds/closures at the same location."
- );
+ let locations = location.to_locations();
+ for constraint in constraints.iter() {
+ let mut constraint = *constraint;
+ constraint.locations = locations;
+ if let ConstraintCategory::Return
+ | ConstraintCategory::UseAsConst
+ | ConstraintCategory::UseAsStatic = constraint.category
+ {
+ // "Returning" from a promoted is an assigment to a
+ // temporary from the user's point of view.
+ constraint.category = ConstraintCategory::Boring;
}
+ self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
+ }
+
+ if !closure_bounds.is_empty() {
+ let combined_bounds_mapping = closure_bounds
+ .into_iter()
+ .flat_map(|(_, value)| value)
+ .collect();
+ let existing = self.cx.borrowck_context
+ .constraints
+ .closure_bounds_mapping
+ .insert(location, combined_bounds_mapping);
+ assert!(
+ existing.is_none(),
+ "Multiple promoteds/closures at the same location."
+ );
}
}
}
}
}
+ // We do not need to handle generators here, because this runs
+ // before the generator transform stage.
_ => {
let ty = if let Some(name) = maybe_name {
span_mirbug_and_err!(
let tcx = self.tcx();
let (variant, substs) = match base_ty {
- PlaceTy { ty, variant_index: Some(variant_index) } => {
- match ty.sty {
- ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
- _ => bug!("can't have downcast of non-adt type"),
+ PlaceTy { ty, variant_index: Some(variant_index) } => match ty.sty {
+ ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
+ ty::Generator(def_id, substs, _) => {
+ let mut variants = substs.state_tys(def_id, tcx);
+ let mut variant = match variants.nth(variant_index.into()) {
+ Some(v) => v,
+ None => {
+ bug!("variant_index of generator out of range: {:?}/{:?}",
+ variant_index,
+ substs.state_tys(def_id, tcx).count())
+ }
+ };
+ return match variant.nth(field.index()) {
+ Some(ty) => Ok(ty),
+ None => Err(FieldAccessError::OutOfRange {
+ field_count: variant.count(),
+ }),
+ }
}
+ _ => bug!("can't have downcast of non-adt non-generator type"),
}
PlaceTy { ty, variant_index: None } => match ty.sty {
ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
}
}
ty::Generator(def_id, substs, _) => {
- // Try pre-transform fields first (upvars and current state)
- if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) {
- return Ok(ty);
- }
-
- // Then try `field_tys` which contains all the fields, but it
- // requires the final optimized MIR.
- return match substs.field_tys(def_id, tcx).nth(field.index()) {
+ // Only prefix fields (upvars and current state) are
+ // accessible without a variant index.
+ return match substs.prefix_tys(def_id, tcx).nth(field.index()) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
- field_count: substs.field_tys(def_id, tcx).count(),
+ field_count: substs.prefix_tys(def_id, tcx).count(),
}),
- };
+ }
}
ty::Tuple(tys) => {
return match tys.get(field.index()) {
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
mir_def_id: DefId,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- implicit_region_bound: Option<ty::Region<'tcx>>,
+ implicit_region_bound: ty::Region<'tcx>,
reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
- borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
- universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
+ borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
+ universal_region_relations: &'a UniversalRegionRelations<'tcx>,
}
struct BorrowCheckContext<'a, 'tcx: 'a> {
}
/// Gets a span representing the location.
- pub fn span(&self, mir: &Mir<'_>) -> Span {
+ pub fn span(&self, mir: &Body<'_>) -> Span {
match self {
Locations::All(span) => *span,
Locations::Single(l) => mir.source_info(*l).span,
impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
fn new(
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mir_def_id: DefId,
param_env: ty::ParamEnv<'gcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- implicit_region_bound: Option<ty::Region<'tcx>>,
- borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
- universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
+ implicit_region_bound: ty::Region<'tcx>,
+ borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
+ universal_region_relations: &'a UniversalRegionRelations<'tcx>,
) -> Self {
let mut checker = Self {
infcx,
locations, data
);
- if let Some(ref mut borrowck_context) = self.borrowck_context {
- constraint_conversion::ConstraintConversion::new(
- self.infcx,
- borrowck_context.universal_regions,
- self.region_bound_pairs,
- self.implicit_region_bound,
- self.param_env,
- locations,
- category,
- &mut borrowck_context.constraints,
- ).convert_all(&data);
- }
+ constraint_conversion::ConstraintConversion::new(
+ self.infcx,
+ self.borrowck_context.universal_regions,
+ self.region_bound_pairs,
+ Some(self.implicit_region_bound),
+ self.param_env,
+ locations,
+ category,
+ &mut self.borrowck_context.constraints,
+ ).convert_all(&data);
}
/// Convenient wrapper around `relate_tys::relate_types` -- see
b,
locations,
category,
- self.borrowck_context.as_mut().map(|x| &mut **x),
+ Some(self.borrowck_context),
)
}
),
)?;
- let universal_region_relations = match self.universal_region_relations {
- Some(rel) => rel,
- None => return Ok(()),
- };
+ let universal_region_relations = self.universal_region_relations;
// Finally, if we instantiated the anon types successfully, we
// have to solve any bounds (e.g., `-> impl Iterator` needs to
self.infcx.tcx
}
- fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Location) {
+ fn check_stmt(&mut self, mir: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
debug!("check_stmt: {:?}", stmt);
let tcx = self.tcx();
match stmt.kind {
// of lowering. Assignments to other sorts of places *are* interesting
// though.
let category = match *place {
- Place::Base(PlaceBase::Local(RETURN_PLACE)) => if let Some(BorrowCheckContext {
+ Place::Base(PlaceBase::Local(RETURN_PLACE)) => if let BorrowCheckContext {
universal_regions:
UniversalRegions {
defining_ty: DefiningTy::Const(def_id, _),
..
},
..
- }) = self.borrowck_context
+ } = self.borrowck_context
{
if tcx.is_static(*def_id) {
ConstraintCategory::UseAsStatic
fn check_terminator(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
term: &Terminator<'tcx>,
term_location: Location,
) {
// output) types in the signature must be live, since
// all the inputs that fed into it were live.
for &late_bound_region in map.values() {
- if let Some(ref mut borrowck_context) = self.borrowck_context {
- let region_vid = borrowck_context
- .universal_regions
- .to_region_vid(late_bound_region);
- borrowck_context
- .constraints
- .liveness_constraints
- .add_element(region_vid, term_location);
- }
+ let region_vid = self.borrowck_context
+ .universal_regions
+ .to_region_vid(late_bound_region);
+ self.borrowck_context
+ .constraints
+ .liveness_constraints
+ .add_element(region_vid, term_location);
}
self.check_call_inputs(mir, term, &sig, args, term_location, from_hir_call);
fn check_call_dest(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>,
destination: &Option<(Place<'tcx>, BasicBlock)>,
let dest_ty = dest.ty(mir, tcx).ty;
let category = match *dest {
Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
- if let Some(BorrowCheckContext {
+ if let BorrowCheckContext {
universal_regions:
UniversalRegions {
defining_ty: DefiningTy::Const(def_id, _),
..
},
..
- }) = self.borrowck_context
+ } = self.borrowck_context
{
if tcx.is_static(*def_id) {
ConstraintCategory::UseAsStatic
fn check_call_inputs(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>,
args: &[Operand<'tcx>],
}
}
- fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) {
+ fn check_iscleanup(&mut self, mir: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) {
let is_cleanup = block_data.is_cleanup;
self.last_span = block_data.terminator().source_info.span;
match block_data.terminator().kind {
fn assert_iscleanup(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
ctxt: &dyn fmt::Debug,
bb: BasicBlock,
iscleanuppad: bool,
}
}
- fn check_local(&mut self, mir: &Mir<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
+ fn check_local(&mut self, mir: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
match mir.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Arg => {
// return values of normal functions are required to be
}
}
AggregateKind::Generator(def_id, substs, _) => {
- // Try pre-transform fields first (upvars and current state)
- if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field_index) {
- Ok(ty)
- } else {
- // Then try `field_tys` which contains all the fields, but it
- // requires the final optimized MIR.
- match substs.field_tys(def_id, tcx).nth(field_index) {
- Some(ty) => Ok(ty),
- None => Err(FieldAccessError::OutOfRange {
- field_count: substs.field_tys(def_id, tcx).count(),
- }),
- }
+ // It doesn't make sense to look at a field beyond the prefix;
+ // these require a variant index, and are not initialized in
+ // aggregate rvalues.
+ match substs.prefix_tys(def_id, tcx).nth(field_index) {
+ Some(ty) => Ok(ty),
+ None => Err(FieldAccessError::OutOfRange {
+ field_count: substs.prefix_tys(def_id, tcx).count(),
+ }),
}
}
AggregateKind::Array(ty) => Ok(ty),
}
}
- fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
+ fn check_rvalue(&mut self, mir: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
let tcx = self.tcx();
match rvalue {
fn check_aggregate_rvalue(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
rvalue: &Rvalue<'tcx>,
aggregate_kind: &AggregateKind<'tcx>,
operands: &[Operand<'tcx>],
/// - `borrowed_place`: the place `P` being borrowed
fn add_reborrow_constraint(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
location: Location,
borrow_region: ty::Region<'tcx>,
borrowed_place: &Place<'tcx>,
all_facts,
constraints,
..
- } = match self.borrowck_context {
- Some(ref mut borrowck_context) => borrowck_context,
- None => return,
- };
+ } = self.borrowck_context;
// In Polonius mode, we also push a `borrow_region` fact
// linking the loan to the region (in some cases, though,
"add_reborrow_constraint({:?}, {:?}, {:?})",
location, borrow_region, borrowed_place
);
- while let Place::Projection(box PlaceProjection { base, elem }) = borrowed_place {
+ while let Place::Projection(box Projection { base, elem }) = borrowed_place {
debug!("add_reborrow_constraint - iteration {:?}", borrowed_place);
match *elem {
let closure_constraints =
closure_region_requirements.apply_requirements(tcx, def_id, substs);
- if let Some(ref mut borrowck_context) = self.borrowck_context {
- let bounds_mapping = closure_constraints
- .iter()
- .enumerate()
- .filter_map(|(idx, constraint)| {
- let ty::OutlivesPredicate(k1, r2) =
- constraint.no_bound_vars().unwrap_or_else(|| {
- bug!("query_constraint {:?} contained bound vars", constraint,);
- });
-
- match k1.unpack() {
- UnpackedKind::Lifetime(r1) => {
- // constraint is r1: r2
- let r1_vid = borrowck_context.universal_regions.to_region_vid(r1);
- let r2_vid = borrowck_context.universal_regions.to_region_vid(r2);
- let outlives_requirements =
- &closure_region_requirements.outlives_requirements[idx];
- Some((
- (r1_vid, r2_vid),
- (
- outlives_requirements.category,
- outlives_requirements.blame_span,
- ),
- ))
- }
- UnpackedKind::Type(_) | UnpackedKind::Const(_) => None,
+ let bounds_mapping = closure_constraints
+ .iter()
+ .enumerate()
+ .filter_map(|(idx, constraint)| {
+ let ty::OutlivesPredicate(k1, r2) =
+ constraint.no_bound_vars().unwrap_or_else(|| {
+ bug!("query_constraint {:?} contained bound vars", constraint,);
+ });
+
+ match k1.unpack() {
+ UnpackedKind::Lifetime(r1) => {
+ // constraint is r1: r2
+ let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
+ let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
+ let outlives_requirements =
+ &closure_region_requirements.outlives_requirements[idx];
+ Some((
+ (r1_vid, r2_vid),
+ (
+ outlives_requirements.category,
+ outlives_requirements.blame_span,
+ ),
+ ))
}
- })
- .collect();
-
- let existing = borrowck_context
- .constraints
- .closure_bounds_mapping
- .insert(location, bounds_mapping);
- assert!(
- existing.is_none(),
- "Multiple closures at the same location."
- );
- }
+ UnpackedKind::Type(_) | UnpackedKind::Const(_) => None,
+ }
+ })
+ .collect();
+
+ let existing = self.borrowck_context
+ .constraints
+ .closure_bounds_mapping
+ .insert(location, bounds_mapping);
+ assert!(
+ existing.is_none(),
+ "Multiple closures at the same location."
+ );
self.push_region_constraints(
location.to_locations(),
})
}
- fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
+ fn typeck_mir(&mut self, mir: &Body<'tcx>) {
self.last_span = mir.span;
debug!("run_on_mir: {:?}", mir.span);
}
}
-pub struct TypeckMir;
-
-impl MirPass for TypeckMir {
- fn run_pass<'a, 'tcx>(
- &self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>,
- ) {
- let def_id = src.def_id();
- debug!("run_pass: {:?}", def_id);
-
- // FIXME: We don't need this MIR pass anymore.
- if true {
- return;
- }
-
- if tcx.sess.err_count() > 0 {
- // compiling a broken program can obviously result in a
- // broken MIR, so try not to report duplicate errors.
- return;
- }
-
- if tcx.is_constructor(def_id) {
- // We just assume that the automatically generated struct/variant constructors are
- // correct. See the comment in the `mir_borrowck` implementation for an
- // explanation why we need this.
- return;
- }
-
- let param_env = tcx.param_env(def_id);
- tcx.infer_ctxt().enter(|infcx| {
- type_check_internal(
- &infcx,
- def_id,
- param_env,
- mir,
- &vec![],
- None,
- None,
- None,
- |_| (),
- );
-
- // For verification purposes, we just ignore the resulting
- // region constraint sets. Not our problem. =)
- });
- }
-}
-
trait NormalizeLocation: fmt::Debug + Copy {
fn to_locations(self) -> Locations;
}