use rustc::mir::*;
use rustc::ty::{self, Ty};
-use rustc::hir::def_id::DefId;
-use syntax_pos::DUMMY_SP;
+use rustc_span::DUMMY_SP;
use super::Item as ConstCx;
/// of the type.
fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;
- fn in_static(cx: &ConstCx<'_, 'tcx>, def_id: DefId) -> bool {
- // `mir_const_qualif` does return the qualifs in the final value of a `static`, so we could
- // use value-based qualification here, but we shouldn't do this without a good reason.
- Self::in_any_value_of_ty(cx, cx.tcx.type_of(def_id))
- }
-
fn in_projection_structurally(
cx: &ConstCx<'_, 'tcx>,
per_local: &impl Fn(Local) -> bool,
place: PlaceRef<'_, 'tcx>,
) -> bool {
if let [proj_base @ .., elem] = place.projection {
- let base_qualif = Self::in_place(cx, per_local, PlaceRef {
- base: place.base,
- projection: proj_base,
- });
- let qualif = base_qualif && Self::in_any_value_of_ty(
+ let base_qualif = Self::in_place(
cx,
- Place::ty_from(place.base, proj_base, *cx.body, cx.tcx)
- .projection_ty(cx.tcx, elem)
- .ty,
+ per_local,
+ PlaceRef { local: place.local, projection: proj_base },
);
+ let qualif = base_qualif
+ && Self::in_any_value_of_ty(
+ cx,
+ Place::ty_from(place.local, proj_base, *cx.body, cx.tcx)
+ .projection_ty(cx.tcx, elem)
+ .ty,
+ );
match elem {
- ProjectionElem::Deref |
- ProjectionElem::Subslice { .. } |
- ProjectionElem::Field(..) |
- ProjectionElem::ConstantIndex { .. } |
- ProjectionElem::Downcast(..) => qualif,
+ ProjectionElem::Deref
+ | ProjectionElem::Subslice { .. }
+ | ProjectionElem::Field(..)
+ | ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::Downcast(..) => qualif,
ProjectionElem::Index(local) => qualif || per_local(*local),
}
place: PlaceRef<'_, 'tcx>,
) -> bool {
match place {
- PlaceRef {
- base: PlaceBase::Local(local),
- projection: [],
- } => per_local(*local),
- PlaceRef {
- base: PlaceBase::Static(_),
- projection: [],
- } => bug!("qualifying already promoted MIR"),
- PlaceRef {
- base: _,
- projection: [.., _],
- } => Self::in_projection(cx, per_local, place),
+ PlaceRef { local, projection: [] } => per_local(*local),
+ PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
}
}
operand: &Operand<'tcx>,
) -> bool {
match *operand {
- Operand::Copy(ref place) |
- Operand::Move(ref place) => Self::in_place(cx, per_local, place.as_ref()),
+ Operand::Copy(ref place) | Operand::Move(ref place) => {
+ Self::in_place(cx, per_local, place.as_ref())
+ }
Operand::Constant(ref constant) => {
- if let Some(static_) = constant.check_static_ptr(cx.tcx) {
- Self::in_static(cx, static_)
- } else if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
+ if constant.check_static_ptr(cx.tcx).is_some() {
+ // `mir_const_qualif` does return the qualifs in the final value of a `static`,
+ // so we could use value-based qualification here, but we shouldn't do this
+ // without a good reason.
+ //
+ // Note: this uses `constant.literal.ty` which is a reference or pointer to the
+ // type of the actual `static` item.
+ Self::in_any_value_of_ty(cx, constant.literal.ty)
+ } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val
+ {
+ assert!(promoted.is_none());
// Don't peek inside trait associated constants.
if cx.tcx.trait_of_item(def_id).is_some() {
Self::in_any_value_of_ty(cx, constant.literal.ty)
match *rvalue {
Rvalue::NullaryOp(..) => false,
- Rvalue::Discriminant(ref place) |
- Rvalue::Len(ref place) => Self::in_place(cx, per_local, place.as_ref()),
+ Rvalue::Discriminant(ref place) | Rvalue::Len(ref place) => {
+ Self::in_place(cx, per_local, place.as_ref())
+ }
- Rvalue::Use(ref operand) |
- Rvalue::Repeat(ref operand, _) |
- Rvalue::UnaryOp(_, ref operand) |
- Rvalue::Cast(_, ref operand, _) => Self::in_operand(cx, per_local, operand),
+ Rvalue::Use(ref operand)
+ | Rvalue::Repeat(ref operand, _)
+ | Rvalue::UnaryOp(_, ref operand)
+ | Rvalue::Cast(_, ref operand, _) => Self::in_operand(cx, per_local, operand),
- Rvalue::BinaryOp(_, ref lhs, ref rhs) |
- Rvalue::CheckedBinaryOp(_, ref lhs, ref rhs) => {
+ Rvalue::BinaryOp(_, ref lhs, ref rhs)
+ | Rvalue::CheckedBinaryOp(_, ref lhs, ref rhs) => {
Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs)
}
- Rvalue::Ref(_, _, ref place) => {
+ Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
// Special-case reborrows to be more like a copy of the reference.
- if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
- if ProjectionElem::Deref == elem {
- let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty;
- if let ty::Ref(..) = base_ty.kind {
- return Self::in_place(cx, per_local, PlaceRef {
- base: &place.base,
- projection: proj_base,
- });
- }
+ if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
+ let base_ty = Place::ty_from(&place.local, proj_base, *cx.body, cx.tcx).ty;
+ if let ty::Ref(..) = base_ty.kind {
+ return Self::in_place(
+ cx,
+ per_local,
+ PlaceRef { local: &place.local, projection: proj_base },
+ );
}
}