From ac4e57c6400bdd500a1918238fc76abc3b7def3d Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Tue, 31 Jul 2012 18:11:38 -0700 Subject: [PATCH] Introduce self_info (self_ty packaged up with a node_id). --- src/rustc/middle/typeck/check.rs | 54 +++++++++++--------- src/rustc/middle/typeck/check/regionmanip.rs | 37 +++++++++++--- 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index d8dd6bf0542..98f0eed7296 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -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, + {self_info: option, ret_ty: ty::t, // Used by loop bodies that return from the outer function indirect_ret_ty: option, @@ -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) { + self_info: option) { 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, + self_info: option, 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"); } } } diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs index efb50b1eb8f..5bbe9bb1867 100644 --- a/src/rustc/middle/typeck/check/regionmanip.rs +++ b/src/rustc/middle/typeck/check/regionmanip.rs @@ -5,16 +5,24 @@ fn replace_bound_regions_in_fn_ty( tcx: ty::ctxt, isr: isr_alist, - self_ty: option, + self_info: option, fn_ty: ty::fn_ty, - mapf: fn(ty::bound_region) -> ty::region) -> {isr: isr_alist, - self_ty: option, - fn_ty: ty::fn_ty} { + mapf: fn(ty::bound_region) -> ty::region) -> + {isr: isr_alist, self_info: option, 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} }};