]>
git.proxmox.com Git - rustc.git/blob - src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Computes the restrictions that result from a borrow.
13 pub use self::RestrictionResult
::*;
16 use rustc
::middle
::expr_use_visitor
as euv
;
17 use rustc
::middle
::mem_categorization
as mc
;
18 use rustc
::middle
::mem_categorization
::Categorization
;
19 use rustc
::middle
::ty
;
20 use syntax
::codemap
::Span
;
22 use borrowck
::ToInteriorKind
;
27 pub enum RestrictionResult
<'tcx
> {
29 SafeIf(Rc
<LoanPath
<'tcx
>>, Vec
<Rc
<LoanPath
<'tcx
>>>)
32 pub fn compute_restrictions
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
34 cause
: euv
::LoanCause
,
36 loan_region
: ty
::Region
)
37 -> RestrictionResult
<'tcx
> {
38 let ctxt
= RestrictionsContext
{
42 loan_region
: loan_region
,
48 ///////////////////////////////////////////////////////////////////////////
51 struct RestrictionsContext
<'a
, 'tcx
: 'a
> {
52 bccx
: &'a BorrowckCtxt
<'a
, 'tcx
>,
54 loan_region
: ty
::Region
,
55 cause
: euv
::LoanCause
,
58 impl<'a
, 'tcx
> RestrictionsContext
<'a
, 'tcx
> {
60 cmt
: mc
::cmt
<'tcx
>) -> RestrictionResult
<'tcx
> {
61 debug
!("restrict(cmt={:?})", cmt
);
63 let new_lp
= |v
: LoanPathKind
<'tcx
>| Rc
::new(LoanPath
::new(v
, cmt
.ty
));
65 match cmt
.cat
.clone() {
66 Categorization
::Rvalue(..) => {
67 // Effectively, rvalues are stored into a
68 // non-aliasable temporary on the stack. Since they
69 // are inherently non-aliasable, they can only be
70 // accessed later through the borrow itself and hence
71 // must inherently comply with its terms.
75 Categorization
::Local(local_id
) => {
76 // R-Variable, locally declared
77 let lp
= new_lp(LpVar(local_id
));
78 SafeIf(lp
.clone(), vec
![lp
])
81 Categorization
::Upvar(mc
::Upvar { id, .. }
) => {
82 // R-Variable, captured into closure
83 let lp
= new_lp(LpUpvar(id
));
84 SafeIf(lp
.clone(), vec
![lp
])
87 Categorization
::Downcast(cmt_base
, _
) => {
88 // When we borrow the interior of an enum, we have to
89 // ensure the enum itself is not mutated, because that
90 // could cause the type of the memory to change.
91 self.restrict(cmt_base
)
94 Categorization
::Interior(cmt_base
, i
) => {
97 // Overwriting the base would not change the type of
98 // the memory, so no additional restrictions are
100 let result
= self.restrict(cmt_base
);
101 self.extend(result
, &cmt
, LpInterior(i
.cleaned()))
104 Categorization
::StaticItem
=> {
108 Categorization
::Deref(cmt_base
, _
, pk
) => {
111 // R-Deref-Send-Pointer
113 // When we borrow the interior of a box, we
114 // cannot permit the base to be mutated, because that
115 // would cause the unique pointer to be freed.
117 // Eventually we should make these non-special and
118 // just rely on Deref<T> implementation.
119 let result
= self.restrict(cmt_base
);
120 self.extend(result
, &cmt
, LpDeref(pk
))
122 mc
::Implicit(bk
, lt
) | mc
::BorrowedPtr(bk
, lt
) => {
123 // R-Deref-[Mut-]Borrowed
124 if !self.bccx
.is_subregion_of(self.loan_region
, lt
) {
128 cause
: BorrowViolation(self.cause
),
130 code
: err_borrowed_pointer_too_short(
131 self.loan_region
, lt
)});
136 ty
::ImmBorrow
=> Safe
,
137 ty
::MutBorrow
| ty
::UniqueImmBorrow
=> {
138 // R-Deref-Mut-Borrowed
140 // The referent can be aliased after the
141 // references lifetime ends (by a newly-unfrozen
143 let result
= self.restrict(cmt_base
);
144 self.extend(result
, &cmt
, LpDeref(pk
))
148 // Borrowck is not relevant for raw pointers
149 mc
::UnsafePtr(..) => Safe
156 result
: RestrictionResult
<'tcx
>,
158 elem
: LoanPathElem
) -> RestrictionResult
<'tcx
> {
161 SafeIf(base_lp
, mut base_vec
) => {
162 let v
= LpExtend(base_lp
, cmt
.mutbl
, elem
);
163 let lp
= Rc
::new(LoanPath
::new(v
, cmt
.ty
));
164 base_vec
.push(lp
.clone());