Require "self" as base expression for intra-class method or field references

All field or method references within a class must begin with "self." now.
A bare reference to a field or method in the same class will no longer
typecheck.
This commit is contained in:
Tim Chevalier 2012-03-29 12:21:13 -07:00
parent c2f28e231f
commit c7082ce8e8
24 changed files with 49 additions and 162 deletions

View file

@ -443,12 +443,6 @@ impl of tr for ast::def {
ast::def_class(did) {
ast::def_class(did.tr(xcx))
}
ast::def_class_field(did0, did1) {
ast::def_class_field(did0.tr(xcx), did1.tr(xcx))
}
ast::def_class_method(did0, did1) {
ast::def_class_method(did0.tr(xcx), did1.tr(xcx))
}
ast::def_region(nid) { ast::def_region(xcx.tr_id(nid)) }
}
}

View file

@ -321,7 +321,7 @@ fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
fn is_illegal_to_modify_def(cx: @ctx, def: def, msg: msg) -> option<str> {
alt def {
def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
def_use(_) | def_class_method(_,_) {
def_use(_) {
some("static item")
}
def_arg(_, m) {
@ -354,18 +354,6 @@ fn is_illegal_to_modify_def(cx: @ctx, def: def, msg: msg) -> option<str> {
}
def_binding(_) { some("binding") }
def_class_field(parent,fld) {
if option::is_none(cx.in_ctor) {
/* Enforce mutability *unless* we're inside a ctor */
alt ty::lookup_class_field(cx.tcx, parent, fld).mutability {
class_mutable { none }
class_immutable { some("immutable class field") }
}
}
else {
none
}
}
_ { none }
}
}

View file

@ -88,8 +88,6 @@ enum mod_index_entry {
mie_view_item(ident, node_id, span),
mie_import_ident(node_id, span),
mie_item(@ast::item),
mie_class_item(node_id, /* parent class name */
@ast::class_member), /* class member */
mie_native_item(@ast::native_item),
mie_enum_variant(/* variant index */uint,
/*parts of enum item*/ [variant],
@ -1017,9 +1015,6 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
ret some(ast::def_fn(local_def(ctor.node.id),
ast::impure_fn));
}
if ns == ns_val {
ret lookup_in_class(local_def(it.id), members, name);
}
// FIXME: AST allows other items to appear in a class,
// but that might not be wise
}
@ -1156,30 +1151,6 @@ fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
}
}
/*
FIXME: not sure about this code. maybe this should be handled
using the mod_index stuff
*/
fn lookup_in_class(parent_id: def_id,
members: [@class_member], name: ident)
-> option<def> {
for m in members {
alt m.node {
instance_var(v_name,_,_,id,_) {
if v_name == name {
ret some(def_class_field(parent_id, local_def(id)));
}
}
class_method(i) {
if i.ident == name {
ret some(def_class_method(parent_id, local_def(i.id)));
}
}
}
}
ret none;
}
fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
loc_pos: uint, ns: namespace) -> option<def> {
@ -1559,18 +1530,6 @@ fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
}
}
}
mie_class_item(parent_id, class_item) {
alt class_item.node {
instance_var(_,_,_,id,_) {
ret some(ast::def_class_field(local_def(parent_id),
local_def(id)));
}
class_method(it) {
ret some(ast::def_class_method(local_def(parent_id),
local_def(it.id)));
}
}
}
}
ret none;
}
@ -1648,11 +1607,6 @@ fn index_mod(md: ast::_mod) -> mod_index {
node:
item_fn(ctor.node.dec, tps, ctor.node.body),
span: ctor.node.body.span}));
// add the members
for ci in items {
add_to_index(index, class_item_ident(ci),
mie_class_item(it.id, ci));
}
}
}
}
@ -1678,8 +1632,7 @@ fn ns_for_def(d: def) -> namespace {
ast::def_variant(_, _) { ns_val }
ast::def_fn(_, _) | ast::def_self(_) |
ast::def_const(_) | ast::def_arg(_, _) | ast::def_local(_, _) |
ast::def_upvar(_, _, _) | ast::def_self(_) |
ast::def_class_field(_,_) | ast::def_class_method(_,_) { ns_val }
ast::def_upvar(_, _, _) | ast::def_self(_) { ns_val }
ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
ast::def_ty_param(_, _) | ast::def_prim_ty(_) | ast::def_class(_)
@ -1761,7 +1714,6 @@ fn mie_span(mie: mod_index_entry) -> span {
mie_item(item) { item.span }
mie_enum_variant(_, _, _, span) { span }
mie_native_item(item) { item.span }
mie_class_item(_,item) { item.span }
};
}

