}
impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
- fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, promoted: &'b IndexVec<Promoted, Body<'tcx>>) -> Self {
+ fn new(
+ cx: &'a mut TypeChecker<'b, 'tcx>,
+ body: &'b Body<'tcx>,
+ promoted: &'b IndexVec<Promoted, Body<'tcx>>,
+ ) -> Self {
TypeVerifier {
body,
promoted,
) -> PlaceTy<'tcx> {
debug!("sanitize_place: {:?}", place);
- place.iterate(|place_base, place_projection| {
- let mut place_ty = match place_base {
- PlaceBase::Local(index) =>
- PlaceTy::from_ty(self.body.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, '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
- );
- };
+ let mut place_ty = match &place.base {
+ PlaceBase::Local(index) =>
+ PlaceTy::from_ty(self.body.local_decls[*index].ty),
+ PlaceBase::Static(box Static { kind, ty: sty, def_id }) => {
+ let sty = self.sanitize_type(place, sty);
+ let check_err =
+ |verifier: &mut TypeVerifier<'a, 'b, '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_body = &self.promoted[*promoted];
- self.sanitize_promoted(promoted_body, location);
-
- let promoted_ty = promoted_body.return_ty();
- check_err(self, place, promoted_ty, sty);
- }
+ };
+ match kind {
+ StaticKind::Promoted(promoted, _) => {
+ if !self.errors_reported {
+ let promoted_body = &self.promoted[*promoted];
+ self.sanitize_promoted(promoted_body, location);
+
+ let promoted_ty = promoted_body.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 => {
+ 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)
}
- };
+ PlaceTy::from_ty(sty)
+ }
+ };
- // FIXME use place_projection.is_empty() when is available
- if place.projection.is_none() {
- if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
- let is_promoted = match place {
- Place {
- base: PlaceBase::Static(box Static {
- kind: StaticKind::Promoted(_),
- ..
- }),
- projection: None,
- } => true,
- _ => false,
- };
+ if place.projection.is_empty() {
+ if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+ let is_promoted = match place {
+ Place {
+ base: PlaceBase::Static(box Static {
+ kind: StaticKind::Promoted(..),
+ ..
+ }),
+ projection: box [],
+ } => true,
+ _ => false,
+ };
- if !is_promoted {
- 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, &[]),
- };
+ if !is_promoted {
+ 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,
- );
- }
+ // 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,
+ );
}
}
+ }
- 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);
- }
+ for elem in place.projection.iter() {
+ 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);
}
- place_ty = self.sanitize_projection(place_ty, &proj.elem, place, location)
}
+ place_ty = self.sanitize_projection(place_ty, elem, place, location)
+ }
- place_ty
- })
+ place_ty
}
fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
let category = match *place {
Place {
base: PlaceBase::Local(RETURN_PLACE),
- projection: None,
+ projection: box [],
} => if let BorrowCheckContext {
universal_regions:
UniversalRegions {
},
Place {
base: PlaceBase::Local(l),
- projection: None,
+ projection: box [],
} if !body.local_decls[l].is_user_variable.is_some() => {
ConstraintCategory::Boring
}
let category = match *dest {
Place {
base: PlaceBase::Local(RETURN_PLACE),
- projection: None,
+ projection: box [],
} => {
if let BorrowCheckContext {
universal_regions:
}
Place {
base: PlaceBase::Local(l),
- projection: None,
+ projection: box [],
} if !body.local_decls[l].is_user_variable.is_some() => {
ConstraintCategory::Boring
}
// *p`, where the `p` has type `&'b mut Foo`, for example, we
// need to ensure that `'b: 'a`.
- let mut borrowed_projection = &borrowed_place.projection;
-
debug!(
"add_reborrow_constraint({:?}, {:?}, {:?})",
location, borrow_region, borrowed_place
);
- while let Some(box proj) = borrowed_projection {
- debug!("add_reborrow_constraint - iteration {:?}", borrowed_projection);
+ for (i, elem) in borrowed_place.projection.iter().enumerate().rev() {
+ debug!("add_reborrow_constraint - iteration {:?}", elem);
+ let proj_base = &borrowed_place.projection[..i];
- match proj.elem {
+ match elem {
ProjectionElem::Deref => {
let tcx = self.infcx.tcx;
- let base_ty = Place::ty_from(&borrowed_place.base, &proj.base, body, tcx).ty;
+ let base_ty = Place::ty_from(&borrowed_place.base, proj_base, body, tcx).ty;
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.sty {
// other field access
}
}
-
- // The "propagate" case. We need to check that our base is valid
- // for the borrow's lifetime.
- borrowed_projection = &proj.base;
}
}