]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_borrowck/src/place_ext.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / place_ext.rs
1 #![deny(rustc::untranslatable_diagnostic)]
2 #![deny(rustc::diagnostic_outside_of_impl)]
3 use crate::borrow_set::LocalsStateAtExit;
4 use rustc_hir as hir;
5 use rustc_middle::mir::ProjectionElem;
6 use rustc_middle::mir::{Body, Mutability, Place};
7 use rustc_middle::ty::{self, TyCtxt};
8
9 /// Extension methods for the `Place` type.
10 pub(crate) trait PlaceExt<'tcx> {
11 /// Returns `true` if we can safely ignore borrows of this place.
12 /// This is true whenever there is no action that the user can do
13 /// to the place `self` that would invalidate the borrow. This is true
14 /// for borrows of raw pointer dereferents as well as shared references.
15 fn ignore_borrow(
16 &self,
17 tcx: TyCtxt<'tcx>,
18 body: &Body<'tcx>,
19 locals_state_at_exit: &LocalsStateAtExit,
20 ) -> bool;
21 }
22
23 impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
24 fn ignore_borrow(
25 &self,
26 tcx: TyCtxt<'tcx>,
27 body: &Body<'tcx>,
28 locals_state_at_exit: &LocalsStateAtExit,
29 ) -> bool {
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
35 //
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 if let LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } =
39 locals_state_at_exit
40 {
41 let ignore = !has_storage_dead_or_moved.contains(self.local)
42 && body.local_decls[self.local].mutability == Mutability::Not;
43 debug!("ignore_borrow: local {:?} => {:?}", self.local, ignore);
44 if ignore {
45 return true;
46 }
47 }
48
49 for (i, elem) in self.projection.iter().enumerate() {
50 let proj_base = &self.projection[..i];
51
52 if elem == ProjectionElem::Deref {
53 let ty = Place::ty_from(self.local, proj_base, body, tcx).ty;
54 match ty.kind() {
55 ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
56 // For references to thread-local statics, we do need
57 // to track the borrow.
58 if body.local_decls[self.local].is_ref_to_thread_local() {
59 continue;
60 }
61 return true;
62 }
63 ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Not) => {
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 return true;
75 }
76 _ => {}
77 }
78 }
79 }
80
81 false
82 }
83 }