|
1 | 1 | use rustc::hir;
|
2 | 2 | use rustc::mir::ProjectionElem;
|
3 |
| -use rustc::mir::{Mir, Place, PlaceBase, Mutability}; |
| 3 | +use rustc::mir::{Mir, Place, NeoPlace, PlaceBase, Mutability}; |
4 | 4 | use rustc::mir::tcx::PlaceTy;
|
5 | 5 | use rustc::ty::{self, TyCtxt};
|
6 | 6 | use borrow_check::borrow_set::LocalsStateAtExit;
|
@@ -76,3 +76,60 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
76 | 76 | is_unsafe_place
|
77 | 77 | }
|
78 | 78 | }
|
| 79 | + |
| 80 | +impl<'tcx> PlaceExt<'tcx> for NeoPlace<'tcx> { |
| 81 | + fn ignore_borrow( |
| 82 | + &self, |
| 83 | + tcx: TyCtxt<'_, '_, 'tcx>, |
| 84 | + mir: &Mir<'tcx>, |
| 85 | + locals_state_at_exit: &LocalsStateAtExit, |
| 86 | + ) -> bool { |
| 87 | + let mut is_unsafe_place = match &self.base { |
| 88 | + // If a local variable is immutable, then we only need to track borrows to guard |
| 89 | + // against two kinds of errors: |
| 90 | + // * The variable being dropped while still borrowed (e.g., because the fn returns |
| 91 | + // a reference to a local variable) |
| 92 | + // * The variable being moved while still borrowed |
| 93 | + // |
| 94 | + // In particular, the variable cannot be mutated -- the "access checks" will fail -- |
| 95 | + // so we don't have to worry about mutation while borrowed. |
| 96 | + PlaceBase::Local(index) => { |
| 97 | + match locals_state_at_exit { |
| 98 | + LocalsStateAtExit::AllAreInvalidated => false, |
| 99 | + LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => { |
| 100 | + let ignore = !has_storage_dead_or_moved.contains(*index) && |
| 101 | + mir.local_decls[*index].mutability == Mutability::Not; |
| 102 | + debug!("ignore_borrow: local {:?} => {:?}", index, ignore); |
| 103 | + ignore |
| 104 | + } |
| 105 | + } |
| 106 | + }, |
| 107 | + PlaceBase::Promoted(_) => false, |
| 108 | + PlaceBase::Static(static_) => { |
| 109 | + tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable) |
| 110 | + } |
| 111 | + }; |
| 112 | + |
| 113 | + let mut base_ty = self.base.ty(mir); |
| 114 | + for elem in self.elems.iter() { |
| 115 | + if let ProjectionElem::Deref = elem { |
| 116 | + if let ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) = base_ty.sty { |
| 117 | + // For both derefs of raw pointers and `&T` |
| 118 | + // references, the original path is `Copy` and |
| 119 | + // therefore not significant. In particular, |
| 120 | + // there is nothing the user can do to the |
| 121 | + // original path that would invalidate the |
| 122 | + // newly created reference -- and if there |
| 123 | + // were, then the user could have copied the |
| 124 | + // original path into a new variable and |
| 125 | + // borrowed *that* one, leaving the original |
| 126 | + // path unborrowed. |
| 127 | + is_unsafe_place = true; |
| 128 | + } |
| 129 | + } |
| 130 | + base_ty = PlaceTy::from(base_ty).projection_ty(tcx, elem).to_ty(tcx); |
| 131 | + } |
| 132 | + |
| 133 | + is_unsafe_place |
| 134 | + } |
| 135 | +} |
0 commit comments