]>
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
::ty
;
19 use syntax
::codemap
::Span
;
21 use borrowck
::ToInteriorKind
;
26 pub enum RestrictionResult
<'tcx
> {
28 SafeIf(Rc
<LoanPath
<'tcx
>>, Vec
<Rc
<LoanPath
<'tcx
>>>)
31 pub fn compute_restrictions
<'a
, 'tcx
>(bccx
: &BorrowckCtxt
<'a
, 'tcx
>,
33 cause
: euv
::LoanCause
,
35 loan_region
: ty
::Region
)
36 -> RestrictionResult
<'tcx
> {
37 let ctxt
= RestrictionsContext
{
41 loan_region
: loan_region
,
47 ///////////////////////////////////////////////////////////////////////////
50 struct RestrictionsContext
<'a
, 'tcx
: 'a
> {
51 bccx
: &'a BorrowckCtxt
<'a
, 'tcx
>,
53 loan_region
: ty
::Region
,
54 cause
: euv
::LoanCause
,
57 impl<'a
, 'tcx
> RestrictionsContext
<'a
, 'tcx
> {
59 cmt
: mc
::cmt
<'tcx
>) -> RestrictionResult
<'tcx
> {
60 debug
!("restrict(cmt={:?})", cmt
);
62 let new_lp
= |v
: LoanPathKind
<'tcx
>| Rc
::new(LoanPath
::new(v
, cmt
.ty
));
64 match cmt
.cat
.clone() {
65 mc
::cat_rvalue(..) => {
66 // Effectively, rvalues are stored into a
67 // non-aliasable temporary on the stack. Since they
68 // are inherently non-aliasable, they can only be
69 // accessed later through the borrow itself and hence
70 // must inherently comply with its terms.
74 mc
::cat_local(local_id
) => {
75 // R-Variable, locally declared
76 let lp
= new_lp(LpVar(local_id
));
77 SafeIf(lp
.clone(), vec
![lp
])
80 mc
::cat_upvar(mc
::Upvar { id, .. }
) => {
81 // R-Variable, captured into closure
82 let lp
= new_lp(LpUpvar(id
));
83 SafeIf(lp
.clone(), vec
![lp
])
86 mc
::cat_downcast(cmt_base
, _
) => {
87 // When we borrow the interior of an enum, we have to
88 // ensure the enum itself is not mutated, because that
89 // could cause the type of the memory to change.
90 self.restrict(cmt_base
)
93 mc
::cat_interior(cmt_base
, i
) => {
96 // Overwriting the base would not change the type of
97 // the memory, so no additional restrictions are
99 let result
= self.restrict(cmt_base
);
100 self.extend(result
, &cmt
, LpInterior(i
.cleaned()))
103 mc
::cat_static_item(..) => {
107 mc
::cat_deref(cmt_base
, _
, pk
) => {
110 // R-Deref-Send-Pointer
112 // When we borrow the interior of a box, we
113 // cannot permit the base to be mutated, because that
114 // would cause the unique pointer to be freed.
116 // Eventually we should make these non-special and
117 // just rely on Deref<T> implementation.
118 let result
= self.restrict(cmt_base
);
119 self.extend(result
, &cmt
, LpDeref(pk
))
121 mc
::Implicit(bk
, lt
) | mc
::BorrowedPtr(bk
, lt
) => {
122 // R-Deref-[Mut-]Borrowed
123 if !self.bccx
.is_subregion_of(self.loan_region
, lt
) {
127 cause
: BorrowViolation(self.cause
),
129 code
: err_borrowed_pointer_too_short(
130 self.loan_region
, lt
)});
135 ty
::ImmBorrow
=> Safe
,
136 ty
::MutBorrow
| ty
::UniqueImmBorrow
=> {
137 // R-Deref-Mut-Borrowed
139 // The referent can be aliased after the
140 // references lifetime ends (by a newly-unfrozen
142 let result
= self.restrict(cmt_base
);
143 self.extend(result
, &cmt
, LpDeref(pk
))
147 // Borrowck is not relevant for raw pointers
148 mc
::UnsafePtr(..) => Safe
155 result
: RestrictionResult
<'tcx
>,
157 elem
: LoanPathElem
) -> RestrictionResult
<'tcx
> {
160 SafeIf(base_lp
, mut base_vec
) => {
161 let v
= LpExtend(base_lp
, cmt
.mutbl
, elem
);
162 let lp
= Rc
::new(LoanPath
::new(v
, cmt
.ty
));
163 base_vec
.push(lp
.clone());