Skip to content

Commit 627b6c1

Browse files
committed
---
yaml --- r: 15174 b: refs/heads/try c: ca6636d h: refs/heads/master v: v3
1 parent 7354e4a commit 627b6c1

File tree

8 files changed

+83
-34
lines changed

8 files changed

+83
-34
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: c141e7a068e3fbb1a5d24dcd000567b7731910bb
5+
refs/heads/try: ca6636d6b689fe209a210b0eda51e368f01cdb0f
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/rustc/middle/alias.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ fn pattern_roots(tcx: ty::ctxt, mutbl: option<unsafe_ty>, pat: @ast::pat)
647647
// return-by-reference
648648
fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool)
649649
-> {ex: @ast::expr, mutbl: option<unsafe_ty>} {
650-
let base_root = mutbl::expr_root(cx.tcx, ex, autoderef);
650+
let base_root = mutbl::expr_root_(cx.tcx, none, ex, autoderef);
651651
let mut unsafe_ty = none;
652652
for d in *base_root.ds {
653653
if d.mutbl { unsafe_ty = some(contains(d.outer_t)); break; }

branches/try/src/rustc/middle/mutbl.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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) ->
126142
type 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

131148
fn 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) == 0u {
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) != 0u &&
@@ -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 }

branches/try/src/rustc/middle/resolve.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,17 +523,23 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
523523
}
524524
ast::item_class(tps, members, ctor) {
525525
visit::visit_ty_params(tps, sc, v);
526+
// Can maybe skip this now that we require self on class fields
526527
let class_scope = cons(scope_item(i), @sc);
527528
/* visit the constructor... */
529+
let ctor_scope = cons(scope_method(ctor.node.self_id, tps),
530+
@class_scope);
528531
visit_fn_with_scope(e, visit::fk_item_fn(i.ident, tps), ctor.node.dec,
529532
ctor.node.body, ctor.span, ctor.node.id,
530-
class_scope, v);
533+
ctor_scope, v);
531534
/* visit the items */
532535
for cm in members {
533536
alt cm.node.decl {
534-
class_method(m) { visit_fn_with_scope(e,
535-
visit::fk_item_fn(m.ident, tps), m.decl, m.body,
536-
m.span, m.id, class_scope, v); }
537+
class_method(m) {
538+
let msc = cons(scope_method(m.self_id, tps + m.tps),
539+
@class_scope);
540+
visit_fn_with_scope(e,
541+
visit::fk_item_fn(m.ident, tps), m.decl, m.body,
542+
m.span, m.id, msc, v); }
537543
instance_var(_,t,_,_) { v.visit_ty(t, class_scope, v); }
538544
}
539545
}

branches/try/src/rustc/middle/typeck.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ type vtable_map = hashmap<ast::node_id, vtable_res>;
4949
type ty_table = hashmap<ast::def_id, ty::t>;
5050

5151
// Used for typechecking the methods of an impl
52-
enum self_info { self_impl(ty::t) }
52+
// first field is the self type, second is the ID for the "self" object
53+
// that's currently in scope
54+
enum self_info { self_impl(ty::t, ast::node_id) }
5355