View file

@ -2177,22 +2177,18 @@ fn trans_local_var(cx: block, def: ast::def) -> local_var_result {
}
}
// The third argument (path) ends up getting used when the id
// refers to a field within the enclosing class, since the name
// gets turned into a record field name.
fn trans_path(cx: block, id: ast::node_id, path: @ast::path)
fn trans_path(cx: block, id: ast::node_id)
-> lval_maybe_callee {
let _icx = cx.insn_ctxt("trans_path");
alt cx.tcx().def_map.find(id) {
none { cx.sess().bug("trans_path: unbound node ID"); }
some(df) {
ret trans_var(cx, df, id, path);
ret trans_var(cx, df, id);
}
}
}
fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
-> lval_maybe_callee {
fn trans_var(cx: block, def: ast::def, id: ast::node_id)-> lval_maybe_callee {
let _icx = cx.insn_ctxt("trans_var");
let ccx = cx.ccx();
alt def {
@ -2225,28 +2221,6 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
}
}
ast::def_class_field(parent, did) {
// base is implicitly "Self"
alt cx.fcx.llself {
some(slf) {
let base = cast_self(cx, slf);
let {bcx, val, kind} = trans_rec_field_inner(cx, base,
slf.t,
path_to_ident(path), path.span);
ret lval_no_env(bcx, val, kind);
}
_ { cx.sess().bug("unbound self param in class"); }
}
}
ast::def_class_method(parent, did) {
alt cx.fcx.llself {
some(slf) {
ret {env: self_env(slf.v, slf.t, none)
with lval_static_fn(cx, did, id)};
}
none { cx.sess().bug("unbound self param in class"); }
}
}
_ {
let loc = trans_local_var(cx, def);
ret lval_no_env(cx, loc.val, loc.kind);
@ -2323,7 +2297,7 @@ fn expr_is_lval(bcx: block, e: @ast::expr) -> bool {
fn trans_callee(bcx: block, e: @ast::expr) -> lval_maybe_callee {
let _icx = bcx.insn_ctxt("trans_callee");
alt e.node {
ast::expr_path(path) { ret trans_path(bcx, e.id, path); }
ast::expr_path(path) { ret trans_path(bcx, e.id); }
ast::expr_field(base, ident, _) {
// Lval means this is a record field, so not a method
if !expr_is_lval(bcx, e) {
@ -2350,8 +2324,8 @@ fn trans_callee(bcx: block, e: @ast::expr) -> lval_maybe_callee {
fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
let _icx = cx.insn_ctxt("trans_lval");
alt e.node {
ast::expr_path(p) {
let v = trans_path(cx, e.id, p);
ast::expr_path(_) {
let v = trans_path(cx, e.id);
ret lval_maybe_callee_to_lval(v, expr_ty(cx, e));
}
ast::expr_field(base, ident, _) {

View file

@ -170,20 +170,6 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ast::def_upvar(_, inner, _) {
ret ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
}
ast::def_class_method(_, id) | ast::def_class_field(_, id) {
if id.crate != ast::local_crate {
fcx.ccx.tcx.sess.span_fatal(sp,
"class method or field referred to \
out of scope");
}
alt fcx.ccx.enclosing_class.find(id.node) {
some(a_ty) { ret {bounds: @[], ty: a_ty}; }
_ { fcx.ccx.tcx.sess.span_fatal(sp,
"class method or field referred to \
out of scope"); }
}
}
_ {
// FIXME: handle other names.
fcx.ccx.tcx.sess.unimpl("definition variant");

View file

@ -83,11 +83,6 @@ enum def {
@def /* closed over def */,
node_id /* expr node that creates the closure */),
def_class(def_id),
// first def_id is for parent class
def_class_field(def_id, def_id),
// No purity allowed for now, I guess
// (simpler this way, b/c presumably methods read mut state)
def_class_method(def_id, def_id),
def_region(node_id)
}

View file

@ -40,9 +40,7 @@ fn def_id_of_def(d: def) -> def_id {
def_fn(id, _) | def_mod(id) |
def_native_mod(id) | def_const(id) |
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
def_use(id) |
def_class(id) | def_class_field(_, id) | def_class_method(_, id) { id }
def_use(id) | def_class(id) { id }
def_arg(id, _) | def_local(id, _) | def_self(id) |
def_upvar(id, _, _) | def_binding(id) | def_region(id) {
local_def(id)

View file

@ -7,7 +7,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
}

View file

@ -7,7 +7,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
fn speak() {}
}

View file

@ -7,10 +7,10 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
fn speak() { meows += 1u; }
fn meow_count() -> uint { meows }
fn speak() { self.meows += 1u; }
fn meow_count() -> uint { self.meows }
}

View file

@ -5,9 +5,9 @@ class cat {
let mut meows : uint;
fn meow() {
#error("Meow");
meows += 1u;
if meows % 5u == 0u {
how_hungry += 1;
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
}
}
}
@ -16,14 +16,14 @@ class cat {
let name : str;
new(in_x : uint, in_y : int, in_name: str)
{ meows = in_x; how_hungry = in_y; name = in_name; }
{ self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }
fn speak() { meow(); }
fn speak() { self.meow(); }
fn eat() -> bool {
if how_hungry > 0 {
if self.how_hungry > 0 {
#error("OM NOM NOM");
how_hungry -= 2;
self.how_hungry -= 2;
ret true;
}
else {

View file

@ -8,7 +8,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
}

View file

@ -6,8 +6,8 @@ class cat {
let how_hungry : int;
fn speak() { meows += 1u; }
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
fn speak() { self.meows += 1u; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {

View file

@ -7,13 +7,13 @@ class cat {
let how_hungry : int;
fn eat() {
how_hungry -= 5;
self.how_hungry -= 5;
}
new(in_x : uint, in_y : int) {
let foo;
meows = in_x + (in_y as uint);
how_hungry = foo;
self.meows = in_x + (in_y as uint);
self.how_hungry = foo;
}
}

View file

@ -1,4 +1,4 @@
// error-pattern:assigning to immutable class field
// error-pattern:assigning to immutable field
class cat {
priv {
let mutable meows : uint;
@ -7,10 +7,10 @@ class cat {
let how_hungry : int;
fn eat() {
how_hungry -= 5;
self.how_hungry -= 5;
}
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {

View file

@ -6,7 +6,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {

View file

@ -6,7 +6,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {

View file

@ -7,7 +7,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {

View file

@ -5,10 +5,10 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
fn speak() { meows += 1u; }
fn meow_count() -> uint { meows }
fn speak() { self.meows += 1u; }
fn meow_count() -> uint { self.meows }
}
fn main() {

View file

@ -3,7 +3,7 @@ class cat {
let name : str;
new(in_name: str)
{ name = in_name; }
{ self.name = in_name; }
}
fn main() {

View file

@ -5,7 +5,7 @@ class cat {
let how_hungry : int;
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
fn speak() {}
}

View file

@ -3,9 +3,9 @@ class cat {
let mut meows : uint;
fn meow() {
#error("Meow");
meows += 1u;
if meows % 5u == 0u {
how_hungry += 1;
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
}
}
}
@ -14,14 +14,14 @@ class cat {
let name : str;
new(in_x : uint, in_y : int, in_name: str)
{ meows = in_x; how_hungry = in_y; name = in_name; }
{ self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }
fn speak() { meow(); }
fn speak() { self.meow(); }
fn eat() -> bool {
if how_hungry > 0 {
if self.how_hungry > 0 {
#error("OM NOM NOM");
how_hungry -= 2;
self.how_hungry -= 2;
ret true;
}
else {

View file

@ -5,8 +5,8 @@ class cat {
let how_hungry : int;
fn meow_count() -> uint { meows }
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
fn meow_count() -> uint { self.meows }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {

View file

@ -7,10 +7,10 @@ class cat {
let how_hungry : int;
fn play() {
meows += 1u;
self.meows += 1u;
self.nap();
}
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
}
fn main() {