2 use rustc::mir::ProjectionElem;
3 use rustc::mir::{Body, Place, PlaceBase, Mutability, Static, StaticKind};
4 use rustc::ty::{self, TyCtxt};
5 use crate::borrow_check::borrow_set::LocalsStateAtExit;
7 /// Extension methods for the `Place` type.
8 crate trait PlaceExt<'tcx> {
9 /// Returns `true` if we can safely ignore borrows of this place.
10 /// This is true whenever there is no action that the user can do
11 /// to the place `self` that would invalidate the borrow. This is true
12 /// for borrows of raw pointer dereferents as well as shared references.
17 locals_state_at_exit: &LocalsStateAtExit,
21 impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
26 locals_state_at_exit: &LocalsStateAtExit,
28 self.iterate(|place_base, place_projection| {
29 let ignore = match place_base {
30 // If a local variable is immutable, then we only need to track borrows to guard
31 // against two kinds of errors:
32 // * The variable being dropped while still borrowed (e.g., because the fn returns
33 // a reference to a local variable)
34 // * The variable being moved while still borrowed
36 // In particular, the variable cannot be mutated -- the "access checks" will fail --
37 // so we don't have to worry about mutation while borrowed.
38 PlaceBase::Local(index) => {
39 match locals_state_at_exit {
40 LocalsStateAtExit::AllAreInvalidated => false,
41 LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
42 let ignore = !has_storage_dead_or_moved.contains(*index) &&
43 body.local_decls[*index].mutability == Mutability::Not;
44 debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
49 PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) =>
51 PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
52 tcx.is_mutable_static(*def_id)
56 for proj in place_projection {
57 if proj.elem == ProjectionElem::Deref {
58 let ty = Place::ty_from(place_base, &proj.base, body, tcx).ty;
60 // For both derefs of raw pointers and `&T`
61 // references, the original path is `Copy` and
62 // therefore not significant. In particular,
63 // there is nothing the user can do to the
64 // original path that would invalidate the
65 // newly created reference -- and if there
66 // were, then the user could have copied the
67 // original path into a new variable and
68 // borrowed *that* one, leaving the original
70 ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => return true,