//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
-use rustc::hir::{def_id::DefId, HirId};
use rustc::middle::lang_items;
use rustc::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc::mir::*;
use rustc::ty::cast::CastTy;
use rustc::ty::{self, TyCtxt};
use rustc_error_codes::*;
+use rustc_errors::struct_span_err;
+use rustc_hir::{def_id::DefId, HirId};
use rustc_index::bit_set::BitSet;
use rustc_span::symbol::sym;
use rustc_span::Span;
use super::qualifs::{self, HasMutInterior, NeedsDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{is_lang_panic_fn, ConstKind, Item, Qualif};
+use crate::const_eval::{is_const_fn, is_unstable_const_fn};
use crate::dataflow::{self as old_dataflow, generic as dataflow};
pub type IndirectlyMutableResults<'mir, 'tcx> =
let Item { tcx, body, def_id, const_kind, .. } = *self.item;
let use_min_const_fn_checks = (const_kind == Some(ConstKind::ConstFn)
- && tcx.is_min_const_fn(def_id))
+ && crate::const_eval::is_min_const_fn(tcx, def_id))
&& !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
if use_min_const_fn_checks {
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
}
};
- self.visit_place_base(&place.base, ctx, location);
- self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+ self.visit_place_base(&place.local, ctx, location);
+ self.visit_projection(&place.local, reborrowed_proj, ctx, location);
return;
}
}
}
Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
};
- self.visit_place_base(&place.base, ctx, location);
- self.visit_projection(&place.base, reborrowed_proj, ctx, location);
+ self.visit_place_base(&place.local, ctx, location);
+ self.visit_projection(&place.local, reborrowed_proj, ctx, location);
return;
}
}
Rvalue::AddressOf(Mutability::Mut, _) => self.check_op(ops::MutAddressOf),
- // At the moment, `PlaceBase::Static` is only used for promoted MIR.
- Rvalue::Ref(_, BorrowKind::Shared, ref place)
- | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
- | Rvalue::AddressOf(Mutability::Not, ref place)
- if matches!(place.base, PlaceBase::Static(_)) =>
- {
- bug!("Saw a promoted during const-checking, which must run before promotion")
- }
-
Rvalue::Ref(_, BorrowKind::Shared, ref place)
| Rvalue::Ref(_, BorrowKind::Shallow, ref place) => {
self.check_immutable_borrow_like(location, place)
}
}
- fn visit_place_base(
- &mut self,
- place_base: &PlaceBase<'tcx>,
- context: PlaceContext,
- location: Location,
- ) {
+ fn visit_place_base(&mut self, place_local: &Local, context: PlaceContext, location: Location) {
trace!(
- "visit_place_base: place_base={:?} context={:?} location={:?}",
- place_base,
+ "visit_place_base: place_local={:?} context={:?} location={:?}",
+ place_local,
context,
location,
);
- self.super_place_base(place_base, context, location);
-
- match place_base {
- PlaceBase::Local(_) => {}
- PlaceBase::Static(_) => {
- bug!("Promotion must be run after const validation");
- }
- }
+ self.super_place_base(place_local, context, location);
}
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
}
fn visit_projection_elem(
&mut self,
- place_base: &PlaceBase<'tcx>,
+ place_local: &Local,
proj_base: &[PlaceElem<'tcx>],
elem: &PlaceElem<'tcx>,
context: PlaceContext,
location: Location,
) {
trace!(
- "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
+ "visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
context={:?} location={:?}",
- place_base,
+ place_local,
proj_base,
elem,
context,
location,
);
- self.super_projection_elem(place_base, proj_base, elem, context, location);
+ self.super_projection_elem(place_local, proj_base, elem, context, location);
match elem {
ProjectionElem::Deref => {
- let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
+ let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
if let ty::RawPtr(_) = base_ty.kind {
if proj_base.is_empty() {
- if let (PlaceBase::Local(local), []) = (place_base, proj_base) {
+ if let (local, []) = (place_local, proj_base) {
let decl = &self.body.local_decls[*local];
if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
let span = decl.source_info.span;
| ProjectionElem::Subslice { .. }
| ProjectionElem::Field(..)
| ProjectionElem::Index(_) => {
- let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty;
+ let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty;
match base_ty.ty_adt_def() {
Some(def) if def.is_union() => {
self.check_op(ops::UnionAccess);
};
// At this point, we are calling a function whose `DefId` is known...
- if self.tcx.is_const_fn(def_id) {
+ if is_const_fn(self.tcx, def_id) {
return;
}
if is_lang_panic_fn(self.tcx, def_id) {
self.check_op(ops::Panic);
- } else if let Some(feature) = self.tcx.is_unstable_const_fn(def_id) {
+ } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
// Exempt unstable const fns inside of macros with
// `#[allow_internal_unstable]`.
if !self.span.allows_unstable(feature) {
// A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
// that points to the allocation for the static. Don't treat these as reborrows.
- if let PlaceBase::Local(local) = place.base {
- if body.local_decls[local].is_ref_to_static() {
- return None;
- }
+ if body.local_decls[place.local].is_ref_to_static() {
+ return None;
}
// Ensure the type being derefed is a reference and not a raw pointer.
//
// This is sufficient to prevent an access to a `static mut` from being marked as a
// reborrow, even if the check above were to disappear.
- let inner_ty = Place::ty_from(&place.base, inner, body, tcx).ty;
+ let inner_ty = Place::ty_from(&place.local, inner, body, tcx).ty;
match inner_ty.kind {
ty::Ref(..) => Some(inner),
_ => None,