store into the borrowings table
This commit is contained in:
parent
4d73185f3e
commit
378996092e
3 changed files with 61 additions and 59 deletions
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue