]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/place_ext.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / place_ext.rs
CommitLineData
c295e0f8 1use crate::borrow_set::LocalsStateAtExit;
dfeec247 2use rustc_hir as hir;
ba9703b0
XL
3use rustc_middle::mir::ProjectionElem;
4use rustc_middle::mir::{Body, Mutability, Place};
5use rustc_middle::ty::{self, TyCtxt};
83c7162d
XL
6
7/// Extension methods for the `Place` type.
8crate trait PlaceExt<'tcx> {
9fa01778 9 /// Returns `true` if we can safely ignore borrows of this place.
b7449926
XL
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,
dc9dc135
XL
15 tcx: TyCtxt<'tcx>,
16 body: &Body<'tcx>,
b7449926 17 locals_state_at_exit: &LocalsStateAtExit,
dc9dc135 18 ) -> bool;
83c7162d
XL
19}
20
21impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
b7449926
XL
22 fn ignore_borrow(
23 &self,
dc9dc135
XL
24 tcx: TyCtxt<'tcx>,
25 body: &Body<'tcx>,
b7449926
XL
26 locals_state_at_exit: &LocalsStateAtExit,
27 ) -> bool {
dfeec247
XL
28 // If a local variable is immutable, then we only need to track borrows to guard
29 // against two kinds of errors:
30 // * The variable being dropped while still borrowed (e.g., because the fn returns
31 // a reference to a local variable)
32 // * The variable being moved while still borrowed
33 //
34 // In particular, the variable cannot be mutated -- the "access checks" will fail --
35 // so we don't have to worry about mutation while borrowed.
36 if let LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } =
37 locals_state_at_exit
38 {
39 let ignore = !has_storage_dead_or_moved.contains(self.local)
40 && body.local_decls[self.local].mutability == Mutability::Not;
41 debug!("ignore_borrow: local {:?} => {:?}", self.local, ignore);
42 if ignore {
43 return true;
e1599b0c 44 }
dfeec247 45 }
b7449926 46
e1599b0c
XL
47 for (i, elem) in self.projection.iter().enumerate() {
48 let proj_base = &self.projection[..i];
49
f9f354fc 50 if elem == ProjectionElem::Deref {
74b04a01 51 let ty = Place::ty_from(self.local, proj_base, body, tcx).ty;
1b1a35ee 52 match ty.kind() {
dfeec247 53 ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
60c5eb7d
XL
54 // For references to thread-local statics, we do need
55 // to track the borrow.
dfeec247 56 if body.local_decls[self.local].is_ref_to_thread_local() {
60c5eb7d
XL
57 continue;
58 }
59 return true;
60 }
dfeec247 61 ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Not) => {
60c5eb7d
XL
62 // For both derefs of raw pointers and `&T`
63 // references, the original path is `Copy` and
64 // therefore not significant. In particular,
65 // there is nothing the user can do to the
66 // original path that would invalidate the
67 // newly created reference -- and if there
68 // were, then the user could have copied the
69 // original path into a new variable and
70 // borrowed *that* one, leaving the original
71 // path unborrowed.
72 return true;
73 }
74 _ => {}
83c7162d 75 }
dc9dc135 76 }
e1599b0c 77 }
dc9dc135 78
60c5eb7d 79 false
83c7162d 80 }
83c7162d 81}