Introduce self_info (self_ty packaged up with a node_id).
This commit is contained in:
@@ -79,11 +79,16 @@ import typeck::infer::{resolve_type, force_tvar};
|
|||||||
|
|
||||||
import std::map::str_hash;
|
import std::map::str_hash;
|
||||||
|
|
||||||
|
type self_info = {
|
||||||
|
self_ty: ty::t,
|
||||||
|
node_id: ast::node_id,
|
||||||
|
};
|
||||||
|
|
||||||
type fn_ctxt_ =
|
type fn_ctxt_ =
|
||||||
// var_bindings, locals and next_var_id are shared
|
// var_bindings, locals and next_var_id are shared
|
||||||
// with any nested functions that capture the environment
|
// with any nested functions that capture the environment
|
||||||
// (and with any functions whose environment is being captured).
|
// (and with any functions whose environment is being captured).
|
||||||
{self_ty: option<ty::t>,
|
{self_info: option<self_info>,
|
||||||
ret_ty: ty::t,
|
ret_ty: ty::t,
|
||||||
// Used by loop bodies that return from the outer function
|
// Used by loop bodies that return from the outer function
|
||||||
indirect_ret_ty: option<ty::t>,
|
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 {
|
region_bnd: ast::node_id) -> @fn_ctxt {
|
||||||
// It's kind of a kludge to manufacture a fake function context
|
// 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
|
// 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,
|
ret_ty: rty,
|
||||||
indirect_ret_ty: none,
|
indirect_ret_ty: none,
|
||||||
purity: ast::pure_fn,
|
purity: ast::pure_fn,
|
||||||
@@ -170,14 +175,14 @@ fn check_bare_fn(ccx: @crate_ctxt,
|
|||||||
decl: ast::fn_decl,
|
decl: ast::fn_decl,
|
||||||
body: ast::blk,
|
body: ast::blk,
|
||||||
id: ast::node_id,
|
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 fty = ty::node_id_to_type(ccx.tcx, id);
|
||||||
let fn_ty = alt check ty::get(fty).struct { ty::ty_fn(f) {f} };
|
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,
|
fn check_fn(ccx: @crate_ctxt,
|
||||||
self_ty: option<ty::t>,
|
self_info: option<self_info>,
|
||||||
fn_ty: ty::fn_ty,
|
fn_ty: ty::fn_ty,
|
||||||
decl: ast::fn_decl,
|
decl: ast::fn_decl,
|
||||||
body: ast::blk,
|
body: ast::blk,
|
||||||
@@ -191,20 +196,20 @@ fn check_fn(ccx: @crate_ctxt,
|
|||||||
// types with free ones. The free region references will be bound
|
// types with free ones. The free region references will be bound
|
||||||
// the node_id of the body block.
|
// 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,
|
let old_isr = option::map_default(old_fcx, @nil,
|
||||||
|fcx| fcx.in_scope_regions);
|
|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))
|
|br| ty::re_free(body.node.id, br))
|
||||||
};
|
};
|
||||||
|
|
||||||
let arg_tys = fn_ty.inputs.map(|a| a.ty);
|
let arg_tys = fn_ty.inputs.map(|a| a.ty);
|
||||||
let ret_ty = fn_ty.output;
|
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)),
|
arg_tys.map(|a| ty_to_str(tcx, a)),
|
||||||
ty_to_str(tcx, ret_ty),
|
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,
|
// Create the function context. This is either derived from scratch or,
|
||||||
@@ -237,7 +242,7 @@ fn check_fn(ccx: @crate_ctxt,
|
|||||||
}
|
}
|
||||||
} else { none };
|
} else { none };
|
||||||
|
|
||||||
@fn_ctxt_({self_ty: self_ty,
|
@fn_ctxt_({self_info: self_info,
|
||||||
ret_ty: ret_ty,
|
ret_ty: ret_ty,
|
||||||
indirect_ret_ty: indirect_ret_ty,
|
indirect_ret_ty: indirect_ret_ty,
|
||||||
purity: purity,
|
purity: purity,
|
||||||
@@ -359,11 +364,12 @@ fn check_fn(ccx: @crate_ctxt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_method(ccx: @crate_ctxt, method: @ast::method, self_ty: ty::t) {
|
fn check_method(ccx: @crate_ctxt, method: @ast::method,
|
||||||
check_bare_fn(ccx, method.decl, method.body, method.id, some(self_ty));
|
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) {
|
cm: @ast::class_member) {
|
||||||
alt cm.node {
|
alt cm.node {
|
||||||
ast::instance_var(_,t,_,_,_) { }
|
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);
|
let rp = ccx.tcx.region_paramd_items.contains_key(it.id);
|
||||||
debug!{"item_impl %s with id %d rp %b",
|
debug!{"item_impl %s with id %d rp %b",
|
||||||
*it.ident, it.id, rp};
|
*it.ident, it.id, rp};
|
||||||
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
|
let self_info = {self_ty: ccx.to_ty(rscope::type_rscope(rp), ty),
|
||||||
for ms.each |m| { check_method(ccx, m, self_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) {
|
ast::item_class(tps, traits, members, m_ctor, m_dtor) {
|
||||||
let tcx = ccx.tcx;
|
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| {
|
do option::iter(m_ctor) |ctor| {
|
||||||
// typecheck the ctor
|
// typecheck the ctor
|
||||||
@@ -422,7 +430,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
|||||||
ctor.node.body, ctor.node.id,
|
ctor.node.body, ctor.node.id,
|
||||||
some(class_t));
|
some(class_t));
|
||||||
// Write the ctor's self's type
|
// 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| {
|
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,
|
dtor.node.body, dtor.node.id,
|
||||||
some(class_t));
|
some(class_t));
|
||||||
// Write the dtor's self's type
|
// 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
|
// typecheck the members
|
||||||
@@ -1123,7 +1131,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||||||
|
|
||||||
fcx.write_ty(expr.id, fty);
|
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));
|
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);
|
ret no_params(typ);
|
||||||
}
|
}
|
||||||
ast::def_self(_) {
|
ast::def_self(_) {
|
||||||
alt fcx.self_ty {
|
alt fcx.self_info {
|
||||||
some(self_ty) {
|
some(self_info) {
|
||||||
ret no_params(self_ty);
|
ret no_params(self_info.self_ty);
|
||||||
}
|
}
|
||||||
none {
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,24 @@ import syntax::print::pprust::{expr_to_str};
|
|||||||
fn replace_bound_regions_in_fn_ty(
|
fn replace_bound_regions_in_fn_ty(
|
||||||
tcx: ty::ctxt,
|
tcx: ty::ctxt,
|
||||||
isr: isr_alist,
|
isr: isr_alist,
|
||||||
self_ty: option<ty::t>,
|
self_info: option<self_info>,
|
||||||
fn_ty: ty::fn_ty,
|
fn_ty: ty::fn_ty,
|
||||||
mapf: fn(ty::bound_region) -> ty::region) -> {isr: isr_alist,
|
mapf: fn(ty::bound_region) -> ty::region) ->
|
||||||
self_ty: option<ty::t>,
|
{isr: isr_alist, self_info: option<self_info>, fn_ty: ty::fn_ty} {
|
||||||
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);
|
let mut all_tys = ty::tys_in_fn_ty(fn_ty);
|
||||||
|
|
||||||
for self_ty.each |t| { vec::push(all_tys, t) }
|
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)),
|
self_ty.map(|t| ty_to_str(tcx, t)),
|
||||||
ty_to_str(tcx, ty::mk_fn(tcx, fn_ty)),
|
ty_to_str(tcx, ty::mk_fn(tcx, fn_ty)),
|
||||||
all_tys.map(|t| ty_to_str(tcx, t))};
|
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));
|
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)),
|
t_self.map(|t| ty_to_str(tcx, t)),
|
||||||
ty_to_str(tcx, t_fn)};
|
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,
|
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} }};
|
fn_ty: alt check ty::get(t_fn).struct { ty::ty_fn(o) {o} }};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user