@@ -12,7 +12,13 @@ type deref = @{mutbl: bool, kind: deref_t, outer_t: ty::t};
1212// vec of dereferences that were used on this root. Note that, in this vec,
1313// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
1414// ds=[index,field])
15- fn expr_root ( tcx : ty:: ctxt , ex: @expr, autoderef : bool ) ->
15+ fn expr_root ( cx : @ctx , ex: @expr, autoderef : bool )
16+ -> { ex : @expr, ds : @[ deref ] } {
17+ expr_root_ ( cx. tcx , cx. in_ctor , ex, autoderef)
18+ }
19+
20+ fn expr_root_ ( tcx : ty:: ctxt , ctor_self : option < node_id > ,
21+ ex: @expr, autoderef : bool ) ->
1622 { ex : @expr, ds : @[ deref ] } {
1723 fn maybe_auto_unbox ( tcx : ty:: ctxt , t : ty:: t ) -> { t : ty:: t , ds : [ deref ] } {
1824 let mut ds = [ ] , t = t;
@@ -58,13 +64,23 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
5864 }
5965 }
6066 ty:: ty_class ( did, _) {
61- util:: common:: log_expr ( * ex) ;
67+ util:: common:: log_expr ( * base) ;
68+ let in_self = alt ctor_self {
69+ some( selfid) {
70+ alt tcx. def_map . find ( base. id ) {
71+ some ( def_self ( slfid) ) { slfid == selfid }
72+ _ { false }
73+ }
74+ }
75+ none { false }
76+ } ;
6277 for fld: ty:: field_ty in ty:: lookup_class_fields ( tcx, did) {
63- #debug ( "%s %?" , fld. ident , fld. mutability ) ;
6478 if str:: eq ( ident, fld. ident ) {
65- is_mutbl = fld. mutability == class_mutable;
79+ is_mutbl = fld. mutability == class_mutable
80+ || in_self; // all fields can be mutated
81+ // in the ctor
82+ break ;
6683 }
67- break ;
6884 }
6985 }
7086 _ { }
@@ -126,10 +142,11 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
126142type mutbl_map = std:: map:: hashmap < node_id , ( ) > ;
127143// Keep track of whether we're inside a ctor, so as to
128144// allow mutating immutable fields in the same class
129- type ctx = { tcx : ty:: ctxt , mutbl_map : mutbl_map , in_ctor : bool } ;
145+ // if we are in a ctor, we track the self id
146+ type ctx = { tcx : ty:: ctxt , mutbl_map : mutbl_map , in_ctor : option < node_id > } ;
130147
131148fn check_crate ( tcx : ty:: ctxt , crate : @crate ) -> mutbl_map {
132- let cx = @{ tcx: tcx, mutbl_map: std:: map:: int_hash ( ) , in_ctor: false } ;
149+ let cx = @{ tcx: tcx, mutbl_map: std:: map:: int_hash ( ) , in_ctor: none } ;
133150 let v = @{ visit_expr: visit_expr,
134151 visit_decl: visit_decl,
135152 visit_item: visit_item
@@ -204,7 +221,7 @@ fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) {
204221 i. node . privacy , i. node . decl , cx, v) ; } ) ;
205222 v. visit_fn ( visit:: fk_ctor ( item. ident , tps) , ctor. node . dec ,
206223 ctor. node . body , ctor. span , ctor. node . id ,
207- @{ in_ctor: true with * cx} , v) ;
224+ @{ in_ctor : some ( ctor . node . self_id ) with * cx} , v) ;
208225 }
209226 _ { visit : : visit_item ( item, cx, v) ; }
210227 }
@@ -221,7 +238,7 @@ fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
221238 cx. mutbl_map . insert ( ast_util:: def_id_of_def ( def) . node , ( ) ) ;
222239 }
223240 _ {
224- let root = expr_root ( cx. tcx , dest, false ) ;
241+ let root = expr_root ( cx, dest, false ) ;
225242 if vec:: len ( * root. ds ) == 0 u {
226243 if msg != msg_move_out {
227244 mk_err ( cx, dest. span , msg, "non-lvalue" ) ;
@@ -251,7 +268,7 @@ fn check_move_rhs(cx: @ctx, src: @expr) {
251268 check_lval( cx, src, msg_move_out) ;
252269 }
253270 _ {
254- let root = expr_root( cx. tcx , src, false ) ;
271+ let root = expr_root( cx, src, false ) ;
255272
256273 // Not a path and no-derefs means this is a temporary.
257274 if vec:: len ( * root. ds ) != 0 u &&
@@ -339,7 +356,7 @@ fn is_illegal_to_modify_def(cx: @ctx, def: def, msg: msg) -> option<str> {
339356
340357 def_binding ( _) { some ( "binding" ) }
341358 def_class_field ( parent, fld) {
342- if ! cx. in_ctor {
359+ if option :: is_none ( cx. in_ctor ) {
343360 /* Enforce mutability *unless* we're inside a ctor */
344361 alt ty:: lookup_class_field ( cx. tcx , parent, fld) . mutability {
345362 class_mutable { none }
0 commit comments