Skip to content

Commit 168306f

Browse files
committed
correct treatment of mutability for deref'd components
Fixes #2980
1 parent 1df5c52 commit 168306f

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

src/rustc/middle/borrowck/categorization.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,18 @@ impl public_methods for borrowck_ctxt {
293293
ret @{cat:cat_discr(cmt, alt_id) with *cmt};
294294
}
295295

296+
/// inherited mutability: used in cases where the mutability of a
297+
/// component is inherited from the base it is a part of. For
298+
/// example, a record field is mutable if it is declared mutable
299+
/// or if the container is mutable.
300+
fn inherited_mutability(base_m: ast::mutability,
301+
comp_m: ast::mutability) -> ast::mutability {
302+
alt comp_m {
303+
m_imm => {base_m} // imm: as mutable as the container
304+
m_mutbl | m_const => {comp_m}
305+
}
306+
}
307+
296308
fn cat_field<N:ast_node>(node: N, base_cmt: cmt,
297309
f_name: ast::ident) -> cmt {
298310
let f_mutbl = alt field_mutbl(self.tcx, base_cmt.ty, f_name) {
@@ -304,10 +316,7 @@ impl public_methods for borrowck_ctxt {
304316
*f_name, ty_to_str(self.tcx, base_cmt.ty)]);
305317
}
306318
};
307-
let m = alt f_mutbl {
308-
m_imm { base_cmt.mutbl } // imm: as mutable as the container
309-
m_mutbl | m_const { f_mutbl }
310-
};
319+
let m = self.inherited_mutability(base_cmt.mutbl, f_mutbl);
311320
let f_comp = comp_field(f_name, f_mutbl);
312321
let lp = base_cmt.lp.map(|lp| @lp_comp(lp, f_comp) );
313322
@{id: node.id(), span: node.span(),
@@ -327,20 +336,22 @@ impl public_methods for borrowck_ctxt {
327336
// Other ptr types admit aliases and are therefore
328337
// not loanable.
329338
alt ptr {
330-
uniq_ptr {some(@lp_deref(l, ptr))}
331-
gc_ptr | region_ptr | unsafe_ptr {none}
339+
uniq_ptr => {some(@lp_deref(l, ptr))}
340+
gc_ptr | region_ptr | unsafe_ptr => {none}
332341
}
333342
};
343+
334344
@{id:node.id(), span:node.span(),
335345
cat:cat_deref(base_cmt, derefs, ptr), lp:lp,
336346
mutbl:mt.mutbl, ty:mt.ty}
337347
}
338348

339349
deref_comp(comp) {
340350
let lp = base_cmt.lp.map(|l| @lp_comp(l, comp) );
351+
let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl);
341352
@{id:node.id(), span:node.span(),
342353
cat:cat_comp(base_cmt, comp), lp:lp,
343-
mutbl:mt.mutbl, ty:mt.ty}
354+
mutbl:m, ty:mt.ty}
344355
}
345356
}
346357
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
enum foo = ~int;
2+
3+
fn borrow(x: @mut foo) {
4+
let y = &***x; //~ ERROR illegal borrow unless pure: unique value in aliasable, mutable location
5+
*x = foo(~4); //~ NOTE impure due to assigning to dereference of mutable @ pointer
6+
}
7+
8+
fn main() {
9+
}

0 commit comments

Comments
 (0)