store into the borrowings table

This commit is contained in:
Niko Matsakis 2012-04-13 14:52:11 -07:00
parent 4d73185f3e
commit 378996092e
3 changed files with 61 additions and 59 deletions

View file

@ -1,6 +1,7 @@
import std::smallintmap;
import std::smallintmap::smallintmap;
import std::smallintmap::map;
import std::map::hashmap;
import middle::ty;
import middle::ty::{ty_vid, region_vid, vid};
import syntax::ast;
@ -77,11 +78,12 @@ fn mk_eqty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
indent {|| cx.commit {|| cx.eq_tys(a, b) } }.to_ures()
}
fn mk_assignty(cx: infer_ctxt, encl_node_id: ast::node_id,
fn mk_assignty(cx: infer_ctxt, a_node_id: ast::node_id,
a: ty::t, b: ty::t) -> ures {
#debug["mk_assignty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
#debug["mk_assignty(%? / %s <: %s)",
a_node_id, a.to_str(cx), b.to_str(cx)];
indent {|| cx.commit {||
cx.assign_tys(encl_node_id, a, b)
cx.assign_tys(a_node_id, a, b)
} }.to_ures()
}
@ -686,7 +688,7 @@ impl resolve_methods for infer_ctxt {
// Type assignment
//
// True if rvalues of type `a` can be assigned to lvalues of type `b`.
// This may cause borrowing to the region scope for `encl_node_id`.
// This may cause borrowing to the region scope enclosing `a_node_id`.
//
// The strategy here is somewhat non-obvious. The problem is
// that the constraint we wish to contend with is not a subtyping
@ -730,7 +732,7 @@ impl resolve_methods for infer_ctxt {
// this upper-bound might be stricter than what is truly needed.
impl assignment for infer_ctxt {
fn assign_tys(encl_node_id: ast::node_id,
fn assign_tys(a_node_id: ast::node_id,
a: ty::t, b: ty::t) -> ures {
fn select(fst: option<ty::t>, snd: option<ty::t>) -> option<ty::t> {
@ -745,8 +747,8 @@ impl assignment for infer_ctxt {
}
}
#debug["assign_tys(encl_node_id=%?, %s -> %s)",
encl_node_id, a.to_str(self), b.to_str(self)];
#debug["assign_tys(a_node_id=%?, %s -> %s)",
a_node_id, a.to_str(self), b.to_str(self)];
let _r = indenter();
alt (ty::get(a).struct, ty::get(b).struct) {
@ -759,34 +761,34 @@ impl assignment for infer_ctxt {
let {root:_, bounds: b_bounds} = self.get(self.vb, b_id);
let a_bnd = select(a_bounds.ub, a_bounds.lb);
let b_bnd = select(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(encl_node_id, a, b, a_bnd, b_bnd)
self.assign_tys_or_sub(a_node_id, a, b, a_bnd, b_bnd)
}
(ty::ty_var(a_id), _) {
let {root:_, bounds:a_bounds} = self.get(self.vb, a_id);
let a_bnd = select(a_bounds.ub, a_bounds.lb);
self.assign_tys_or_sub(encl_node_id, a, b, a_bnd, some(b))
self.assign_tys_or_sub(a_node_id, a, b, a_bnd, some(b))
}
(_, ty::ty_var(b_id)) {
let {root:_, bounds: b_bounds} = self.get(self.vb, b_id);
let b_bnd = select(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(encl_node_id, a, b, some(a), b_bnd)
self.assign_tys_or_sub(a_node_id, a, b, some(a), b_bnd)
}
(_, _) {
self.assign_tys_or_sub(encl_node_id, a, b, some(a), some(b))
self.assign_tys_or_sub(a_node_id, a, b, some(a), some(b))
}
}
}
fn assign_tys_or_sub(
encl_node_id: ast::node_id,
a_node_id: ast::node_id,
a: ty::t, b: ty::t,
a_bnd: option<ty::t>, b_bnd: option<ty::t>) -> ures {
#debug["assign_tys_or_sub(encl_node_id=%?, %s -> %s, %s -> %s)",
encl_node_id, a.to_str(self), b.to_str(self),
#debug["assign_tys_or_sub(a_node_id=%?, %s -> %s, %s -> %s)",
a_node_id, a.to_str(self), b.to_str(self),
a_bnd.to_str(self), b_bnd.to_str(self)];
let _r = indenter();
@ -802,17 +804,17 @@ impl assignment for infer_ctxt {
alt (ty::get(a_bnd).struct, ty::get(b_bnd).struct) {
(ty::ty_box(mt_a), ty::ty_rptr(r_b, mt_b)) {
let nr_b = ty::mk_box(self.tcx, mt_b);
self.crosspolinate(encl_node_id, a, nr_b, r_b)
self.crosspolinate(a_node_id, a, nr_b, r_b)
}
(ty::ty_uniq(mt_a), ty::ty_rptr(r_b, mt_b)) {
let nr_b = ty::mk_uniq(self.tcx, mt_b);
self.crosspolinate(encl_node_id, a, nr_b, r_b)
self.crosspolinate(a_node_id, a, nr_b, r_b)
}
(ty::ty_evec(mt_a, vs_a),
ty::ty_evec(mt_b, ty::vstore_slice(r_b)))
if is_borrowable(vs_a) {
let nr_b = ty::mk_evec(self.tcx, mt_b, vs_a);
self.crosspolinate(encl_node_id, a, nr_b, r_b)
self.crosspolinate(a_node_id, a, nr_b, r_b)
}
_ {
self.sub_tys(a, b)
@ -825,17 +827,26 @@ impl assignment for infer_ctxt {
}
}
fn crosspolinate(encl_node_id: ast::node_id,
a: ty::t, nr_b: ty::t, r_b: ty::region) -> ures {
fn crosspolinate(a_node_id: ast::node_id,
a: ty::t,
nr_b: ty::t,
r_b: ty::region) -> ures {
#debug["crosspolinate(encl_node_id=%?, a=%s, nr_b=%s, r_b=%s)",
encl_node_id, a.to_str(self), nr_b.to_str(self),
#debug["crosspolinate(a_node_id=%?, a=%s, nr_b=%s, r_b=%s)",
a_node_id, a.to_str(self), nr_b.to_str(self),
r_b.to_str(self)];
indent {||
self.sub_tys(a, nr_b).then {||
let r_a = ty::re_scope(encl_node_id);
sub(self).contraregions(r_a, r_b).to_ures()
let a_scope_id = self.tcx.region_map.parents.get(a_node_id);
let r_a = ty::re_scope(a_scope_id);
#debug["a_scope_id=%?", a_scope_id];
sub(self).contraregions(r_a, r_b).chain {|_r|
// if successful, add an entry indicating that
// borrowing occurred
self.tcx.borrowings.insert(a_node_id, ());
uok()
}
}
}
}

View file

@ -192,12 +192,6 @@ enum ast_ty_to_ty_cache_entry {
atttce_resolved(t) /* resolved to a type, irrespective of region */
}
enum borrowing {
bo_none,
bo_box(@borrowing),
bo_uniq(@borrowing)
}
type ctxt =
@{interner: hashmap<intern_key, t_box>,
mut next_id: uint,
@ -229,7 +223,7 @@ type ctxt =
iface_method_cache: hashmap<def_id, @[method]>,
ty_param_bounds: hashmap<ast::node_id, param_bounds>,
inferred_modes: hashmap<ast::node_id, ast::mode>,
borrowings: hashmap<ast::node_id, borrowing>};
borrowings: hashmap<ast::node_id, ()>};
type t_box = @{struct: sty,
id: uint,

View file

@ -1426,15 +1426,13 @@ mod demand {
}
}
// Checks that the type `actual` can be assigned to `expected`, borrowing
// to `encl_node_id` if necessary.
fn assign(fcx: @fn_ctxt, sp: span, encl_node_id: ast::node_id,
expected: ty::t, actual: ty::t) {
alt infer::mk_assignty(fcx.infcx, encl_node_id, actual, expected) {
// Checks that the type `actual` can be assigned to `expected`.
fn assign(fcx: @fn_ctxt, sp: span, expected: ty::t, expr: @ast::expr) {
let expr_ty = fcx.expr_ty(expr);
alt infer::mk_assignty(fcx.infcx, expr.id, expr_ty, expected) {
result::ok(()) { /* ok */ }
result::err(err) {
fcx.report_mismatched_types(sp, expected, actual, err);
fcx.report_mismatched_types(sp, expected, expr_ty, err);
}
}
}
@ -2179,17 +2177,16 @@ fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity,
}
}
type unifier = fn(@fn_ctxt, span, ty::t, ty::t);
fn check_expr(fcx: @fn_ctxt, expr: @ast::expr) -> bool {
ret check_expr_with_unifier(fcx, expr, ty::mk_nil(fcx.ccx.tcx)) {
|_fcx, _span, _t1, _t2|
/* unify is a no-op */
ret check_expr_with_unifier(fcx, expr, ty::mk_nil(fcx.ccx.tcx)) {||
/* do not take any action on unify */
};
}
fn check_expr_with(fcx: @fn_ctxt, expr: @ast::expr, expected: ty::t) -> bool {
ret check_expr_with_unifier(fcx, expr, expected, demand::suptype);
ret check_expr_with_unifier(fcx, expr, expected) {||
demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr));
};
}
// determine the `self` type, using fresh variables for all variables declared
@ -2548,9 +2545,8 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
proto: ast::proto,
decl: ast::fn_decl,
body: ast::blk,
unifier: unifier,
expected: ty::t,
is_loop_body: bool) {
is_loop_body: bool,
unifier: fn()) {
let tcx = fcx.ccx.tcx;
let fty = ty::mk_fn(tcx,
ty_of_fn_decl(tcx, m_check_tyvar(fcx), proto, decl));
@ -2564,7 +2560,7 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
// typecheck the body so that we have more information about the
// argument types in the body. This is needed to make binops and
// record projection work on type inferred arguments.
unifier(fcx, expr.span, expected, fty);
unifier();
let ret_ty = ty::ty_fn_ret(fty);
let arg_tys = vec::map(ty::ty_fn_args(fty)) {|a| a.ty };
@ -2574,8 +2570,10 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
fcx.self_ty);
}
fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
expected: ty::t, unifier: unifier) -> bool {
fn check_expr_with_unifier(fcx: @fn_ctxt,
expr: @ast::expr,
expected: ty::t,
unifier: fn()) -> bool {
#debug(">> typechecking expr %d (%s)",
expr.id, syntax::print::pprust::expr_to_str(expr));
@ -2646,10 +2644,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
};
if is_block == check_blocks {
let arg_ty = arg_tys[i].ty;
bot |= check_expr_with_unifier(fcx, a, arg_ty) {
|fcx, span, expected, actual|
demand::assign(fcx, span, call_expr_id,
expected, actual);
bot |= check_expr_with_unifier(fcx, a, arg_ty) {||
demand::assign(fcx, a.span, arg_ty, a);
};
}
}
@ -3071,7 +3067,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
fcx.write_nil(id);
}
ast::expr_copy(a) {
bot = check_expr_with_unifier(fcx, a, expected, unifier);
bot = check_expr_with(fcx, a, expected);
fcx.write_ty(id, fcx.expr_ty(a));
}
ast::expr_move(lhs, rhs) {
@ -3142,7 +3138,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
}
ast::expr_fn(proto, decl, body, captures) {
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
unifier, expected, false);
false, unifier);
capture::check_capture_clause(tcx, expr.id, proto, *captures);
}
ast::expr_fn_block(decl, body) {
@ -3155,7 +3151,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
expr_to_str(expr),
ty_to_str(tcx, expected));
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
unifier, expected, false);
false, unifier);
}
ast::expr_loop_body(b) {
let rty = structurally_resolved_type(fcx, expr.span, expected);
@ -3168,8 +3164,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
};
alt check b.node {
ast::expr_fn_block(decl, body) {
check_expr_fn_with_unifier(fcx, b, proto, decl, body,
unifier, inner_ty, true);
check_expr_fn_with_unifier(fcx, b, proto, decl, body, true) {||
demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
}
}
}
let block_ty = structurally_resolved_type(
@ -3517,7 +3514,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr,
ty_to_str(tcx, fcx.expr_ty(expr)),
ty_to_str(tcx, expected));
unifier(fcx, expr.span, expected, fcx.expr_ty(expr));
unifier();
#debug("<< bot=%b", bot);
ret bot;