]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/place_ext.rs
Rollup merge of #60453 - tbu-:pr_getrandom_enoperm, r=sfackler
[rust.git] / src / librustc_mir / borrow_check / place_ext.rs
1 use rustc::hir;
2 use rustc::mir::ProjectionElem;
3 use rustc::mir::{Mir, Place, PlaceBase, Mutability, Static, StaticKind};
4 use rustc::ty::{self, TyCtxt};
5 use crate::borrow_check::borrow_set::LocalsStateAtExit;
6
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.
13     fn ignore_borrow(
14         &self,
15         tcx: TyCtxt<'_, '_, 'tcx>,
16         mir: &Mir<'tcx>,
17         locals_state_at_exit: &LocalsStateAtExit,
18         ) -> bool;
19 }
20
21 impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
22     fn ignore_borrow(
23         &self,
24         tcx: TyCtxt<'_, '_, 'tcx>,
25         mir: &Mir<'tcx>,
26         locals_state_at_exit: &LocalsStateAtExit,
27     ) -> bool {
28         match self {
29             // If a local variable is immutable, then we only need to track borrows to guard
30             // against two kinds of errors:
31             // * The variable being dropped while still borrowed (e.g., because the fn returns
32             //   a reference to a local variable)
33             // * The variable being moved while still borrowed
34             //
35             // In particular, the variable cannot be mutated -- the "access checks" will fail --
36             // so we don't have to worry about mutation while borrowed.
37             Place::Base(PlaceBase::Local(index)) => {
38                 match locals_state_at_exit {
39                     LocalsStateAtExit::AllAreInvalidated => false,
40                     LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
41                         let ignore = !has_storage_dead_or_moved.contains(*index) &&
42                             mir.local_decls[*index].mutability == Mutability::Not;
43                         debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
44                         ignore
45                     }
46                 }
47             }
48             Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
49                 false,
50             Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
51                 tcx.is_mutable_static(*def_id)
52             }
53             Place::Projection(proj) => match proj.elem {
54                 ProjectionElem::Field(..)
55                 | ProjectionElem::Downcast(..)
56                 | ProjectionElem::Subslice { .. }
57                 | ProjectionElem::ConstantIndex { .. }
58                 | ProjectionElem::Index(_) => proj.base.ignore_borrow(
59                     tcx, mir, locals_state_at_exit),
60
61                 ProjectionElem::Deref => {
62                     let ty = proj.base.ty(mir, tcx).ty;
63                     match ty.sty {
64                         // For both derefs of raw pointers and `&T`
65                         // references, the original path is `Copy` and
66                         // therefore not significant.  In particular,
67                         // there is nothing the user can do to the
68                         // original path that would invalidate the
69                         // newly created reference -- and if there
70                         // were, then the user could have copied the
71                         // original path into a new variable and
72                         // borrowed *that* one, leaving the original
73                         // path unborrowed.
74                         ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => true,
75                         _ => proj.base.ignore_borrow(tcx, mir, locals_state_at_exit),
76                     }
77                 }
78             },
79         }
80     }
81 }