Introduce self_info (self_ty packaged up with a node_id).

This commit is contained in:
Lindsey Kuper 2012-07-31 18:11:38 -07:00
parent 361a9b03e6
commit ac4e57c640
2 changed files with 61 additions and 30 deletions

View File

@ -79,11 +79,16 @@
import std::map::str_hash;
type self_info = {
self_ty: ty::t,
node_id: ast::node_id,
};
type fn_ctxt_ =
// var_bindings, locals and next_var_id are shared
// with any nested functions that capture the environment
// (and with any functions whose environment is being captured).
{self_ty: option<ty::t>,
{self_info: option<self_info>,
ret_ty: ty::t,
// Used by loop bodies that return from the outer function
indirect_ret_ty: option<ty::t>,
@ -122,7 +127,7 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t,
region_bnd: ast::node_id) -> @fn_ctxt {
// It's kind of a kludge to manufacture a fake function context
// and statement context, but we might as well do write the code only once
@fn_ctxt_({self_ty: none,
@fn_ctxt_({self_info: none,
ret_ty: rty,
indirect_ret_ty: none,
purity: ast::pure_fn,
@ -170,14 +175,14 @@ fn check_bare_fn(ccx: @crate_ctxt,
decl: ast::fn_decl,
body: ast::blk,
id: ast::node_id,
self_ty: option<ty::t>) {
self_info: option<self_info>) {
let fty = ty::node_id_to_type(ccx.tcx, id);
let fn_ty = alt check ty::get(fty).struct { ty::ty_fn(f) {f} };
check_fn(ccx, self_ty, fn_ty, decl, body, false, none);
check_fn(ccx, self_info, fn_ty, decl, body, false, none);
}
fn check_fn(ccx: @crate_ctxt,
self_ty: option<ty::t>,
self_info: option<self_info>,
fn_ty: ty::fn_ty,
decl: ast::fn_decl,
body: ast::blk,
@ -191,20 +196,20 @@ fn check_fn(ccx: @crate_ctxt,
// types with free ones. The free region references will be bound
// the node_id of the body block.
let {isr, self_ty, fn_ty} = {
let {isr, self_info, fn_ty} = {
let old_isr = option::map_default(old_fcx, @nil,
|fcx| fcx.in_scope_regions);
replace_bound_regions_in_fn_ty(tcx, old_isr, self_ty, fn_ty,
replace_bound_regions_in_fn_ty(tcx, old_isr, self_info, fn_ty,
|br| ty::re_free(body.node.id, br))
};
let arg_tys = fn_ty.inputs.map(|a| a.ty);
let ret_ty = fn_ty.output;
debug!{"check_fn(arg_tys=%?, ret_ty=%?, self_ty=%?)",
debug!{"check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)",
arg_tys.map(|a| ty_to_str(tcx, a)),
ty_to_str(tcx, ret_ty),
option::map(self_ty, |st| ty_to_str(tcx, st))};
option::map(self_info, |s| ty_to_str(tcx, s.self_ty))};
// ______________________________________________________________________
// Create the function context. This is either derived from scratch or,
@ -237,7 +242,7 @@ fn check_fn(ccx: @crate_ctxt,
}
} else { none };
@fn_ctxt_({self_ty: self_ty,
@fn_ctxt_({self_info: self_info,
ret_ty: ret_ty,
indirect_ret_ty: indirect_ret_ty,
purity: purity,
@ -359,11 +364,12 @@ fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { }
}
}
fn check_method(ccx: @crate_ctxt, method: @ast::method, self_ty: ty::t) {
check_bare_fn(ccx, method.decl, method.body, method.id, some(self_ty));
fn check_method(ccx: @crate_ctxt, method: @ast::method,
self_info: self_info) {
check_bare_fn(ccx, method.decl, method.body, method.id, some(self_info));
}
fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
fn check_class_member(ccx: @crate_ctxt, class_t: self_info,
cm: @ast::class_member) {
alt cm.node {
ast::instance_var(_,t,_,_,_) { }
@ -409,12 +415,14 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
let rp = ccx.tcx.region_paramd_items.contains_key(it.id);
debug!{"item_impl %s with id %d rp %b",
*it.ident, it.id, rp};
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
for ms.each |m| { check_method(ccx, m, self_ty);}
let self_info = {self_ty: ccx.to_ty(rscope::type_rscope(rp), ty),
node_id: it.id };
for ms.each |m| { check_method(ccx, m, self_info);}
}
ast::item_class(tps, traits, members, m_ctor, m_dtor) {
let tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id);
let class_t = {self_ty: ty::node_id_to_type(tcx, it.id),
node_id: it.id};
do option::iter(m_ctor) |ctor| {
// typecheck the ctor
@ -422,7 +430,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
ctor.node.body, ctor.node.id,
some(class_t));
// Write the ctor's self's type
write_ty_to_tcx(tcx, ctor.node.self_id, class_t);
write_ty_to_tcx(tcx, ctor.node.self_id, class_t.self_ty);
}
do option::iter(m_dtor) |dtor| {
@ -431,7 +439,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
dtor.node.body, dtor.node.id,
some(class_t));
// Write the dtor's self's type
write_ty_to_tcx(tcx, dtor.node.self_id, class_t);
write_ty_to_tcx(tcx, dtor.node.self_id, class_t.self_ty);
};
// typecheck the members
@ -1123,7 +1131,7 @@ fn check_expr_fn(fcx: @fn_ctxt,
fcx.write_ty(expr.id, fty);
check_fn(fcx.ccx, fcx.self_ty, fn_ty, decl, body,
check_fn(fcx.ccx, fcx.self_info, fn_ty, decl, body,
is_loop_body, some(fcx));
}
@ -2145,12 +2153,12 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ret no_params(typ);
}
ast::def_self(_) {
alt fcx.self_ty {
some(self_ty) {
ret no_params(self_ty);
alt fcx.self_info {
some(self_info) {
ret no_params(self_info.self_ty);
}
none {
fcx.ccx.tcx.sess.span_bug(sp, ~"def_self with no self_ty");
fcx.ccx.tcx.sess.span_bug(sp, ~"def_self with no self_info");
}
}
}

View File

@ -5,16 +5,24 @@
fn replace_bound_regions_in_fn_ty(
tcx: ty::ctxt,
isr: isr_alist,
self_ty: option<ty::t>,
self_info: option<self_info>,
fn_ty: ty::fn_ty,
mapf: fn(ty::bound_region) -> ty::region) -> {isr: isr_alist,
self_ty: option<ty::t>,
fn_ty: ty::fn_ty} {
mapf: fn(ty::bound_region) -> ty::region) ->
{isr: isr_alist, self_info: option<self_info>, fn_ty: ty::fn_ty} {
// Take self_info apart; the self_ty part is the only one we want
// to update here.
let self_ty = alt self_info {
some(s) { some(s.self_ty) }
none { none }
};
let mut all_tys = ty::tys_in_fn_ty(fn_ty);
for self_ty.each |t| { vec::push(all_tys, t) }
debug!{"replace_bound_regions_in_fn_ty(self_ty=%?, fn_ty=%s, all_tys=%?)",
debug!{"replace_bound_regions_in_fn_ty(self_info.self_ty=%?, fn_ty=%s, \
all_tys=%?)",
self_ty.map(|t| ty_to_str(tcx, t)),
ty_to_str(tcx, ty::mk_fn(tcx, fn_ty)),
all_tys.map(|t| ty_to_str(tcx, t))};
@ -29,12 +37,27 @@ fn replace_bound_regions_in_fn_ty(
});
let t_self = self_ty.map(|t| replace_bound_regions(tcx, isr, t));
debug!{"result of replace_bound_regions_in_fn_ty: self_ty=%?, fn_ty=%s",
debug!{"result of replace_bound_regions_in_fn_ty: self_info.self_ty=%?, \
fn_ty=%s",
t_self.map(|t| ty_to_str(tcx, t)),
ty_to_str(tcx, t_fn)};
// Glue updated self_ty back together with its original node_id.
let new_self_info = alt self_info {
some(s) {
alt check t_self {
some(t) {
some({self_ty: t, node_id: s.node_id})
}
// this 'none' case shouldn't happen
}
}
none { none }
};
ret {isr: isr,
self_ty: t_self,
self_info: new_self_info,
fn_ty: alt check ty::get(t_fn).struct { ty::ty_fn(o) {o} }};