Skip to content

Commit bc21a5d

Browse files
committed
rustc: Create self region bindings, and forbid the self region from being used in places it shouldn't be
1 parent 041c9a0 commit bc21a5d

File tree

6 files changed

+57
-16
lines changed

6 files changed

+57
-16
lines changed

src/rustc/metadata/tyencode.rs

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ fn enc_region(w: io::writer, cx: @ctxt, r: ty::region) {
103103
ty::re_block(nid) {
104104
w.write_char('b'); w.write_int(nid); w.write_char('|');
105105
}
106+
ty::re_self(did) {
107+
w.write_char('s'); w.write_str(cx.ds(did)); w.write_char('|');
108+
}
106109
ty::re_inferred { w.write_char('?'); }
107110
}
108111
}

src/rustc/middle/region.rs

+38-8
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,19 @@ type ctxt = {
6565
parent: parent,
6666

6767
/* True if we're within the pattern part of an alt, false otherwise. */
68-
in_alt: bool
68+
in_alt: bool,
69+
70+
/*
71+
* Points to the site of the current typeclass implementation, or none if
72+
* we're outside one.
73+
*/
74+
self_binding: option<ast::def_id>
6975
};
7076

7177
fn region_to_scope(region_map: @region_map, region: ty::region)
7278
-> ast::node_id {
7379
ret alt region {
74-
ty::re_caller(def_id) { def_id.node }
80+
ty::re_caller(def_id) | ty::re_self(def_id) { def_id.node }
7581
ty::re_named(def_id) { region_map.region_name_to_fn.get(def_id) }
7682
ty::re_block(node_id) { node_id }
7783
ty::re_inferred { fail "unresolved region in region_to_scope" }
@@ -115,7 +121,21 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
115121
alt ty.node {
116122
ast::ty_rptr({id: region_id, node: node}, _) {
117123
alt node {
118-
ast::re_inferred | ast::re_self { /* no-op */ }
124+
ast::re_inferred { /* no-op */ }
125+
ast::re_self {
126+
alt cx.self_binding {
127+
some(def_id) {
128+
let region = ty::re_self(def_id);
129+
let rm = cx.region_map;
130+
rm.ast_type_to_region.insert(region_id, region);
131+
}
132+
none {
133+
cx.sess.span_err(ty.span,
134+
"the `self` region is not \
135+
allowed here");
136+
}
137+
}
138+
}
119139
ast::re_named(ident) {
120140
// If at item scope, introduce or reuse a binding. If at
121141
// block scope, require that the binding be introduced.
@@ -281,13 +301,22 @@ fn resolve_local(local: @ast::local, cx: ctxt, visitor: visit::vt<ctxt>) {
281301

282302
fn resolve_item(item: @ast::item, cx: ctxt, visitor: visit::vt<ctxt>) {
283303
// Items create a new outer block scope as far as we're concerned.
284-
let parent = alt item.node {
285-
ast::item_fn(_, _, _) | ast::item_enum(_, _) { pa_fn_item(item.id) }
286-
_ { pa_item(item.id) }
304+
let parent;
305+
let mut self_binding = cx.self_binding;
306+
alt item.node {
307+
ast::item_fn(_, _, _) | ast::item_enum(_, _) {
308+
parent = pa_fn_item(item.id);
309+
}
310+
ast::item_impl(_, _, _, _) {
311+
self_binding = some({crate: ast::local_crate, node: item.id});
312+
parent = pa_item(item.id);
313+
}
314+
_ { parent = pa_item(item.id); }
287315
};
288316
let new_cx: ctxt = {bindings: @list::nil,
289317
parent: parent,
290-
in_alt: false
318+
in_alt: false,
319+
self_binding: self_binding
291320
with cx};
292321
visit::visit_item(item, new_cx, visitor);
293322
}
@@ -307,7 +336,8 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
307336
mut bindings: @list::nil,
308337
mut queued_locals: [],
309338
parent: pa_crate,
310-
in_alt: false};
339+
in_alt: false,
340+
self_binding: none};
311341
let visitor = visit::mk_vt(@{
312342
visit_block: resolve_block,
313343
visit_item: resolve_item,

src/rustc/middle/regionck.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
2828
alt ty::get(t).struct {
2929
ty::ty_rptr(region, _) {
3030
alt region {
31-
ty::re_named(_) | ty::re_caller(_) { /* ok */ }
31+
ty::re_named(_) | ty::re_caller(_) | ty::re_self(_) {
32+
/* ok */
33+
}
3234
ty::re_block(rbi) {
3335
let referent_block_id = rbi;
3436
let enclosing_block_id = alt cx.enclosing_block {

src/rustc/middle/ty.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ type fn_ty = {proto: ast::proto,
233233
enum region {
234234
re_named(def_id),
235235
re_caller(def_id),
236+
re_self(def_id),
236237
re_block(node_id),
237238
re_inferred /* currently unresolved (for typedefs) */
238239
}
@@ -1152,8 +1153,9 @@ fn hash_type_structure(st: sty) -> uint {
11521153
alt r {
11531154
re_named(_) { 1u }
11541155
re_caller(_) { 2u }
1155-
re_block(_) { 3u }
1156-
re_inferred { 4u }
1156+
re_self(_) { 3u }
1157+
re_block(_) { 4u }
1158+
re_inferred { 5u }
11571159
}
11581160
}
11591161
alt st {

src/rustc/middle/typeck.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,11 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
254254
fn subst_inferred_regions(tcx: ty::ctxt, use_site: ast::node_id,
255255
ty: ty::t) -> ty::t {
256256
ret ty::fold_ty(tcx, ty::fm_rptr({|r|
257-
if r == ty::re_inferred {
258-
tcx.region_map.ast_type_to_inferred_region.get(use_site)
259-
} else {
260-
r
257+
alt r {
258+
ty::re_inferred | ty::re_self(_) {
259+
tcx.region_map.ast_type_to_inferred_region.get(use_site)
260+
}
261+
_ { r }
261262
}
262263
}), ty);
263264
}
@@ -1462,7 +1463,9 @@ fn instantiate_self_regions(pcx: pat_ctxt, args: [ty::t]) -> [ty::t] {
14621463
if ty::type_has_rptrs(arg_ty) {
14631464
ty::fold_ty(pcx.fcx.ccx.tcx, ty::fm_rptr({|r|
14641465
alt r {
1465-
ty::re_inferred | ty::re_caller(_) { pcx.pat_region }
1466+
ty::re_inferred | ty::re_caller(_) | ty::re_self(_) {
1467+
pcx.pat_region
1468+
}
14661469
_ { r }
14671470
}
14681471
}), arg_ty)

src/rustc/util/ppaux.rs

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
7373
re_named(_) { "<name>." } // TODO: include name
7474
re_caller(_) { "<caller>." }
7575
re_block(_) { "<block>." } // TODO: include line number
76+
re_self(_) { "self." }
7677
re_inferred { "" }
7778
}
7879
}

0 commit comments

Comments
 (0)