rustc: Create self region bindings, and forbid the self region from being used in places it shouldn't be

This commit is contained in:
Patrick Walton 2012-03-15 16:36:58 -07:00
parent 041c9a0863
commit bc21a5ddbe
6 changed files with 57 additions and 16 deletions

View File

@ -103,6 +103,9 @@ fn enc_region(w: io::writer, cx: @ctxt, r: ty::region) {
ty::re_block(nid) {
w.write_char('b'); w.write_int(nid); w.write_char('|');
}
ty::re_self(did) {
w.write_char('s'); w.write_str(cx.ds(did)); w.write_char('|');
}
ty::re_inferred { w.write_char('?'); }
}
}

View File

@ -65,13 +65,19 @@ type ctxt = {
parent: parent,
/* True if we're within the pattern part of an alt, false otherwise. */
in_alt: bool
in_alt: bool,
/*
* Points to the site of the current typeclass implementation, or none if
* we're outside one.
*/
self_binding: option<ast::def_id>
};
fn region_to_scope(region_map: @region_map, region: ty::region)
-> ast::node_id {
ret alt region {
ty::re_caller(def_id) { def_id.node }
ty::re_caller(def_id) | ty::re_self(def_id) { def_id.node }
ty::re_named(def_id) { region_map.region_name_to_fn.get(def_id) }
ty::re_block(node_id) { node_id }
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>) {
alt ty.node {
ast::ty_rptr({id: region_id, node: node}, _) {
alt node {
ast::re_inferred | ast::re_self { /* no-op */ }
ast::re_inferred { /* no-op */ }
ast::re_self {
alt cx.self_binding {
some(def_id) {
let region = ty::re_self(def_id);
let rm = cx.region_map;
rm.ast_type_to_region.insert(region_id, region);
}
none {
cx.sess.span_err(ty.span,
"the `self` region is not \
allowed here");
}
}
}
ast::re_named(ident) {
// If at item scope, introduce or reuse a binding. If at
// block scope, require that the binding be introduced.
@ -281,13 +301,22 @@ fn resolve_local(local: @ast::local, cx: ctxt, visitor: visit::vt<ctxt>) {
fn resolve_item(item: @ast::item, cx: ctxt, visitor: visit::vt<ctxt>) {
// Items create a new outer block scope as far as we're concerned.
let parent = alt item.node {
ast::item_fn(_, _, _) | ast::item_enum(_, _) { pa_fn_item(item.id) }
_ { pa_item(item.id) }
let parent;
let mut self_binding = cx.self_binding;
alt item.node {
ast::item_fn(_, _, _) | ast::item_enum(_, _) {
parent = pa_fn_item(item.id);
}
ast::item_impl(_, _, _, _) {
self_binding = some({crate: ast::local_crate, node: item.id});
parent = pa_item(item.id);
}
_ { parent = pa_item(item.id); }
};
let new_cx: ctxt = {bindings: @list::nil,
parent: parent,
in_alt: false
in_alt: false,
self_binding: self_binding
with cx};
visit::visit_item(item, new_cx, visitor);
}
@ -307,7 +336,8 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
mut bindings: @list::nil,
mut queued_locals: [],
parent: pa_crate,
in_alt: false};
in_alt: false,
self_binding: none};
let visitor = visit::mk_vt(@{
visit_block: resolve_block,
visit_item: resolve_item,

View File

@ -28,7 +28,9 @@ fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
alt ty::get(t).struct {
ty::ty_rptr(region, _) {
alt region {
ty::re_named(_) | ty::re_caller(_) { /* ok */ }
ty::re_named(_) | ty::re_caller(_) | ty::re_self(_) {
/* ok */
}
ty::re_block(rbi) {
let referent_block_id = rbi;
let enclosing_block_id = alt cx.enclosing_block {

View File

@ -233,6 +233,7 @@ type fn_ty = {proto: ast::proto,
enum region {
re_named(def_id),
re_caller(def_id),
re_self(def_id),
re_block(node_id),
re_inferred /* currently unresolved (for typedefs) */
}
@ -1152,8 +1153,9 @@ fn hash_type_structure(st: sty) -> uint {
alt r {
re_named(_) { 1u }
re_caller(_) { 2u }
re_block(_) { 3u }
re_inferred { 4u }
re_self(_) { 3u }
re_block(_) { 4u }
re_inferred { 5u }
}
}
alt st {

View File

@ -254,10 +254,11 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
fn subst_inferred_regions(tcx: ty::ctxt, use_site: ast::node_id,
ty: ty::t) -> ty::t {
ret ty::fold_ty(tcx, ty::fm_rptr({|r|
if r == ty::re_inferred {
tcx.region_map.ast_type_to_inferred_region.get(use_site)
} else {
r
alt r {
ty::re_inferred | ty::re_self(_) {
tcx.region_map.ast_type_to_inferred_region.get(use_site)
}
_ { r }
}
}), ty);
}
@ -1462,7 +1463,9 @@ fn instantiate_self_regions(pcx: pat_ctxt, args: [ty::t]) -> [ty::t] {
if ty::type_has_rptrs(arg_ty) {
ty::fold_ty(pcx.fcx.ccx.tcx, ty::fm_rptr({|r|
alt r {
ty::re_inferred | ty::re_caller(_) { pcx.pat_region }
ty::re_inferred | ty::re_caller(_) | ty::re_self(_) {
pcx.pat_region
}
_ { r }
}
}), arg_ty)

View File

@ -73,6 +73,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
re_named(_) { "<name>." } // TODO: include name
re_caller(_) { "<caller>." }
re_block(_) { "<block>." } // TODO: include line number
re_self(_) { "self." }
re_inferred { "" }
}
}