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:
parent
c2f28e231f
commit
c7082ce8e8
24 changed files with 49 additions and 162 deletions
|
|
@ -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)) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, _) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ class cat {
|
|||
let name : str;
|
||||
|
||||
new(in_name: str)
|
||||
{ name = in_name; }
|
||||
{ self.name = in_name; }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue