rustc: Create self region bindings, and forbid the self region from being used in places it shouldn't be
This commit is contained in:
parent
041c9a0863
commit
bc21a5ddbe
|
@ -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('?'); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 { "" }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue