1
Fork 0

Move inference-related fields/methods from fn_ctxt to infer_ctxt.

This commit is contained in:
Lindsey Kuper 2012-05-17 11:07:24 -07:00
parent 251a0a38d7
commit 7f45ba4744
6 changed files with 68 additions and 60 deletions

View file

@ -53,6 +53,7 @@ import middle::ty;
import middle::ty::{arg, field, node_type_table, mk_nil, import middle::ty::{arg, field, node_type_table, mk_nil,
ty_param_bounds_and_ty, lookup_public_fields}; ty_param_bounds_and_ty, lookup_public_fields};
import middle::ty::{ty_vid, region_vid, vid}; import middle::ty::{ty_vid, region_vid, vid};
import middle::typeck::infer::{ty_and_region_var_methods};
import util::ppaux::{ty_to_str, tys_to_str, region_to_str, import util::ppaux::{ty_to_str, tys_to_str, region_to_str,
bound_region_to_str, vstore_to_str}; bound_region_to_str, vstore_to_str};
import std::smallintmap; import std::smallintmap;
@ -68,6 +69,7 @@ import std::list;
import list::{list, nil, cons}; import list::{list, nil, cons};
export check_crate; export check_crate;
export infer;
export method_map; export method_map;
export method_origin, serialize_method_origin, deserialize_method_origin; export method_origin, serialize_method_origin, deserialize_method_origin;
export vtable_map; export vtable_map;

View file

