Skip to content

Commit 89cd2f6

Browse files
committed
Enforce that self doesn't escape from a class
Closes #2294
1 parent 11e9947 commit 89cd2f6

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

src/rustc/driver/driver.rs

+2
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
186186
bind middle::check_loop::check_crate(ty_cx, crate));
187187
time(time_passes, "alt checking",
188188
bind middle::check_alt::check_crate(ty_cx, crate));
189+
time(time_passes, "self checking",
190+
bind middle::check_self::check_crate(ty_cx, crate));
189191
time(time_passes, "typestate checking",
190192
bind middle::tstate::ck::check_crate(ty_cx, crate));
191193
let (_root_map, mutbl_map) = time(

src/rustc/middle/check_self.rs

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
This module checks that within a class, "self" doesn't escape.
3+
That is, it rejects any class in which "self" occurs other than
4+
as the left-hand side of a field reference.
5+
*/
6+
import syntax::ast::*;
7+
import syntax::visit::*;
8+
import driver::session::session;
9+
import std::map::hashmap;
10+
import resolve::def_map;
11+
12+
fn check_crate(cx: ty::ctxt, crate: @crate) {
13+
visit_crate(*crate, cx, mk_vt(@{
14+
visit_item: bind check_item(_, _, _)
15+
with *default_visitor()
16+
}));
17+
cx.sess.abort_if_errors();
18+
}
19+
20+
fn check_item(it: @item, &&cx: ty::ctxt, &&_v: vt<ty::ctxt>) {
21+
alt it.node {
22+
item_class(*) {
23+
visit_item(it, cx, check_self_visitor());
24+
}
25+
_ {}
26+
}
27+
}
28+
29+
fn check_self_visitor() -> vt<ty::ctxt> {
30+
mk_vt(@{
31+
visit_expr: bind check_self_expr(_, _, _)
32+
with *default_visitor()
33+
})
34+
}
35+
36+
fn check_self_expr(e: @expr, &&cx: ty::ctxt, &&v: vt<ty::ctxt>) {
37+
alt e.node {
38+
expr_field(@{node: expr_path(p),_},_,_) {
39+
// self is ok here; don't descend
40+
}
41+
expr_path(_) {
42+
alt cx.def_map.find(e.id) {
43+
some(def_self(_)) {
44+
cx.sess.span_err(e.span, "can't return self or store \
45+
it in a data structure");
46+
}
47+
_ {}
48+
}
49+
}
50+
_ { visit_expr(e, cx, v); }
51+
}
52+
}
53+
54+
// Local Variables:
55+
// mode: rust
56+
// fill-column: 78;
57+
// indent-tabs-mode: nil
58+
// c-basic-offset: 4
59+
// buffer-file-coding-system: utf-8-unix
60+
// End:

src/rustc/rustc.rc

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ mod middle {
5555
mod check_loop;
5656
mod check_alt;
5757
mod check_const;
58+
mod check_self;
5859
mod lint;
5960
mod borrowck;
6061
mod alias;

src/test/compile-fail/issue-2294.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class cat {
2+
fn kitty() -> cat { self } //! ERROR: can't return self or store it in a data structure
3+
new() { }
4+
}
5+
6+
fn main() {}

0 commit comments

Comments
 (0)