1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// ----------------------------------------------------------------------
// Loan(Ex, M, S) = Ls holds if ToAddr(Ex) will remain valid for the entirety
// of the scope S, presuming that the returned set of loans `Ls` are honored.
export public_methods;
impl public_methods for borrowck_ctxt {
fn loan(cmt: cmt, mutbl: ast::mutability) -> @dvec<loan> {
let lc = @{bccx: self, loans: @dvec()};
lc.loan(cmt, mutbl);
ret lc.loans;
}
}
type loan_ctxt = @{
bccx: borrowck_ctxt,
loans: @dvec<loan>
};
impl loan_methods for loan_ctxt {
fn ok_with_loan_of(cmt: cmt,
mutbl: ast::mutability) {
// Note: all cmt's that we deal with will have a non-none lp, because
// the entry point into this routine, `borrowck_ctxt::loan()`, rejects
// any cmt with a none-lp.
(*self.loans).push({lp:option::get(cmt.lp),
cmt:cmt,
mutbl:mutbl});
}
fn loan(cmt: cmt, req_mutbl: ast::mutability) {
#debug["loan(%s, %s)",
self.bccx.cmt_to_repr(cmt),
self.bccx.mut_to_str(req_mutbl)];
let _i = indenter();
// see stable() above; should only be called when `cmt` is lendable
if cmt.lp.is_none() {
self.bccx.tcx.sess.span_bug(
cmt.span,
"loan() called with non-lendable value");
}
alt cmt.cat {
cat_binding(_) | cat_rvalue | cat_special(_) {
// should never be loanable
self.bccx.tcx.sess.span_bug(
cmt.span,
"rvalue with a non-none lp");
}
cat_local(_) | cat_arg(_) | cat_stack_upvar(_) {
self.ok_with_loan_of(cmt, req_mutbl)
}
cat_discr(base, _) {
self.loan(base, req_mutbl)
}
cat_comp(cmt_base, comp_field(*)) |
cat_comp(cmt_base, comp_index(*)) |
cat_comp(cmt_base, comp_tuple) {
// For most components, the type of the embedded data is
// stable. Therefore, the base structure need only be
// const---unless the component must be immutable. In
// that case, it must also be embedded in an immutable
// location, or else the whole structure could be
// overwritten and the component along with it.
self.loan_stable_comp(cmt, cmt_base, req_mutbl)
}
cat_comp(cmt_base, comp_variant(enum_did)) {
// For enums, the memory is unstable if there are multiple
// variants, because if the enum value is overwritten then
// the memory changes type.
if ty::enum_is_univariant(self.bccx.tcx, enum_did) {
self.loan_stable_comp(cmt, cmt_base, req_mutbl)
} else {
self.loan_unstable_deref(cmt, cmt_base, req_mutbl)
}
}
cat_deref(cmt_base, _, uniq_ptr) {
// For unique pointers, the memory being pointed out is
// unstable because if the unique pointer is overwritten
// then the memory is freed.
self.loan_unstable_deref(cmt, cmt_base, req_mutbl)
}
cat_deref(cmt1, _, unsafe_ptr) |
cat_deref(cmt1, _, gc_ptr) |
cat_deref(cmt1, _, region_ptr) {
// Aliased data is simply not lendable.
self.bccx.tcx.sess.span_bug(
cmt.span,
"aliased ptr with a non-none lp");
}
}
}
// A "stable component" is one where assigning the base of the
// component cannot cause the component itself to change types.
// Example: record fields.
fn loan_stable_comp(cmt: cmt,
cmt_base: cmt,
req_mutbl: ast::mutability) {
let base_mutbl = alt req_mutbl {
m_imm { m_imm }
m_const | m_mutbl { m_const }
};
self.loan(cmt_base, base_mutbl);
self.ok_with_loan_of(cmt, req_mutbl)
}
// An "unstable deref" means a deref of a ptr/comp where, if the
// base of the deref is assigned to, pointers into the result of the
// deref would be invalidated. Examples: interior of variants, uniques.
fn loan_unstable_deref(cmt: cmt,
cmt_base: cmt,
req_mutbl: ast::mutability) {
// Variant components: the base must be immutable, because
// if it is overwritten, the types of the embedded data
// could change.
self.loan(cmt_base, m_imm);
self.ok_with_loan_of(cmt, req_mutbl)
}
}
|