From 378996092ec494126585d36d8984fa11c5ae4ae2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Apr 2012 14:52:11 -0700 Subject: [PATCH] store into the borrowings table --- src/rustc/middle/infer.rs | 57 +++++++++++++++++++++++--------------- src/rustc/middle/ty.rs | 8 +----- src/rustc/middle/typeck.rs | 55 +++++++++++++++++------------------- 3 files changed, 61 insertions(+), 59 deletions(-) diff --git a/src/rustc/middle/infer.rs b/src/rustc/middle/infer.rs index ec8f7e17e35..513cd524d72 100644 --- a/src/rustc/middle/infer.rs +++ b/src/rustc/middle/infer.rs @@ -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, snd: option) -> option { @@ -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, b_bnd: option) -> 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() + } } } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index c40e6f185b8..d5a3169f1b5 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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, mut next_id: uint, @@ -229,7 +223,7 @@ type ctxt = iface_method_cache: hashmap, ty_param_bounds: hashmap, inferred_modes: hashmap, - borrowings: hashmap}; + borrowings: hashmap}; type t_box = @{struct: sty, id: uint, diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 992006f4a3f..49c2b0adc38 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -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;