1 #![deny(rustc::untranslatable_diagnostic)]
2 #![deny(rustc::diagnostic_outside_of_impl)]
3 use crate::borrow_set
::LocalsStateAtExit
;
5 use rustc_middle
::mir
::ProjectionElem
;
6 use rustc_middle
::mir
::{Body, Mutability, Place}
;
7 use rustc_middle
::ty
::{self, TyCtxt}
;
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.
19 locals_state_at_exit
: &LocalsStateAtExit
,
23 impl<'tcx
> PlaceExt
<'tcx
> for Place
<'tcx
> {
28 locals_state_at_exit
: &LocalsStateAtExit
,
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 if let LocalsStateAtExit
::SomeAreInvalidated { has_storage_dead_or_moved }
=
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
);
49 for (i
, elem
) in self.projection
.iter().enumerate() {
50 let proj_base
= &self.projection
[..i
];
52 if elem
== ProjectionElem
::Deref
{
53 let ty
= Place
::ty_from(self.local
, proj_base
, body
, tcx
).ty
;
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() {
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