@ -86,8 +86,6 @@ type fn_ctxt =
proto: ast::proto, proto: ast::proto,
infcx: infer::infer_ctxt, infcx: infer::infer_ctxt,
locals: hashmap<ast::node_id, ty_vid>, locals: hashmap<ast::node_id, ty_vid>,
ty_var_counter: @mut uint,
region_var_counter: @mut uint,
mut blocks: [ast::node_id], // stack of blocks in scope, may be empty mut blocks: [ast::node_id], // stack of blocks in scope, may be empty
in_scope_regions: isr_alist, in_scope_regions: isr_alist,
@ -181,13 +179,11 @@ fn check_fn(ccx: @crate_ctxt,
// Create the function context. This is either derived from scratch or, // Create the function context. This is either derived from scratch or,
// in the case of function expressions, based on the outer context. // in the case of function expressions, based on the outer context.
let fcx: @fn_ctxt = { let fcx: @fn_ctxt = {
let {infcx, locals, tvc, rvc, purity, let {infcx, locals, purity, node_types, node_type_substs} =
node_types, node_type_substs} = alt old_fcx { alt old_fcx {
none { none {
{infcx: infer::new_infer_ctxt(tcx), {infcx: infer::new_infer_ctxt(tcx),
locals: int_hash(), locals: int_hash(),
tvc: @mut 0u,
rvc: @mut 0u,
purity: decl.purity, purity: decl.purity,
node_types: smallintmap::mk(), node_types: smallintmap::mk(),
node_type_substs: map::int_hash()} node_type_substs: map::int_hash()}
@ -196,8 +192,6 @@ fn check_fn(ccx: @crate_ctxt,
assert decl.purity == ast::impure_fn; assert decl.purity == ast::impure_fn;
{infcx: fcx.infcx, {infcx: fcx.infcx,
locals: fcx.locals, locals: fcx.locals,
tvc: fcx.ty_var_counter,
rvc: fcx.region_var_counter,
purity: fcx.purity, purity: fcx.purity,
node_types: fcx.node_types, node_types: fcx.node_types,
node_type_substs: fcx.node_type_substs} node_type_substs: fcx.node_type_substs}
@ -219,8 +213,6 @@ fn check_fn(ccx: @crate_ctxt,
proto: proto, proto: proto,
infcx: infcx, infcx: infcx,
locals: locals, locals: locals,
ty_var_counter: tvc,
region_var_counter: rvc,
mut blocks: [], mut blocks: [],
in_scope_regions: isr, in_scope_regions: isr,
node_types: node_types, node_types: node_types,
@ -265,7 +257,7 @@ fn check_fn(ccx: @crate_ctxt,
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
let assign = fn@(nid: ast::node_id, ty_opt: option<ty::t>) { let assign = fn@(nid: ast::node_id, ty_opt: option<ty::t>) {
let var_id = fcx.next_ty_var_id(); let var_id = fcx.infcx.next_ty_var_id();
fcx.locals.insert(nid, var_id); fcx.locals.insert(nid, var_id);
alt ty_opt { alt ty_opt {
none {/* nothing to do */ } none {/* nothing to do */ }
@ -429,13 +421,13 @@ impl of ast_conv for @fn_ctxt {
} }
fn ty_infer(_span: span) -> ty::t { fn ty_infer(_span: span) -> ty::t {
self.next_ty_var() self.infcx.next_ty_var()
} }
} }
impl of region_scope for @fn_ctxt { impl of region_scope for @fn_ctxt {
fn anon_region() -> result<ty::region, str> { fn anon_region() -> result<ty::region, str> {
result::ok(self.next_region_var()) result::ok(self.infcx.next_region_var())
} }
fn named_region(id: str) -> result<ty::region, str> { fn named_region(id: str) -> result<ty::region, str> {
empty_rscope.named_region(id).chain_err { |_e| empty_rscope.named_region(id).chain_err { |_e|
@ -522,25 +514,6 @@ impl methods for @fn_ctxt {
fn opt_node_ty_substs(id: ast::node_id) -> option<ty::substs> { fn opt_node_ty_substs(id: ast::node_id) -> option<ty::substs> {
self.node_type_substs.find(id) self.node_type_substs.find(id)
} }
fn next_ty_var_id() -> ty_vid {
let id = *self.ty_var_counter;
*self.ty_var_counter += 1u;
ret ty_vid(id);
}
fn next_ty_var() -> ty::t {
ty::mk_var(self.ccx.tcx, self.next_ty_var_id())
}
fn next_ty_vars(n: uint) -> [ty::t] {
vec::from_fn(n) {|_i| self.next_ty_var() }
}
fn next_region_var_id() -> region_vid {
let id = *self.region_var_counter;
*self.region_var_counter += 1u;
ret region_vid(id);
}
fn next_region_var() -> ty::region {
ret ty::re_var(self.next_region_var_id());
}
fn report_mismatched_types(sp: span, e: ty::t, a: ty::t, fn report_mismatched_types(sp: span, e: ty::t, a: ty::t,
err: ty::type_err) { err: ty::type_err) {
@ -691,7 +664,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
rp: rp, rp: rp,
raw_ty: ty::mk_class(tcx, local_def(class_id), raw_ty: ty::mk_class(tcx, local_def(class_id),
{self_r: alt rp { {self_r: alt rp {
ast::rp_self { some(fcx.next_region_var()) } ast::rp_self { some(fcx.infcx.next_region_var()) }
ast::rp_none { none }}, ast::rp_none { none }},
self_ty: none, self_ty: none,
tps: ty::ty_params_to_tys(tcx, ts)})} tps: ty::ty_params_to_tys(tcx, ts)})}
@ -708,9 +681,9 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
let self_r = alt rp { let self_r = alt rp {
ast::rp_none { none } ast::rp_none { none }
ast::rp_self { some(fcx.next_region_var()) } ast::rp_self { some(fcx.infcx.next_region_var()) }
}; };
let tps = fcx.next_ty_vars(n_tps); let tps = fcx.infcx.next_ty_vars(n_tps);
let substs = {self_r: self_r, self_ty: none, tps: tps}; let substs = {self_r: self_r, self_ty: none, tps: tps};
let substd_ty = ty::subst(tcx, substs, raw_ty); let substd_ty = ty::subst(tcx, substs, raw_ty);
@ -772,7 +745,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
} else { } else {
"s were" "s were"
}]); }]);
fcx.next_ty_vars(supplied_arg_count) fcx.infcx.next_ty_vars(supplied_arg_count)
} }
} }
@ -875,7 +848,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
let (if_t, if_bot) = let (if_t, if_bot) =
alt elsopt { alt elsopt {
some(els) { some(els) {
let if_t = fcx.next_ty_var(); let if_t = fcx.infcx.next_ty_var();
let thn_bot = check_block(fcx, thn); let thn_bot = check_block(fcx, thn);
let thn_t = fcx.node_ty(thn.node.id); let thn_t = fcx.node_ty(thn.node.id);
demand::suptype(fcx, thn.span, if_t, thn_t); demand::suptype(fcx, thn.span, if_t, thn_t);
@ -938,7 +911,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
// result [ML T] where TL <: T and TR <: T. In other words, the // result [ML T] where TL <: T and TR <: T. In other words, the
// result type is (generally) the LUB of (TL, TR) and takes the // result type is (generally) the LUB of (TL, TR) and takes the
// mutability from the LHS. // mutability from the LHS.
let t_var = fcx.next_ty_var(); let t_var = fcx.infcx.next_ty_var();
let const_vec_t = ty::mk_vec(tcx, {ty: t_var, let const_vec_t = ty::mk_vec(tcx, {ty: t_var,
mutbl: ast::m_const}); mutbl: ast::m_const});
demand::suptype(fcx, lhs.span, const_vec_t, lhs_t); demand::suptype(fcx, lhs.span, const_vec_t, lhs_t);
@ -960,7 +933,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
} }
(_, _) if ty::is_binopable(tcx, lhs_t, op) { (_, _) if ty::is_binopable(tcx, lhs_t, op) {
let tvar = fcx.next_ty_var(); let tvar = fcx.infcx.next_ty_var();
demand::suptype(fcx, expr.span, tvar, lhs_t); demand::suptype(fcx, expr.span, tvar, lhs_t);
let rhs_bot = check_expr_with(fcx, rhs, tvar); let rhs_bot = check_expr_with(fcx, rhs, tvar);
let rhs_t = alt op { let rhs_t = alt op {
@ -1087,7 +1060,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
} }
ast::expr_vec(args, mutbl) { ast::expr_vec(args, mutbl) {
let tt = ast_expr_vstore_to_vstore(fcx, ev, vec::len(args), vst); let tt = ast_expr_vstore_to_vstore(fcx, ev, vec::len(args), vst);
let t: ty::t = fcx.next_ty_var(); let t: ty::t = fcx.infcx.next_ty_var();
for args.each {|e| bot |= check_expr_with(fcx, e, t); } for args.each {|e| bot |= check_expr_with(fcx, e, t); }
ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt) ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt)
} }
@ -1117,7 +1090,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
ast::expr_binary(ast::gt, lhs, rhs) | ast::expr_binary(ast::gt, lhs, rhs) |
ast::expr_binary(ast::ge, lhs, rhs) { ast::expr_binary(ast::ge, lhs, rhs) {
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
let tvar = fcx.next_ty_var(); let tvar = fcx.infcx.next_ty_var();
bot |= check_expr_with(fcx, lhs, tvar); bot |= check_expr_with(fcx, lhs, tvar);
bot |= check_expr_with(fcx, rhs, tvar); bot |= check_expr_with(fcx, rhs, tvar);
fcx.write_ty(id, ty::mk_bool(tcx)); fcx.write_ty(id, ty::mk_bool(tcx));
@ -1463,7 +1436,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
fcx.write_ty(id, t_1); fcx.write_ty(id, t_1);
} }
ast::expr_vec(args, mutbl) { ast::expr_vec(args, mutbl) {
let t: ty::t = fcx.next_ty_var(); let t: ty::t = fcx.infcx.next_ty_var();
for args.each {|e| bot |= check_expr_with(fcx, e, t); } for args.each {|e| bot |= check_expr_with(fcx, e, t); }
let typ = ty::mk_vec(tcx, {ty: t, mutbl: mutbl}); let typ = ty::mk_vec(tcx, {ty: t, mutbl: mutbl});
fcx.write_ty(id, typ); fcx.write_ty(id, typ);
@ -1608,7 +1581,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
field, ty_to_str(tcx, t_err)]; field, ty_to_str(tcx, t_err)];
tcx.sess.span_err(expr.span, msg); tcx.sess.span_err(expr.span, msg);
// NB: Adding a bogus type to allow typechecking to continue // NB: Adding a bogus type to allow typechecking to continue
fcx.write_ty(id, fcx.next_ty_var()); fcx.write_ty(id, fcx.infcx.next_ty_var());
} }
} }
} }
@ -1836,8 +1809,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
proto: ast::proto_box, proto: ast::proto_box,
infcx: infer::new_infer_ctxt(ccx.tcx), infcx: infer::new_infer_ctxt(ccx.tcx),
locals: int_hash(), locals: int_hash(),
ty_var_counter: @mut 0u,
region_var_counter: @mut 0u,
mut blocks: [], mut blocks: [],
in_scope_regions: @nil, in_scope_regions: @nil,
node_types: smallintmap::mk(), node_types: smallintmap::mk(),
@ -1878,8 +1849,6 @@ fn check_enum_variants(ccx: @crate_ctxt,
proto: ast::proto_box, proto: ast::proto_box,
infcx: infer::new_infer_ctxt(ccx.tcx), infcx: infer::new_infer_ctxt(ccx.tcx),
locals: int_hash(), locals: int_hash(),
ty_var_counter: @mut 0u,
region_var_counter: @mut 0u,
mut blocks: [], mut blocks: [],
in_scope_regions: @nil, in_scope_regions: @nil,
node_types: smallintmap::mk(), node_types: smallintmap::mk(),
@ -2148,24 +2117,24 @@ fn instantiate_path(fcx: @fn_ctxt,
// For now, there is no way to explicitly specify the region bound. // For now, there is no way to explicitly specify the region bound.
// This will have to change eventually. // This will have to change eventually.
let self_r = alt tpt.rp { let self_r = alt tpt.rp {
ast::rp_self { some(fcx.next_region_var()) } ast::rp_self { some(fcx.infcx.next_region_var()) }
ast::rp_none { none } ast::rp_none { none }
}; };
let tps = if ty_substs_len == 0u { let tps = if ty_substs_len == 0u {
fcx.next_ty_vars(ty_param_count) fcx.infcx.next_ty_vars(ty_param_count)
} else if ty_param_count == 0u { } else if ty_param_count == 0u {
fcx.ccx.tcx.sess.span_err fcx.ccx.tcx.sess.span_err
(sp, "this item does not take type parameters"); (sp, "this item does not take type parameters");
fcx.next_ty_vars(ty_param_count) fcx.infcx.next_ty_vars(ty_param_count)
} else if ty_substs_len > ty_param_count { } else if ty_substs_len > ty_param_count {
fcx.ccx.tcx.sess.span_err fcx.ccx.tcx.sess.span_err
(sp, "too many type parameters provided for this item"); (sp, "too many type parameters provided for this item");
fcx.next_ty_vars(ty_param_count) fcx.infcx.next_ty_vars(ty_param_count)
} else if ty_substs_len < ty_param_count { } else if ty_substs_len < ty_param_count {
fcx.ccx.tcx.sess.span_err fcx.ccx.tcx.sess.span_err
(sp, "not enough type parameters provided for this item"); (sp, "not enough type parameters provided for this item");
fcx.next_ty_vars(ty_param_count) fcx.infcx.next_ty_vars(ty_param_count)
} else { } else {
pth.types.map { |aty| fcx.to_ty(aty) } pth.types.map { |aty| fcx.to_ty(aty) }
}; };

View file

@ -1,3 +1,5 @@
import middle::typeck::infer::{ty_and_region_var_methods};
fn check_alt(fcx: @fn_ctxt, fn check_alt(fcx: @fn_ctxt,
expr: @ast::expr, expr: @ast::expr,
discrim: @ast::expr, discrim: @ast::expr,
@ -5,7 +7,7 @@ fn check_alt(fcx: @fn_ctxt,
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
let mut bot = false; let mut bot = false;
let pattern_ty = fcx.next_ty_var(); let pattern_ty = fcx.infcx.next_ty_var();
bot = check_expr_with(fcx, discrim, pattern_ty); bot = check_expr_with(fcx, discrim, pattern_ty);
// Typecheck the patterns first, so that we get types for all the // Typecheck the patterns first, so that we get types for all the
@ -22,7 +24,7 @@ fn check_alt(fcx: @fn_ctxt,
for arm.pats.each {|p| check_pat(pcx, p, pattern_ty);} for arm.pats.each {|p| check_pat(pcx, p, pattern_ty);}
} }
// Now typecheck the blocks. // Now typecheck the blocks.
let mut result_ty = fcx.next_ty_var(); let mut result_ty = fcx.infcx.next_ty_var();
let mut arm_non_bot = false; let mut arm_non_bot = false;
for arms.each {|arm| for arms.each {|arm|
alt arm.guard { alt arm.guard {

View file

@ -1,6 +1,7 @@
/* Code to handle method lookups (which can be quite complex) */ /* Code to handle method lookups (which can be quite complex) */
import regionmanip::universally_quantify_regions; import regionmanip::universally_quantify_regions;
import middle::typeck::infer::{ty_and_region_var_methods};
enum lookup = { enum lookup = {
fcx: @fn_ctxt, fcx: @fn_ctxt,
@ -266,18 +267,18 @@ impl methods for lookup {
let n_tps_supplied = self.supplied_tps.len(); let n_tps_supplied = self.supplied_tps.len();
let m_substs = { let m_substs = {
if n_tps_supplied == 0u { if n_tps_supplied == 0u {
self.fcx.next_ty_vars(n_tps_m) self.fcx.infcx.next_ty_vars(n_tps_m)
} else if n_tps_m == 0u { } else if n_tps_m == 0u {
tcx.sess.span_err( tcx.sess.span_err(
self.expr.span, self.expr.span,
"this method does not take type parameters"); "this method does not take type parameters");
self.fcx.next_ty_vars(n_tps_m) self.fcx.infcx.next_ty_vars(n_tps_m)
} else if n_tps_supplied != n_tps_m { } else if n_tps_supplied != n_tps_m {
tcx.sess.span_err( tcx.sess.span_err(
self.expr.span, self.expr.span,
"incorrect number of type \ "incorrect number of type \
parameters given for this method"); parameters given for this method");
self.fcx.next_ty_vars(n_tps_m) self.fcx.infcx.next_ty_vars(n_tps_m)
} else { } else {
self.supplied_tps self.supplied_tps
} }

View file

@ -1,3 +1,5 @@
import middle::typeck::infer::{ty_and_region_var_methods};
// Helper functions related to manipulating region types. // Helper functions related to manipulating region types.
// Helper for the other universally_quantify_*() routines. Extracts the bound // Helper for the other universally_quantify_*() routines. Extracts the bound
@ -13,7 +15,7 @@ fn universally_quantify_from_sty(fcx: @fn_ctxt,
indent {|| indent {||
let tcx = fcx.tcx(); let tcx = fcx.tcx();
let isr = collect_bound_regions_in_tys(tcx, @nil, bound_tys) { |br| let isr = collect_bound_regions_in_tys(tcx, @nil, bound_tys) { |br|
let rvar = fcx.next_region_var(); let rvar = fcx.infcx.next_region_var();
#debug["Bound region %s maps to %s", #debug["Bound region %s maps to %s",
bound_region_to_str(fcx.ccx.tcx, br), bound_region_to_str(fcx.ccx.tcx, br),
region_to_str(fcx.ccx.tcx, rvar)]; region_to_str(fcx.ccx.tcx, rvar)];

View file

@ -165,6 +165,7 @@ export mk_assignty;
export resolve_shallow; export resolve_shallow;
export resolve_deep; export resolve_deep;
export resolve_deep_var; export resolve_deep_var;
export ty_and_region_var_methods;
export compare_tys; export compare_tys;
export fixup_err, fixup_err_to_str; export fixup_err, fixup_err_to_str;
@ -195,6 +196,10 @@ enum infer_ctxt = @{
tcx: ty::ctxt, tcx: ty::ctxt,
vb: vals_and_bindings<ty::ty_vid, ty::t>, vb: vals_and_bindings<ty::ty_vid, ty::t>,
rb: vals_and_bindings<ty::region_vid, ty::region>, rb: vals_and_bindings<ty::region_vid, ty::region>,
// For keeping track of existing type/region variables.
ty_var_counter: @mut uint,
region_var_counter: @mut uint,
}; };
enum fixup_err { enum fixup_err {
@ -219,8 +224,9 @@ type fres<T> = result::result<T, fixup_err>;
fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt { fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
infer_ctxt(@{tcx: tcx, infer_ctxt(@{tcx: tcx,
vb: {vals: smallintmap::mk(), mut bindings: []}, vb: {vals: smallintmap::mk(), mut bindings: []},
rb: {vals: smallintmap::mk(), mut bindings: []}}) rb: {vals: smallintmap::mk(), mut bindings: []},
} ty_var_counter: @mut 0u,
region_var_counter: @mut 0u})}
fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
#debug["mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)]; #debug["mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
@ -423,6 +429,32 @@ impl methods for infer_ctxt {
} }
} }
impl ty_and_region_var_methods for infer_ctxt {
fn next_ty_var_id() -> ty_vid {
let id = *self.ty_var_counter;
*self.ty_var_counter += 1u;
ret ty_vid(id);
}
fn next_ty_var() -> ty::t {
ty::mk_var(self.tcx, self.next_ty_var_id())
}
fn next_ty_vars(n: uint) -> [ty::t] {
vec::from_fn(n) {|_i| self.next_ty_var() }
}
fn next_region_var_id() -> region_vid {
let id = *self.region_var_counter;
*self.region_var_counter += 1u;
ret region_vid(id);
}
fn next_region_var() -> ty::region {
ret ty::re_var(self.next_region_var_id());
}
}
impl unify_methods for infer_ctxt { impl unify_methods for infer_ctxt {
fn set<V:copy vid, T:copy to_str>( fn set<V:copy vid, T:copy to_str>(