5456
type crate_ctxt = {mut self_infos: [self_info],
5557
impl_map: resolve::impl_map,
@@ -117,7 +119,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
117119
}
118120
ast::def_self(_) {
119121
alt get_self_info(fcx.ccx) {
120-
some(self_impl(impl_t)) {
122+
some(self_impl(impl_t,_)) {
121123
ret {bounds: @[], ty: impl_t};
122124
}
123125
none {
@@ -3128,20 +3130,28 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
31283130
// field
31293131
#debug("class named %s", ty_to_str(tcx, base_t));
31303132
/*
3131-
This is an external reference, so only consider public
3132-
fields
3133+
check whether this is a self-reference or not, which
3134+
determines whether we look at all fields or only public
3135+
ones
31333136
*/
3134-
let cls_items = lookup_public_fields(tcx, base_id);
3135-
#debug("cls_items: %?", cls_items);
3136-
alt lookup_field_ty(tcx, base_id, cls_items, field) {
3137+
let node_def = lookup_def(fcx, base.span, base.id);
3138+
let cls_items = alt get_self_info(fcx.ccx) {
3139+
some(self_impl(_, n_id)) if alt node_def {
3140+
ast::def_self(base_id) { base_id == n_id }
3141+
_ { false }} {
3142+
// base expr is "self" -- consider all fields
3143+
ty::lookup_class_fields(tcx, base_id)
3144+
}
3145+
_ { lookup_public_fields(tcx, base_id) }
3146+
};
3147+
alt lookup_field_ty(tcx, base_id, cls_items, field) {
31373148
some(field_ty) {
3138-
#debug("a");
31393149
// (2) look up what field's type is, and return it
31403150
// FIXME: actually instantiate any type params
31413151
write_ty(tcx, id, field_ty);
31423152
handled = true;
31433153
}
3144-
none { #debug("b"); }
3154+
none {}
31453155
}
31463156
}
31473157
_ {}
@@ -3659,11 +3669,16 @@ fn class_types(ccx: @crate_ctxt, members: [@ast::class_item]) -> class_map {
36593669
rslt
36603670
}
36613671

3662-
fn check_class_member(ccx: @crate_ctxt, cm: ast::class_member) {
3672+
fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
3673+
cm: ast::class_member) {
36633674
alt cm {
36643675
ast::instance_var(_,t,_,_) {
36653676
}
3666-
ast::class_method(m) { check_method(ccx, m); }
3677+
ast::class_method(m) {
3678+
ccx.self_infos += [self_impl(class_t, m.self_id)];
3679+
check_method(ccx, m);
3680+
vec::pop(ccx.self_infos);
3681+
}
36673682
}
36683683
}
36693684

@@ -3681,20 +3696,28 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
36813696
let mut self_ty = ast_ty_to_ty(ccx.tcx, m_check, ty);
36823697
let self_region = ty::re_self;
36833698
self_ty = instantiate_self_regions(ccx.tcx, self_region, self_ty);
3684-
ccx.self_infos += [self_impl(self_ty)];
3685-
for m in ms { check_method(ccx, m); }
3686-
vec::pop(ccx.self_infos);
3699+
for m in ms {
3700+
ccx.self_infos += [self_impl(self_ty, m.id)];
3701+
check_method(ccx, m);
3702+
vec::pop(ccx.self_infos);
3703+
}
36873704
}
36883705
ast::item_class(tps, members, ctor) {
36893706
let cid = some(it.id);
3707+
let class_t = node_id_to_type(ccx.tcx, it.id);
36903708
let members_info = class_types(ccx, members);
3709+
// can also ditch the enclosing_class stuff once we move to self
3710+
// FIXME
36913711
let class_ccx = @{enclosing_class_id:cid,
36923712
enclosing_class:members_info with *ccx};
3713+
class_ccx.self_infos += [self_impl(class_t, ctor.node.self_id)];
36933714
// typecheck the ctor
36943715
check_fn(class_ccx, ast::proto_bare, ctor.node.dec,
36953716
ctor.node.body, ctor.node.id, false, none);
3717+
vec::pop(class_ccx.self_infos);
36963718
// typecheck the members
3697-
for m in members { check_class_member(class_ccx, m.node.decl); }
3719+
for m in members { check_class_member(class_ccx, class_t,
3720+
m.node.decl); }
36983721
}
36993722
_ {/* nothing to do */ }
37003723
}

branches/try/src/rustc/syntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ type class_ctor = spanned<class_ctor_>;
684684

685685
#[auto_serialize]
686686
type class_ctor_ = {id: node_id,
687+
self_id: node_id,
687688
dec: fn_decl,
688689
body: blk};
689690

branches/try/src/rustc/syntax/parse/parser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2092,10 +2092,12 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
20922092
}
20932093
p.bump();
20942094
alt the_ctor {
2095-
some((ct_d, ct_b, ct_s)) { ret mk_item(p, lo, p.last_span.hi,
2095+
some((ct_d, ct_b, ct_s)) {
2096+
ret mk_item(p, lo, p.last_span.hi,
20962097
class_name,
20972098
ast::item_class(ty_params, items,
20982099
{node: {id: ctor_id,
2100+
self_id: p.get_id(),
20992101
dec: ct_d,
21002102
body: ct_b},
21012103
span: ct_s}), attrs); }

branches/try/src/test/run-pass/classes-simple.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class cat {
55

66
let how_hungry : int;
77

8-
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
8+
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
99
}
1010

1111
fn main() {

0 commit comments

Comments
 (0)