@@ -57,6 +57,16 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
5757 }
5858 }
5959 }
60+ ty:: ty_class ( did, _) {
61+ util:: common:: log_expr ( * ex) ;
62+ for fld: ty:: field_ty in ty:: lookup_class_fields ( tcx, did) {
63+ #debug ( "%s %?" , fld. ident , fld. mutability ) ;
64+ if str:: eq ( ident, fld. ident ) {
65+ is_mutbl = fld. mutability == class_mutable;
66+ }
67+ break ;
68+ }
69+ }
6070 _ { }
6171 }
6272 ds += [ @{ mutbl: is_mutbl, kind: field, outer_t: auto_unbox. t } ] ;
@@ -114,14 +124,17 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
114124// Actual mutbl-checking pass
115125
116126type mutbl_map = std:: map:: hashmap < node_id , ( ) > ;
117- type ctx = { tcx : ty:: ctxt , mutbl_map : mutbl_map } ;
127+ // Keep track of whether we're inside a ctor, so as to
128+ // allow mutating immutable fields in the same class
129+ type ctx = { tcx : ty:: ctxt , mutbl_map : mutbl_map , in_ctor : bool } ;
118130
119131fn check_crate ( tcx : ty:: ctxt , crate : @crate ) -> mutbl_map {
120- let cx = @{ tcx: tcx, mutbl_map: std:: map:: int_hash ( ) } ;
121- let v = @{ visit_expr: bind visit_expr ( cx, _, _, _) ,
122- visit_decl: bind visit_decl ( cx, _, _, _)
132+ let cx = @{ tcx: tcx, mutbl_map: std:: map:: int_hash ( ) , in_ctor: false } ;
133+ let v = @{ visit_expr: visit_expr,
134+ visit_decl: visit_decl,
135+ visit_item: visit_item
123136 with * visit:: default_visitor ( ) } ;
124- visit:: visit_crate ( * crate , ( ) , visit:: mk_vt ( v) ) ;
137+ visit:: visit_crate ( * crate , cx , visit:: mk_vt ( v) ) ;
125138 ret cx. mutbl_map ;
126139}
127140
@@ -135,8 +148,8 @@ fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
135148 } ) ;
136149}
137150
138- fn visit_decl ( cx : @ ctx , d : @decl , & & e : ( ) , v : visit:: vt < ( ) > ) {
139- visit:: visit_decl ( d, e , v) ;
151+ fn visit_decl ( d : @decl , & & cx : @ ctx , v : visit:: vt < @ ctx > ) {
152+ visit:: visit_decl ( d, cx , v) ;
140153 alt d. node {
141154 decl_local ( locs) {
142155 for loc in locs {
@@ -152,7 +165,7 @@ fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
152165 }
153166}
154167
155- fn visit_expr ( cx : @ ctx , ex: @expr, & & e : ( ) , v : visit:: vt < ( ) > ) {
168+ fn visit_expr ( ex : @expr, &&cx : @ ctx , v : visit:: vt < @ ctx > ) {
156169 alt ex. node {
157170 expr_call ( f, args, _) { check_call ( cx, f, args) ; }
158171 expr_bind ( f, args) { check_bind ( cx, f, args) ; }
@@ -179,7 +192,22 @@ fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
179192 }
180193 _ { }
181194 }
182- visit:: visit_expr ( ex, e, v) ;
195+ visit:: visit_expr ( ex, cx, v) ;
196+ }
197+
198+ fn visit_item ( item : @item, &&cx : @ctx , v : visit:: vt < @ctx > ) {
199+ alt item. node {
200+ item_class ( tps, items, ctor) {
201+ v. visit_ty_params ( tps, cx, v) ;
202+ vec:: map :: < @class_item , ( ) > ( items,
203+ { |i| v. visit_class_item ( i. span ,
204+ i. node . privacy , i. node . decl , cx, v) ; } ) ;
205+ v. visit_fn ( visit:: fk_ctor ( item. ident , tps) , ctor. node . dec ,
206+ ctor. node . body , ctor. span , ctor. node . id ,
207+ @{ in_ctor: true with * cx} , v) ;
208+ }
209+ _ { visit : : visit_item ( item, cx, v) ; }
210+ }
183211}
184212
185213fn check_lval ( cx : @ctx , dest: @expr, msg : msg ) {
@@ -277,7 +305,7 @@ fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
277305fn is_illegal_to_modify_def ( cx: @ctx, def: def, msg: msg) -> option<str> {
278306 alt def {
279307 def_fn( _, _) | def_mod ( _) | def_native_mod ( _) | def_const ( _) |
280- def_use ( _) {
308+ def_use ( _) | def_class_method ( _ , _ ) {
281309 some ( "static item" )
282310 }
283311 def_arg ( _, m) {
@@ -310,6 +338,18 @@ fn is_illegal_to_modify_def(cx: @ctx, def: def, msg: msg) -> option<str> {
310338 }
311339
312340 def_binding ( _) { some ( "binding" ) }
341+ def_class_field ( parent, fld) {
342+ if !cx. in_ctor {
343+ /* Enforce mutability *unless* we're inside a ctor */
344+ alt ty:: lookup_class_field ( cx. tcx , parent, fld) . mutability {
345+ class_mutable { none }
346+ class_immutable { some( "immutable class field" ) }
347+ }
348+ }
349+ else {
350+ none
351+ }
352+ }
313353 _ { none }
314354 }
315355}
0 commit comments