提交 e9ac7489 编写于 作者: N Niko Matsakis

Refactor representation of borrowing so that it is tracked by fn_ctxt and not infer

上级 e398a72c
......@@ -106,6 +106,7 @@ fn run_tests_console(opts: test_opts,
tests: ~[test_desc]) -> bool {
fn callback(event: testevent, st: console_test_state) {
debug!("callback(event=%?)", event);
match event {
te_filtered(filtered_tests) => {
st.total = vec::len(filtered_tests);
......
此差异已折叠。
......@@ -7,7 +7,7 @@ fn check_alt(fcx: @fn_ctxt,
let tcx = fcx.ccx.tcx;
let mut bot;
let pattern_ty = fcx.infcx.next_ty_var();
let pattern_ty = fcx.infcx().next_ty_var();
bot = check_expr_with(fcx, discrim, pattern_ty);
let is_lvalue = ty::expr_is_lval(fcx.ccx.method_map, discrim);
......@@ -30,7 +30,7 @@ fn check_alt(fcx: @fn_ctxt,
for arm.pats.each |p| { check_pat(pcx, p, pattern_ty);}
}
// Now typecheck the blocks.
let mut result_ty = fcx.infcx.next_ty_var();
let mut result_ty = fcx.infcx().next_ty_var();
let mut arm_non_bot = false;
for arms.each |arm| {
match arm.guard {
......@@ -128,7 +128,7 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
tcx.sess.span_fatal
(pat.span,
fmt!("mismatched types: expected enum but found `%s`",
fcx.infcx.ty_to_str(expected)));
fcx.infcx().ty_to_str(expected)));
}
}
}
......@@ -151,14 +151,15 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
check_expr_with(fcx, begin, expected);
check_expr_with(fcx, end, expected);
let b_ty =
fcx.infcx.resolve_type_vars_if_possible(fcx.expr_ty(begin));
fcx.infcx().resolve_type_vars_if_possible(fcx.expr_ty(begin));
let e_ty =
fcx.infcx.resolve_type_vars_if_possible(fcx.expr_ty(end));
fcx.infcx().resolve_type_vars_if_possible(fcx.expr_ty(end));
debug!("pat_range beginning type: %?", b_ty);
debug!("pat_range ending type: %?", e_ty);
if !require_same_types(
tcx, Some(fcx.infcx), false, pat.span, b_ty, e_ty,
|| ~"mismatched types in range") {
tcx, Some(fcx.infcx()), false, pat.span, b_ty, e_ty,
|| ~"mismatched types in range")
{
// no-op
} else if !ty::type_is_numeric(b_ty) {
tcx.sess.span_err(pat.span, ~"non-numeric type used in range");
......@@ -180,7 +181,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
// then the type of x is &M T where M is the mutability
// and T is the expected type
let region_var =
fcx.infcx.next_region_var_with_lb(
fcx.infcx().next_region_var_with_lb(
pat.span, pcx.block_region);
let mt = {ty: expected, mutbl: mutbl};
let region_ty = ty::mk_rptr(tcx, region_var, mt);
......@@ -241,7 +242,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx.sess.span_fatal
(pat.span,
fmt!("mismatched types: expected `%s` but found record",
fcx.infcx.ty_to_str(expected)));
fcx.infcx().ty_to_str(expected)));
}
};
let f_count = vec::len(fields);
......@@ -284,7 +285,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx.sess.span_fatal(pat.span,
fmt!("mismatched types: expected `%s` \
but found struct",
fcx.infcx.ty_to_str(expected)));
fcx.infcx().ty_to_str(expected)));
}
}
......@@ -299,7 +300,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx.sess.span_err(pat.span,
fmt!("mismatched types: expected `%s` but \
found `%s`",
fcx.infcx.ty_to_str(expected),
fcx.infcx().ty_to_str(expected),
name));
}
_ => {
......@@ -364,7 +365,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx.sess.span_fatal
(pat.span,
fmt!("mismatched types: expected `%s`, found tuple",
fcx.infcx.ty_to_str(expected)));
fcx.infcx().ty_to_str(expected)));
}
};
let e_count = vec::len(elts);
......@@ -392,7 +393,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx.sess.span_fatal(
pat.span,
~"mismatched types: expected `" +
fcx.infcx.ty_to_str(expected) +
fcx.infcx().ty_to_str(expected) +
~"` found box");
}
}
......@@ -407,7 +408,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
tcx.sess.span_fatal(
pat.span,
~"mismatched types: expected `" +
fcx.infcx.ty_to_str(expected) +
fcx.infcx().ty_to_str(expected) +
~"` found uniq");
}
}
......
......@@ -6,7 +6,7 @@ fn suptype(fcx: @fn_ctxt, sp: span,
expected: ty::t, actual: ty::t) {
// n.b.: order of actual, expected is reversed
match infer::mk_subty(fcx.infcx, false, sp,
match infer::mk_subty(fcx.infcx(), false, sp,
actual, expected) {
result::Ok(()) => { /* ok */ }
result::Err(ref err) => {
......@@ -18,11 +18,11 @@ fn suptype(fcx: @fn_ctxt, sp: span,
fn eqtype(fcx: @fn_ctxt, sp: span,
expected: ty::t, actual: ty::t) {
match infer::mk_eqty(fcx.infcx, false, sp, actual, expected) {
result::Ok(()) => { /* ok */ }
result::Err(ref err) => {
fcx.report_mismatched_types(sp, expected, actual, err);
}
match infer::mk_eqty(fcx.infcx(), false, sp, actual, expected) {
Ok(()) => { /* ok */ }
Err(ref err) => {
fcx.report_mismatched_types(sp, expected, actual, err);
}
}
}
......
......@@ -108,14 +108,14 @@ struct lookup {
fn method() -> Option<method_map_entry> {
debug!("method lookup(m_name=%s, self_ty=%s, %?)",
self.fcx.tcx().sess.str_of(self.m_name),
self.fcx.infcx.ty_to_str(self.self_ty),
self.fcx.infcx().ty_to_str(self.self_ty),
ty::get(self.self_ty).struct);
// Determine if there are any inherent methods we can call.
// (An inherent method is one that belongs to no trait, but is
// inherent to a class or impl.)
let optional_inherent_methods;
match get_base_type_def_id(self.fcx.infcx,
match get_base_type_def_id(self.fcx.infcx(),
self.self_expr.span,
self.self_ty) {
None => {
......@@ -438,35 +438,27 @@ fn check_type_match(impl_ty: ty::t,
// Depending on our argument, we find potential matches by
// checking subtypability, type assignability, or reference
// subtypability. Collect the matches.
let matches;
match mode {
subtyping_mode => {
matches = self.fcx.can_mk_subty(self.self_ty, impl_ty);
}
assignability_mode => {
matches = self.fcx.can_mk_assignty(self.self_expr,
self.borrow_lb,
self.self_ty,
impl_ty);
}
immutable_reference_mode => {
let region = self.fcx.infcx.next_region_var(
self.self_expr.span,
self.self_expr.id);
let tm = { ty: self.self_ty, mutbl: ast::m_imm };
let ref_ty = ty::mk_rptr(self.tcx(), region, tm);
matches = self.fcx.can_mk_subty(ref_ty, impl_ty);
}
mutable_reference_mode => {
let region = self.fcx.infcx.next_region_var(
self.self_expr.span,
self.self_expr.id);
let tm = { ty: self.self_ty, mutbl: ast::m_mutbl };
let ref_ty = ty::mk_rptr(self.tcx(), region, tm);
matches = self.fcx.can_mk_subty(ref_ty, impl_ty);
}
subtyping_mode => self.fcx.can_mk_subty(self.self_ty, impl_ty),
assignability_mode => self.fcx.can_mk_assignty(self.self_ty,
impl_ty),
immutable_reference_mode => {
let region = self.fcx.infcx().next_region_var(
self.self_expr.span,
self.self_expr.id);
let tm = { ty: self.self_ty, mutbl: ast::m_imm };
let ref_ty = ty::mk_rptr(self.tcx(), region, tm);
self.fcx.can_mk_subty(ref_ty, impl_ty)
}
mutable_reference_mode => {
let region = self.fcx.infcx().next_region_var(
self.self_expr.span,
self.self_expr.id);
let tm = { ty: self.self_ty, mutbl: ast::m_mutbl };
let ref_ty = ty::mk_rptr(self.tcx(), region, tm);
self.fcx.can_mk_subty(ref_ty, impl_ty)
}
}
matches
}
// Returns true if any were added and false otherwise.
......@@ -530,7 +522,7 @@ fn add_candidates_from_m(inner_ty: ty::t,
None => {
match m.self_ty {
ast::sty_region(_) =>
Some(self.fcx.infcx.next_region_var(
Some(self.fcx.infcx().next_region_var(
self.self_expr.span,
self.self_expr.id)),
_ => None
......@@ -640,7 +632,7 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
debug!("write_mty_from_candidate(n_tps_m=%u, fty=%s, entry=%?)",
cand.n_tps_m,
self.fcx.infcx.ty_to_str(cand.fty),
self.fcx.infcx().ty_to_str(cand.fty),
cand.entry);
match cand.mode {
......@@ -655,30 +647,18 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
self.tcx().sess.span_bug(
self.expr.span,
fmt!("%s was assignable to %s but now is not?",
self.fcx.infcx.ty_to_str(cand.self_ty),
self.fcx.infcx.ty_to_str(cand.rcvr_ty)));
self.fcx.infcx().ty_to_str(cand.self_ty),
self.fcx.infcx().ty_to_str(cand.rcvr_ty)));
}
}
}
immutable_reference_mode => {
// Borrow as an immutable reference.
let region_var = self.fcx.infcx.next_region_var(
self.self_expr.span,
self.self_expr.id);
self.fcx.infcx.borrowings.push({expr_id: self.self_expr.id,
span: self.self_expr.span,
scope: region_var,
mutbl: ast::m_imm});
self.add_borrow(ast::m_imm);
}
mutable_reference_mode => {
// Borrow as a mutable reference.
let region_var = self.fcx.infcx.next_region_var(
self.self_expr.span,
self.self_expr.id);
self.fcx.infcx.borrowings.push({expr_id: self.self_expr.id,
span: self.self_expr.span,
scope: region_var,
mutbl: ast::m_mutbl});
self.add_borrow(ast::m_mutbl);
}
}
......@@ -688,18 +668,18 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
let n_tps_m = cand.n_tps_m;
let m_substs = {
if n_tps_supplied == 0u {
self.fcx.infcx.next_ty_vars(n_tps_m)
self.fcx.infcx().next_ty_vars(n_tps_m)
} else if n_tps_m == 0u {
tcx.sess.span_err(
self.expr.span,
~"this method does not take type parameters");
self.fcx.infcx.next_ty_vars(n_tps_m)
self.fcx.infcx().next_ty_vars(n_tps_m)
} else if n_tps_supplied != n_tps_m {
tcx.sess.span_err(
self.expr.span,
~"incorrect number of type \
parameters given for this method");
self.fcx.infcx.next_ty_vars(n_tps_m)
self.fcx.infcx().next_ty_vars(n_tps_m)
} else {
self.supplied_tps
}
......@@ -712,5 +692,13 @@ fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
return cand.entry;
}
fn add_borrow(mutbl: ast::mutability) {
let region_var = self.fcx.infcx().next_region_var(
self.self_expr.span,
self.self_expr.id);
self.fcx.inh.borrowings.insert(self.self_expr.id, {region: region_var,
mutbl: mutbl});
}
}
......@@ -81,7 +81,7 @@ impl @rcx {
/// that `<R0>` be bigger than the let and the `*b` expression, so we
/// will effectively resolve `<R0>` to be the block B.
fn resolve_type(unresolved_ty: ty::t) -> fres<ty::t> {
resolve_type(self.fcx.infcx, unresolved_ty,
resolve_type(self.fcx.infcx(), unresolved_ty,
resolve_and_force_all_but_regions)
}
......@@ -95,7 +95,7 @@ fn regionck_expr(fcx: @fn_ctxt, e: @ast::expr) {
let rcx = rcx_({fcx:fcx, mut errors_reported: 0u});
let v = regionck_visitor();
v.visit_expr(e, @rcx, v);
fcx.infcx.resolve_regions();
fcx.infcx().resolve_regions();
}
fn regionck_fn(fcx: @fn_ctxt,
......@@ -104,7 +104,7 @@ fn regionck_fn(fcx: @fn_ctxt,
let rcx = rcx_({fcx:fcx, mut errors_reported: 0u});
let v = regionck_visitor();
v.visit_block(blk, @rcx, v);
fcx.infcx.resolve_regions();
fcx.infcx().resolve_regions();
}
fn regionck_visitor() -> rvt {
......
......@@ -3,6 +3,7 @@
fixup_err_to_str};
import ast_util::new_def_hash;
import syntax::print::pprust;
import result::{Result, Ok, Err};
// vtable resolution looks for places where trait bounds are
// subsituted in and figures out which vtable is used. There is some
......@@ -85,7 +86,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
{
debug!("lookup_vtable(ty=%s, trait_ty=%s)",
fcx.infcx.ty_to_str(ty), fcx.infcx.ty_to_str(trait_ty));
fcx.infcx().ty_to_str(ty), fcx.inh.infcx.ty_to_str(trait_ty));
let _i = indenter();
let tcx = fcx.ccx.tcx;
......@@ -253,8 +254,8 @@ impl<T> self_ty<T>: some_trait<T> { ... }
debug!("(checking vtable) @2 relating trait ty %s to \
of_ty %s",
fcx.infcx.ty_to_str(trait_ty),
fcx.infcx.ty_to_str(of_ty));
fcx.infcx().ty_to_str(trait_ty),
fcx.infcx().ty_to_str(of_ty));
let of_ty = ty::subst(tcx, &substs, of_ty);
relate_trait_tys(fcx, expr, trait_ty, of_ty);
......@@ -347,18 +348,18 @@ fn fixup_ty(fcx: @fn_ctxt,
is_early: bool) -> Option<ty::t>
{
let tcx = fcx.ccx.tcx;
match resolve_type(fcx.infcx, ty, resolve_and_force_all_but_regions) {
result::Ok(new_type) => Some(new_type),
result::Err(e) if !is_early => {
tcx.sess.span_fatal(
expr.span,
fmt!("cannot determine a type \
for this bounded type parameter: %s",
fixup_err_to_str(e)))
}
result::Err(_) => {
None
}
match resolve_type(fcx.infcx(), ty, resolve_and_force_all_but_regions) {
Ok(new_type) => Some(new_type),
Err(e) if !is_early => {
tcx.sess.span_fatal(
expr.span,
fmt!("cannot determine a type \
for this bounded type parameter: %s",
fixup_err_to_str(e)))
}
Err(_) => {
None
}
}
}
......
......@@ -3,30 +3,58 @@
// substitutions.
import check::{fn_ctxt, lookup_local};
import infer::{resolve_type, resolve_all, force_all};
import infer::{resolve_type, resolve_region, resolve_all, force_all};
export resolve_type_vars_in_fn;
export resolve_type_vars_in_expr;
import result::{Result, Ok, Err};
fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t) ->
Option<ty::t> {
fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t)
-> Option<ty::t>
{
if !ty::type_needs_infer(typ) { return Some(typ); }
match resolve_type(fcx.infcx, typ, resolve_all | force_all) {
result::Ok(new_type) => return Some(new_type),
result::Err(e) => {
if !fcx.ccx.tcx.sess.has_errors() {
fcx.ccx.tcx.sess.span_err(
sp,
fmt!("cannot determine a type \
for this expression: %s",
infer::fixup_err_to_str(e)))
match resolve_type(fcx.infcx(), typ, resolve_all | force_all) {
Ok(new_type) => return Some(new_type),
Err(e) => {
if !fcx.ccx.tcx.sess.has_errors() {
fcx.ccx.tcx.sess.span_err(
sp,
fmt!("cannot determine a type \
for this expression: %s",
infer::fixup_err_to_str(e)))
}
return None;
}
return None;
}
}
}
fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id)
-> Option<ty::t> {
-> Option<ty::t>
{
let fcx = wbcx.fcx, tcx = fcx.ccx.tcx;
// Resolve any borrowings for the node with id `id`
match fcx.inh.borrowings.find(id) {
None => (),
Some(borrow) => {
match resolve_region(fcx.infcx(), borrow.region,
resolve_all | force_all) {
Err(e) => {
// This should not, I think, happen.
fcx.ccx.tcx.sess.span_err(
sp, fmt!("cannot resolve scope of borrow: %s",
infer::fixup_err_to_str(e)));
}
Ok(r) => {
debug!("Borrowing node %d -> region %?, mutbl %?",
id, r, borrow.mutbl);
fcx.tcx().borrowings.insert(id, {region: r,
mutbl: borrow.mutbl});
}
}
}
}
// Resolve the type of the node with id `id`
let n_ty = fcx.node_ty(id);
match resolve_type_vars_in_type(fcx, sp, n_ty) {
None => {
......@@ -58,8 +86,9 @@ fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id)
fn maybe_resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span,
id: ast::node_id)
-> Option<ty::t> {
if wbcx.fcx.node_types.contains_key(id) {
-> Option<ty::t>
{
if wbcx.fcx.inh.node_types.contains_key(id) {
resolve_type_vars_for_node(wbcx, sp, id)
} else {
None
......@@ -118,7 +147,7 @@ fn visit_pat(p: @ast::pat, wbcx: wb_ctxt, v: wb_vt) {
resolve_type_vars_for_node(wbcx, p.span, p.id);
debug!("Type for pattern binding %s (id %d) resolved to %s",
pat_to_str(p, wbcx.fcx.ccx.tcx.sess.intr()), p.id,
wbcx.fcx.infcx.ty_to_str(
wbcx.fcx.infcx().ty_to_str(
ty::node_id_to_type(wbcx.fcx.ccx.tcx,
p.id)));
visit::visit_pat(p, wbcx, v);
......@@ -127,21 +156,22 @@ fn visit_local(l: @ast::local, wbcx: wb_ctxt, v: wb_vt) {
if !wbcx.success { return; }
let var_id = lookup_local(wbcx.fcx, l.span, l.node.id);
let var_ty = ty::mk_var(wbcx.fcx.tcx(), var_id);
match resolve_type(wbcx.fcx.infcx, var_ty, resolve_all | force_all) {
result::Ok(lty) => {
debug!("Type for local %s (id %d) resolved to %s",
pat_to_str(l.node.pat, wbcx.fcx.ccx.tcx.sess.intr()),l.node.id,
wbcx.fcx.infcx.ty_to_str(lty));
write_ty_to_tcx(wbcx.fcx.ccx.tcx, l.node.id, lty);
}
result::Err(e) => {
wbcx.fcx.ccx.tcx.sess.span_err(
l.span,
fmt!("cannot determine a type \
for this local variable: %s",
infer::fixup_err_to_str(e)));
wbcx.success = false;
}
match resolve_type(wbcx.fcx.infcx(), var_ty, resolve_all | force_all) {
Ok(lty) => {
debug!("Type for local %s (id %d) resolved to %s",
pat_to_str(l.node.pat, wbcx.fcx.tcx().sess.intr()),
l.node.id,
wbcx.fcx.infcx().ty_to_str(lty));
write_ty_to_tcx(wbcx.fcx.ccx.tcx, l.node.id, lty);
}
Err(e) => {
wbcx.fcx.ccx.tcx.sess.span_err(
l.span,
fmt!("cannot determine a type \
for this local variable: %s",
infer::fixup_err_to_str(e)));
wbcx.success = false;
}
}
visit::visit_local(l, wbcx, v);
}
......@@ -163,9 +193,6 @@ fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool {
let wbcx = {fcx: fcx, mut success: true};
let visit = mk_visitor();
visit.visit_expr(e, wbcx, visit);
if wbcx.success {
infer::resolve_borrowings(fcx.infcx);
}
return wbcx.success;
}
......@@ -184,8 +211,5 @@ fn resolve_type_vars_in_fn(fcx: @fn_ctxt,
for decl.inputs.each |arg| {
resolve_type_vars_for_node(wbcx, arg.ty.span, arg.id);
}
if wbcx.success {
infer::resolve_borrowings(fcx.infcx);
}
return wbcx.success;
}
......@@ -273,6 +273,7 @@ fn bar() {
import unify::{vals_and_bindings, root};
import integral::{int_ty_set, int_ty_set_all};
import combine::{combine_fields, eq_tys};
import assignment::Assign;
import sub::Sub;
import lub::Lub;
......@@ -296,20 +297,13 @@ fn bar() {
export root, to_str;
export int_ty_set_all;
// Extra information needed to perform an assignment that may borrow.
// The `expr_id` and `span` are the id/span of the expression
// whose type is being assigned, and `borrow_scope` is the region
// scope to use if the value should be borrowed.
type assignment = {
expr_id: ast::node_id,
span: span,
borrow_lb: ast::node_id,
};
type bound<T:copy> = Option<T>;
type bounds<T:copy> = {lb: bound<T>, ub: bound<T>};
type cres<T> = Result<T,ty::type_err>;
type cres<T> = Result<T,ty::type_err>; // "combine result"
type ures = cres<()>; // "unify result"
type fres<T> = Result<T, fixup_err>; // "fixup result"
type ares = cres<Option<ty::borrow>>; // "assignment result"
enum infer_ctxt = @{
tcx: ty::ctxt,
......@@ -329,12 +323,7 @@ enum infer_ctxt = @{
// For keeping track of existing type and region variables.
ty_var_counter: @mut uint,
ty_var_integral_counter: @mut uint,
region_var_counter: @mut uint,
borrowings: DVec<{expr_id: ast::node_id,
span: span,
scope: ty::region,
mutbl: ast::mutability}>
region_var_counter: @mut uint
};
enum fixup_err {
......@@ -358,9 +347,6 @@ fn fixup_err_to_str(f: fixup_err) -> ~str {
}
}
type ures = result::Result<(), ty::type_err>;
type fres<T> = result::Result<T, fixup_err>;
fn new_vals_and_bindings<V:copy, T:copy>() -> vals_and_bindings<V, T> {
vals_and_bindings {
vals: smallintmap::mk(),
......@@ -375,19 +361,14 @@ fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
region_vars: RegionVarBindings(tcx),
ty_var_counter: @mut 0u,
ty_var_integral_counter: @mut 0u,
region_var_counter: @mut 0u,
borrowings: DVec()})}
fn mk_sub(cx: infer_ctxt, a_is_expected: bool, span: span) -> Sub {
Sub(combine_fields {infcx: cx, a_is_expected: a_is_expected, span: span})
}
region_var_counter: @mut 0u})}
fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span,
a: ty::t, b: ty::t) -> ures {
debug!("mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx));
do indent {
do cx.commit {
mk_sub(cx, a_is_expected, span).tys(a, b)
cx.sub(a_is_expected, span).tys(a, b)
}
}.to_ures()
}
......@@ -396,7 +377,7 @@ fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
debug!("can_mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx));
do indent {
do cx.probe {
mk_sub(cx, true, ast_util::dummy_sp()).tys(a, b)
cx.sub(true, ast_util::dummy_sp()).tys(a, b)
}
}.to_ures()
}
......@@ -406,7 +387,7 @@ fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span,
debug!("mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx));
do indent {
do cx.commit {
mk_sub(cx, a_is_expected, span).regions(a, b)
cx.sub(a_is_expected, span).regions(a, b)
}
}.to_ures()
}
......@@ -416,37 +397,30 @@ fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span,
debug!("mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx));
do indent {
do cx.commit {
let suber = mk_sub(cx, a_is_expected, span);
let suber = cx.sub(a_is_expected, span);
eq_tys(&suber, a, b)
}
}.to_ures()
}
fn mk_assignty(cx: infer_ctxt, anmnt: &assignment,
a: ty::t, b: ty::t) -> ures {
debug!("mk_assignty(%? / %s <: %s)",
anmnt, a.to_str(cx), b.to_str(cx));
fn mk_assignty(cx: infer_ctxt, a_is_expected: bool, span: span,
a: ty::t, b: ty::t) -> ares {
debug!("mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx));
do indent {
do cx.commit {
cx.assign_tys(anmnt, a, b)
Assign(cx.combine_fields(a_is_expected, span)).tys(a, b)
}
}.to_ures()
}
}
fn can_mk_assignty(cx: infer_ctxt, anmnt: &assignment,
a: ty::t, b: ty::t) -> ures {
debug!("can_mk_assignty(%? / %s <: %s)",
anmnt, a.to_str(cx), b.to_str(cx));
// FIXME(#2593)---this will not unroll any entries we make in the
// borrowings table. But this is OK for the moment because this
// is only used in method lookup, and there must be exactly one
// match or an error is reported. Still, it should be fixed. (#2593)
// NDM OUTDATED
indent(|| cx.probe(||
cx.assign_tys(anmnt, a, b)
) ).to_ures()
fn can_mk_assignty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
debug!("can_mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx));
do indent {
do cx.probe {
let span = ast_util::dummy_sp();
Assign(cx.combine_fields(true, span)).tys(a, b)
}
}.to_ures()
}
// See comment on the type `resolve_state` below
......@@ -460,6 +434,7 @@ fn resolve_region(cx: infer_ctxt, r: ty::region, modes: uint)
resolver(cx, modes).resolve_region_chk(r)
}
/*
fn resolve_borrowings(cx: infer_ctxt) {
for cx.borrowings.each |item| {
match resolve_region(cx, item.scope, resolve_all|force_all) {
......@@ -479,6 +454,7 @@ fn resolve_borrowings(cx: infer_ctxt) {
}
}
}
*/
trait then {
fn then<T:copy>(f: fn() -> Result<T,ty::type_err>)
......@@ -533,10 +509,20 @@ struct Snapshot {
ty_var_bindings_len: uint;
ty_var_integral_bindings_len: uint;
region_vars_snapshot: uint;
borrowings_len: uint;
}
impl infer_ctxt {
fn combine_fields(a_is_expected: bool,
span: span) -> combine_fields {
combine_fields {infcx: self,
a_is_expected: a_is_expected,
span: span}
}
fn sub(a_is_expected: bool, span: span) -> Sub {
Sub(self.combine_fields(a_is_expected, span))
}
fn in_snapshot() -> bool {
self.region_vars.in_snapshot()
}
......@@ -549,8 +535,6 @@ fn start_snapshot() -> Snapshot {
self.ty_var_integral_bindings.bindings.len(),
region_vars_snapshot:
self.region_vars.start_snapshot(),
borrowings_len:
self.borrowings.len()
}
}
......@@ -564,9 +548,6 @@ fn rollback_to(snapshot: &Snapshot) {
self.region_vars.rollback_to(
snapshot.region_vars_snapshot);
while self.borrowings.len() != snapshot.borrowings_len {
self.borrowings.pop();
}
}
/// Execute `f` and commit the bindings if successful
......
......@@ -49,70 +49,74 @@
// needed.
import to_str::to_str;
import combine::combine_fields;
impl infer_ctxt {
fn assign_tys(anmnt: &assignment, a: ty::t, b: ty::t) -> ures {
fn to_ares(+c: cres<ty::t>) -> ares {
match c {
Ok(_) => Ok(None),
Err(e) => Err(e)
}
}
fn select(fst: Option<ty::t>, snd: Option<ty::t>) -> Option<ty::t> {
match fst {
Some(t) => Some(t),
None => match snd {
Some(t) => Some(t),
None => None
}
}
}
// Note: Assign is not actually a combiner, in that it does not
// conform to the same interface, though it performs a similar
// function.
enum Assign = combine_fields;
debug!("assign_tys(anmnt=%?, %s -> %s)",
anmnt, a.to_str(self), b.to_str(self));
impl Assign {
fn tys(a: ty::t, b: ty::t) -> ares {
debug!("Assign.tys(%s -> %s)",
a.to_str(self.infcx),
b.to_str(self.infcx));
let _r = indenter();
match (ty::get(a).struct, ty::get(b).struct) {
(ty::ty_bot, _) => {
uok()
}
(ty::ty_var(a_id), ty::ty_var(b_id)) => {
let nde_a = self.get(&self.ty_var_bindings, a_id);
let nde_b = self.get(&self.ty_var_bindings, b_id);
let a_bounds = nde_a.possible_types;
let b_bounds = nde_b.possible_types;
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(anmnt, a, b, a_bnd, b_bnd)
}
(ty::ty_var(a_id), _) => {
let nde_a = self.get(&self.ty_var_bindings, a_id);
let a_bounds = nde_a.possible_types;
let a_bnd = select(a_bounds.ub, a_bounds.lb);
self.assign_tys_or_sub(anmnt, a, b, a_bnd, Some(b))
}
(_, ty::ty_var(b_id)) => {
let nde_b = self.get(&self.ty_var_bindings, b_id);
let b_bounds = nde_b.possible_types;
let b_bnd = select(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(anmnt, a, b, Some(a), b_bnd)
}
(_, _) => {
self.assign_tys_or_sub(anmnt, a, b, Some(a), Some(b))
}
(ty::ty_bot, _) => {
Ok(None)
}
(ty::ty_var(a_id), ty::ty_var(b_id)) => {
let nde_a = self.infcx.get(&self.infcx.ty_var_bindings, a_id);
let nde_b = self.infcx.get(&self.infcx.ty_var_bindings, b_id);
let a_bounds = nde_a.possible_types;
let b_bounds = nde_b.possible_types;
let a_bnd = option::or(a_bounds.ub, a_bounds.lb);
let b_bnd = option::or(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(a, b, a_bnd, b_bnd)
}
(ty::ty_var(a_id), _) => {
let nde_a = self.infcx.get(&self.infcx.ty_var_bindings, a_id);
let a_bounds = nde_a.possible_types;
let a_bnd = option::or(a_bounds.ub, a_bounds.lb);
self.assign_tys_or_sub(a, b, a_bnd, Some(b))
}
(_, ty::ty_var(b_id)) => {
let nde_b = self.infcx.get(&self.infcx.ty_var_bindings, b_id);
let b_bounds = nde_b.possible_types;
let b_bnd = option::or(b_bounds.lb, b_bounds.ub);
self.assign_tys_or_sub(a, b, Some(a), b_bnd)
}
(_, _) => {
self.assign_tys_or_sub(a, b, Some(a), Some(b))
}
}
}
}
priv impl Assign {
fn assign_tys_or_sub(
anmnt: &assignment,
a: ty::t, b: ty::t,
+a_bnd: Option<ty::t>, +b_bnd: Option<ty::t>) -> ures {
+a_bnd: Option<ty::t>, +b_bnd: Option<ty::t>) -> ares {
debug!("assign_tys_or_sub(anmnt=%?, %s -> %s, %s -> %s)",
anmnt, a.to_str(self), b.to_str(self),
a_bnd.to_str(self), b_bnd.to_str(self));
debug!("Assign.assign_tys_or_sub(%s -> %s, %s -> %s)",
a.to_str(self.infcx), b.to_str(self.infcx),
a_bnd.to_str(self.infcx), b_bnd.to_str(self.infcx));
let _r = indenter();
fn is_borrowable(v: ty::vstore) -> bool {
......@@ -123,73 +127,73 @@ fn is_borrowable(v: ty::vstore) -> bool {
}
match (a_bnd, b_bnd) {
(Some(a_bnd), Some(b_bnd)) => {
match (ty::get(a_bnd).struct, ty::get(b_bnd).struct) {
(ty::ty_box(*), ty::ty_rptr(r_b, mt_b)) => {
let nr_b = ty::mk_box(self.tcx, {ty: mt_b.ty,
mutbl: m_const});
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
}
(ty::ty_uniq(*), ty::ty_rptr(r_b, mt_b)) => {
let nr_b = ty::mk_uniq(self.tcx, {ty: mt_b.ty,
mutbl: m_const});
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
}
(ty::ty_estr(vs_a),
ty::ty_estr(ty::vstore_slice(r_b)))
if is_borrowable(vs_a) => {
let nr_b = ty::mk_estr(self.tcx, vs_a);
self.crosspollinate(anmnt, a, nr_b, m_imm, r_b)
}
(ty::ty_evec(_, 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, {ty: mt_b.ty,
mutbl: m_const}, vs_a);
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
}
_ => {
mk_sub(self, false, anmnt.span).tys(a, b).to_ures()
}
(Some(a_bnd), Some(b_bnd)) => {
// check for a case where a non-region pointer (@, ~) is
// being assigned to a region pointer:
match (ty::get(a_bnd).struct, ty::get(b_bnd).struct) {
(ty::ty_box(_), ty::ty_rptr(r_b, mt_b)) => {
let nr_b = ty::mk_box(self.infcx.tcx,
{ty: mt_b.ty, mutbl: m_const});
self.try_assign(a, nr_b, mt_b.mutbl, r_b)
}
(ty::ty_uniq(_), ty::ty_rptr(r_b, mt_b)) => {
let nr_b = ty::mk_uniq(self.infcx.tcx,
{ty: mt_b.ty, mutbl: m_const});
self.try_assign(a, nr_b, mt_b.mutbl, r_b)
}
(ty::ty_estr(vs_a),
ty::ty_estr(ty::vstore_slice(r_b)))
if is_borrowable(vs_a) => {
let nr_b = ty::mk_estr(self.infcx.tcx, vs_a);
self.try_assign(a, nr_b, m_imm, r_b)
}
(ty::ty_evec(_, vs_a),
ty::ty_evec(mt_b, ty::vstore_slice(r_b)))
if is_borrowable(vs_a) => {
let nr_b = ty::mk_evec(self.infcx.tcx,
{ty: mt_b.ty, mutbl: m_const},
vs_a);
self.try_assign(a, nr_b, mt_b.mutbl, r_b)
}
_ => {
// otherwise, assignment follows normal subtype rules:
to_ares(Sub(*self).tys(a, b))
}
}
}
_ => {
// if insufficient bounds were available, just follow
// normal subtype rules:
to_ares(Sub(*self).tys(a, b))
}
}
_ => {
mk_sub(self, false, anmnt.span).tys(a, b).to_ures()
}
}
}
fn crosspollinate(anmnt: &assignment,
a: ty::t,
nr_b: ty::t,
m: ast::mutability,
r_b: ty::region) -> ures {
debug!("crosspollinate(anmnt=%?, a=%s, nr_b=%s, r_b=%s)",
anmnt, a.to_str(self), nr_b.to_str(self),
r_b.to_str(self));
/// Given an assignment from a type like `@a` to `&r_b/m nr_b`,
/// this function checks that `a <: nr_b`. In that case, the
/// assignment is permitted, so it constructs a fresh region
/// variable `r_a >= r_b` and returns a corresponding assignment
/// record. See the discussion at the top of this file for more
/// details.
fn try_assign(a: ty::t,
nr_b: ty::t,
m: ast::mutability,
r_b: ty::region) -> ares {
debug!("try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)",
a.to_str(self.infcx),
nr_b.to_str(self.infcx),
m,
r_b.to_str(self.infcx));
do indent {
let sub = mk_sub(self, false, anmnt.span);
let sub = Sub(*self);
do sub.tys(a, nr_b).chain |_t| {
// Create a fresh region variable `r_a` with the given
// borrow bounds:
let r_a = self.next_region_var(anmnt.span,
anmnt.borrow_lb);
debug!("anmnt=%?", anmnt);
let r_a = self.infcx.next_region_var_nb(self.span);
do sub.contraregions(r_a, r_b).chain |_r| {
// if successful, add an entry indicating that
// borrowing occurred
debug!("borrowing expression #%?, scope=%?, m=%?",
anmnt, r_a, m);
self.borrowings.push({expr_id: anmnt.expr_id,
span: anmnt.span,
scope: r_a,
mutbl: m});
uok()
Ok(Some({region: r_a, mutbl: m}))
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册