mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +00:00
rewrite the resolution infrastructure; but it's still grody
This commit is contained in:
parent
68f8812511
commit
0d3658bb43
@ -142,7 +142,9 @@ checking for overflow:
|
||||
assert incd == [2u, 3u, 4u];
|
||||
}
|
||||
"]
|
||||
fn map<T,U:copy,V:copy>(ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
|
||||
fn map<T,U:copy,V:copy>(
|
||||
ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
|
||||
|
||||
let mut vs: [V] = [];
|
||||
vec::reserve(vs, vec::len(ts));
|
||||
for vec::each(ts) {|t|
|
||||
@ -154,6 +156,20 @@ fn map<T,U:copy,V:copy>(ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
|
||||
ret ok(vs);
|
||||
}
|
||||
|
||||
fn map_opt<T,U:copy,V:copy>(
|
||||
o_t: option<T>, op: fn(T) -> result<V,U>) -> result<option<V>,U> {
|
||||
|
||||
alt o_t {
|
||||
none { ok(none) }
|
||||
some(t) {
|
||||
alt op(t) {
|
||||
ok(v) { ok(some(v)) }
|
||||
err(e) { err(e) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = "Same as map, but it operates over two parallel vectors.
|
||||
|
||||
A precondition is used here to ensure that the vectors are the same
|
||||
|
@ -17,9 +17,9 @@ export new_infer_ctxt;
|
||||
export mk_subty;
|
||||
export mk_eqty;
|
||||
export mk_assignty;
|
||||
export resolve_type_structure;
|
||||
export fixup_vars;
|
||||
export resolve_var;
|
||||
export resolve_shallow;
|
||||
export resolve_deep;
|
||||
export resolve_deep_var;
|
||||
export compare_tys;
|
||||
export fixup_err, fixup_err_to_str;
|
||||
|
||||
@ -92,16 +92,23 @@ fn compare_tys(tcx: ty::ctxt, a: ty::t, b: ty::t) -> ures {
|
||||
mk_eqty(infcx, a, b)
|
||||
}
|
||||
|
||||
fn resolve_type_structure(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
|
||||
cx.resolve_ty(a)
|
||||
// Resolves one level of type structure but not any type variables
|
||||
// that may be nested within.
|
||||
fn resolve_shallow(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
|
||||
resolver(cx, false, false).resolve(a)
|
||||
}
|
||||
|
||||
fn resolve_var(cx: infer_ctxt, vid: ty_vid) -> fres<ty::t> {
|
||||
cx.fixup_ty(ty::mk_var(cx.tcx, vid))
|
||||
// see resolve_deep()
|
||||
fn resolve_deep_var(cx: infer_ctxt, vid: ty_vid,
|
||||
force_vars: bool) -> fres<ty::t> {
|
||||
resolver(cx, true, force_vars).resolve(ty::mk_var(cx.tcx, vid))
|
||||
}
|
||||
|
||||
fn fixup_vars(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
|
||||
cx.fixup_ty(a)
|
||||
// Resolves all levels of type structure. If `force_vars` is true,
|
||||
// then we will resolve unconstrained type/region variables to
|
||||
// something arbitrary. Otherwise, we preserve them as variables.
|
||||
fn resolve_deep(cx: infer_ctxt, a: ty::t, force_vars: bool) -> fres<ty::t> {
|
||||
resolver(cx, true, force_vars).resolve(a)
|
||||
}
|
||||
|
||||
impl methods for ures {
|
||||
@ -555,25 +562,137 @@ impl unify_methods for infer_ctxt {
|
||||
}
|
||||
}
|
||||
|
||||
impl resolve_methods for infer_ctxt {
|
||||
fn rok(t: ty::t) -> fres<ty::t> {
|
||||
#debug["Resolve OK: %s", t.to_str(self)];
|
||||
ok(t)
|
||||
// Resolution is the process of removing type variables and replacing
|
||||
// them with their inferred values. There are several "modes" for
|
||||
// resolution. The first is a shallow resolution: this only resolves
|
||||
// one layer, but does not resolve any nested variables. So, for
|
||||
// example, if we have two variables A and B, and the constraint that
|
||||
// A <: [B] and B <: int, then shallow resolution on A would yield
|
||||
// [B]. Deep resolution, on the other hand, would yield [int].
|
||||
//
|
||||
// But there is one more knob: the force_vars variable controls the
|
||||
// behavior in the face of unconstrained variables. If we have A, B
|
||||
// and only the constraint that A <: B, then the result is [_|_] if
|
||||
// force_vars is true and [B] otherwise. We use force_vars == true
|
||||
// when resolving types after typeck, but false otherwise (for
|
||||
// example, when pretty-printing them for errors).
|
||||
|
||||
type resolve_state = @{
|
||||
infcx: infer_ctxt,
|
||||
deep: bool,
|
||||
force_vars: bool,
|
||||
mut err: option<fixup_err>,
|
||||
mut r_seen: [region_vid],
|
||||
mut v_seen: [ty_vid]
|
||||
};
|
||||
|
||||
fn resolver(infcx: infer_ctxt, deep: bool, fvars: bool) -> resolve_state {
|
||||
@{infcx: infcx,
|
||||
deep: deep,
|
||||
force_vars: fvars,
|
||||
mut err: none,
|
||||
mut r_seen: [],
|
||||
mut v_seen: []}
|
||||
}
|
||||
|
||||
impl methods for resolve_state {
|
||||
fn resolve(typ: ty::t) -> fres<ty::t> {
|
||||
self.err = none;
|
||||
|
||||
// n.b. This is a hokey mess because the current fold doesn't
|
||||
// allow us to pass back errors in any useful way.
|
||||
|
||||
assert vec::is_empty(self.v_seen) && vec::is_empty(self.r_seen);
|
||||
let rty = self.resolve1(typ);
|
||||
assert vec::is_empty(self.v_seen) && vec::is_empty(self.r_seen);
|
||||
alt self.err {
|
||||
none {
|
||||
#debug["Resolved %s to %s (deep=%b, force_vars=%b)",
|
||||
ty_to_str(self.infcx.tcx, typ),
|
||||
ty_to_str(self.infcx.tcx, rty),
|
||||
self.deep,
|
||||
self.force_vars];
|
||||
ret ok(rty);
|
||||
}
|
||||
some(e) { ret err(e); }
|
||||
}
|
||||
}
|
||||
|
||||
fn rerr<T>(v: fixup_err) -> fres<T> {
|
||||
#debug["Resolve error: %?", v];
|
||||
err(v)
|
||||
fn resolve1(typ: ty::t) -> ty::t {
|
||||
let tb = ty::get(typ);
|
||||
alt tb.struct {
|
||||
ty::ty_var(vid) { self.resolve_ty_var(vid) }
|
||||
_ if !tb.has_regions && !self.deep { typ }
|
||||
_ {
|
||||
ty::fold_regions_and_ty(
|
||||
self.infcx.tcx, typ,
|
||||
{ |r| self.resolve_region(r) },
|
||||
{ |t| self.resolve_if_deep(t) },
|
||||
{ |t| self.resolve_if_deep(t) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_if_deep(typ: ty::t) -> ty::t {
|
||||
if !self.deep {typ} else {self.resolve1(typ)}
|
||||
}
|
||||
|
||||
fn resolve_region(orig: ty::region) -> ty::region {
|
||||
alt orig {
|
||||
ty::re_var(rid) { self.resolve_region_var(rid) }
|
||||
_ { orig }
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_region_var(rid: region_vid) -> ty::region {
|
||||
if vec::contains(self.r_seen, rid) {
|
||||
self.err = some(cyclic_region(rid));
|
||||
ret ty::re_var(rid);
|
||||
} else {
|
||||
vec::push(self.r_seen, rid);
|
||||
let r = self.resolve_var(
|
||||
self.infcx.rb,
|
||||
{|_t| false },
|
||||
rid,
|
||||
{||
|
||||
if self.force_vars {ty::re_static}
|
||||
else {ty::re_var(rid)}
|
||||
});
|
||||
vec::pop(self.r_seen);
|
||||
ret r;
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_ty_var(vid: ty_vid) -> ty::t {
|
||||
if vec::contains(self.v_seen, vid) {
|
||||
self.err = some(cyclic_ty(vid));
|
||||
ret ty::mk_var(self.infcx.tcx, vid);
|
||||
} else {
|
||||
vec::push(self.v_seen, vid);
|
||||
let tcx = self.infcx.tcx;
|
||||
let t0 = self.resolve_var(
|
||||
self.infcx.vb,
|
||||
{|t| type_is_bot(t) },
|
||||
vid,
|
||||
{||
|
||||
if self.force_vars {ty::mk_bot(tcx)}
|
||||
else {ty::mk_var(tcx, vid)}
|
||||
});
|
||||
let t1 = self.resolve1(t0);
|
||||
vec::pop(self.v_seen);
|
||||
ret t1;
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_var<V: copy vid, T:copy to_str>(
|
||||
vb: vals_and_bindings<V, T>, bot_guard: fn(T)->bool,
|
||||
vid: V, unbound: fn() -> fres<T>) -> fres<T> {
|
||||
vid: V, unbound: fn() -> T) -> T {
|
||||
|
||||
let {root:_, bounds} = self.get(vb, vid);
|
||||
let {root:_, bounds} = self.infcx.get(vb, vid);
|
||||
|
||||
#debug["resolve_var(%s) bounds=%s",
|
||||
vid.to_str(), bounds.to_str(self)];
|
||||
vid.to_str(),
|
||||
bounds.to_str(self.infcx)];
|
||||
|
||||
// Nonobvious: prefer the most specific type
|
||||
// (i.e., the lower bound) to the more general
|
||||
@ -582,116 +701,12 @@ impl resolve_methods for infer_ctxt {
|
||||
// perf. penalties, so it pays to know more.
|
||||
|
||||
alt bounds {
|
||||
{ ub:_, lb:some(t) } if !bot_guard(t) { ok(t) }
|
||||
{ ub:some(t), lb:_ } { ok(t) }
|
||||
{ ub:_, lb:some(t) } { ok(t) }
|
||||
{ ub:_, lb:some(t) } if !bot_guard(t) { t }
|
||||
{ ub:some(t), lb:_ } { t }
|
||||
{ ub:_, lb:some(t) } { t }
|
||||
{ ub:none, lb:none } { unbound() }
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_ty_var(vid: ty_vid) -> fres<ty::t> {
|
||||
ret self.resolve_var(
|
||||
self.vb,
|
||||
{|t| type_is_bot(t) },
|
||||
vid,
|
||||
{|| ok(ty::mk_bot(self.tcx)) });
|
||||
}
|
||||
|
||||
fn resolve_region_var(rid: region_vid) -> fres<ty::region> {
|
||||
ret self.resolve_var(
|
||||
self.rb,
|
||||
{|_t| false },
|
||||
rid,
|
||||
{|| ok(ty::re_static) });
|
||||
}
|
||||
|
||||
fn resolve_ty(typ: ty::t) -> fres<ty::t> {
|
||||
alt ty::get(typ).struct {
|
||||
ty::ty_var(vid) { self.resolve_ty_var(vid) }
|
||||
ty::ty_rptr(ty::re_var(rid), base_ty) {
|
||||
alt self.resolve_region_var(rid) {
|
||||
err(terr) { err(terr) }
|
||||
ok(region) {
|
||||
self.rok(ty::mk_rptr(self.tcx, region, base_ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { self.rok(typ) }
|
||||
}
|
||||
}
|
||||
|
||||
fn fixup_region(r: ty::region,
|
||||
&r_seen: [region_vid],
|
||||
err: @mut option<fixup_err>) -> ty::region {
|
||||
alt r {
|
||||
ty::re_var(rid) if vec::contains(r_seen, rid) {
|
||||
*err = some(cyclic_region(rid)); r
|
||||
}
|
||||
|
||||
ty::re_var(rid) {
|
||||
alt self.resolve_region_var(rid) {
|
||||
result::ok(r1) {
|
||||
vec::push(r_seen, rid);
|
||||
let r2 = self.fixup_region(r1, r_seen, err);
|
||||
vec::pop(r_seen);
|
||||
ret r2;
|
||||
}
|
||||
result::err(e) { *err = some(e); r }
|
||||
}
|
||||
}
|
||||
|
||||
_ { r }
|
||||
}
|
||||
}
|
||||
|
||||
fn fixup_ty1(ty: ty::t,
|
||||
&ty_seen: [ty_vid],
|
||||
&r_seen: [region_vid],
|
||||
err: @mut option<fixup_err>) -> ty::t {
|
||||
let tb = ty::get(ty);
|
||||
if !tb.has_vars { ret ty; }
|
||||
alt tb.struct {
|
||||
ty::ty_var(vid) if vec::contains(ty_seen, vid) {
|
||||
*err = some(cyclic_ty(vid)); ty
|
||||
}
|
||||
|
||||
ty::ty_var(vid) {
|
||||
alt self.resolve_ty_var(vid) {
|
||||
result::err(e) { *err = some(e); ty }
|
||||
result::ok(ty1) {
|
||||
vec::push(ty_seen, vid);
|
||||
let ty2 = self.fixup_ty1(ty1, ty_seen, r_seen, err);
|
||||
vec::pop(ty_seen);
|
||||
ret ty2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_rptr(r, {ty: base_ty, mutbl: m}) {
|
||||
let base_ty1 = self.fixup_ty1(base_ty, ty_seen, r_seen, err);
|
||||
let r1 = self.fixup_region(r, r_seen, err);
|
||||
ret ty::mk_rptr(self.tcx, r1, {ty: base_ty1, mutbl: m});
|
||||
}
|
||||
|
||||
sty {
|
||||
ty::fold_sty_to_ty(self.tcx, sty) {|t|
|
||||
self.fixup_ty1(t, ty_seen, r_seen, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fixup_ty(typ: ty::t) -> fres<ty::t> {
|
||||
#debug["fixup_ty(%s)", ty_to_str(self.tcx, typ)];
|
||||
let mut ty_seen = [];
|
||||
let mut r_seen = [];
|
||||
let unresolved = @mut none;
|
||||
let rty = self.fixup_ty1(typ, ty_seen, r_seen, unresolved);
|
||||
alt *unresolved {
|
||||
none { ret self.rok(rty); }
|
||||
some(e) { ret self.rerr(e); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ______________________________________________________________________
|
||||
|
@ -37,6 +37,7 @@ export expr_ty_params_and_ty;
|
||||
export expr_is_lval;
|
||||
export field_ty;
|
||||
export fold_ty, fold_sty_to_ty, fold_region, fold_regions, fold_ty_var;
|
||||
export fold_regions_and_ty;
|
||||
export field;
|
||||
export field_idx;
|
||||
export get_field;
|
||||
@ -147,6 +148,7 @@ export item_path_str;
|
||||
export ast_ty_to_ty_cache_entry;
|
||||
export atttce_unresolved, atttce_resolved;
|
||||
export mach_sty;
|
||||
export ty_sort_str;
|
||||
|
||||
// Data types
|
||||
|
||||
|
@ -12,7 +12,8 @@ import middle::ty;
|
||||
import middle::ty::{arg, field, node_type_table, mk_nil,
|
||||
ty_param_bounds_and_ty, lookup_public_fields};
|
||||
import middle::ty::{ty_vid, region_vid, vid};
|
||||
import util::ppaux::{ty_to_str, region_to_str};
|
||||
import util::ppaux::{ty_to_str, region_to_str,
|
||||
bound_region_to_str, vstore_to_str};
|
||||
import std::smallintmap;
|
||||
import std::smallintmap::map;
|
||||
import std::map;
|
||||
@ -257,7 +258,7 @@ fn instantiate_path(fcx: @fn_ctxt,
|
||||
|
||||
// Type tests
|
||||
fn structurally_resolved_type(fcx: @fn_ctxt, sp: span, tp: ty::t) -> ty::t {
|
||||
alt infer::resolve_type_structure(fcx.infcx, tp) {
|
||||
alt infer::resolve_shallow(fcx.infcx, tp) {
|
||||
// note: the bot type doesn't count as resolved; it's what we use when
|
||||
// there is no information about a variable.
|
||||
result::ok(t_s) if !ty::type_is_bot(t_s) { ret t_s; }
|
||||
@ -274,17 +275,6 @@ fn structure_of(fcx: @fn_ctxt, sp: span, typ: ty::t) -> ty::sty {
|
||||
ty::get(structurally_resolved_type(fcx, sp, typ)).struct
|
||||
}
|
||||
|
||||
// Returns the one-level-deep structure of the given type or none if it
|
||||
// is not known yet.
|
||||
fn structure_of_maybe(fcx: @fn_ctxt, _sp: span, typ: ty::t) ->
|
||||
option<ty::sty> {
|
||||
let r = infer::resolve_type_structure(fcx.infcx, typ);
|
||||
alt r {
|
||||
result::ok(typ_s) { some(ty::get(typ_s).struct) }
|
||||
result::err(_) { none }
|
||||
}
|
||||
}
|
||||
|
||||
fn type_is_integral(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
|
||||
let typ_s = structurally_resolved_type(fcx, sp, typ);
|
||||
ret ty::type_is_integral(typ_s);
|
||||
@ -523,18 +513,60 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
|
||||
ret ty;
|
||||
}
|
||||
|
||||
fn mk_vstore<AC: ast_conv, RS: region_scope copy>(
|
||||
fn mk_bounded<AC: ast_conv, RS: region_scope copy>(
|
||||
self: AC, rscope: RS, a_seq_ty: @ast::ty, vst: ty::vstore) -> ty::t {
|
||||
|
||||
let tcx = self.tcx();
|
||||
let seq_ty = ast_ty_to_ty(self, rscope, a_seq_ty);
|
||||
|
||||
alt ty::get(seq_ty).struct {
|
||||
ty::ty_vec(mt) { ty::mk_evec(tcx, mt, vst) }
|
||||
ty::ty_str { ty::mk_estr(tcx, vst) }
|
||||
ty::ty_vec(mt) {
|
||||
ret ty::mk_evec(tcx, mt, vst);
|
||||
}
|
||||
|
||||
ty::ty_str {
|
||||
ret ty::mk_estr(tcx, vst);
|
||||
}
|
||||
|
||||
ty::ty_enum(_, subst) |
|
||||
ty::ty_class(_, subst) |
|
||||
ty::ty_res(_, _, subst) {
|
||||
// n.b.: This is a hacky abuse of the vstore terminology to also
|
||||
// make it work for region bounds. The idea is to allow a type
|
||||
// Id/&r where Id is an enum, class, or resource, but not Id/@
|
||||
// etc. We also do not want to allow Id/&r if the given
|
||||
// enum/class/resource does not define a region parameter.
|
||||
//
|
||||
// Really, these "/&r" bounds ought to be part of the path, like
|
||||
// type parameters. (In fact, we could generalize to allowing
|
||||
// multiple such bounds someday)
|
||||
alt (subst.self_r, vst) {
|
||||
(some(_), ty::vstore_slice(_)) { /* ok */ }
|
||||
(none, ty::vstore_slice(_)) {
|
||||
tcx.sess.span_err(
|
||||
a_seq_ty.span,
|
||||
#fmt["inappropriate bound for %s, \
|
||||
which is not declared as containing \
|
||||
region pointers",
|
||||
ty::ty_sort_str(tcx, seq_ty)]);
|
||||
}
|
||||
(_, _) {
|
||||
tcx.sess.span_err(
|
||||
a_seq_ty.span,
|
||||
#fmt["a %s bound is not appropriate for %s",
|
||||
vstore_to_str(tcx, vst),
|
||||
ty::ty_sort_str(tcx, seq_ty)]);
|
||||
}
|
||||
}
|
||||
ret seq_ty;
|
||||
}
|
||||
|
||||
_ {
|
||||
tcx.sess.span_bug(a_seq_ty.span,
|
||||
"found sequence storage modifier \
|
||||
on non-sequence type")
|
||||
tcx.sess.span_err(
|
||||
a_seq_ty.span,
|
||||
#fmt["Bound not allowed on a %s.",
|
||||
ty::ty_sort_str(tcx, seq_ty)]);
|
||||
ret seq_ty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -633,21 +665,21 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
|
||||
}
|
||||
ast::ty_vstore(a_t, ast::vstore_slice(a_r)) {
|
||||
let r = ast_region_to_region(self, rscope, ast_ty.span, a_r);
|
||||
mk_vstore(self, in_anon_rscope(rscope, r), a_t, ty::vstore_slice(r))
|
||||
mk_bounded(self, in_anon_rscope(rscope, r), a_t, ty::vstore_slice(r))
|
||||
}
|
||||
ast::ty_vstore(a_t, ast::vstore_uniq) {
|
||||
mk_vstore(self, rscope, a_t, ty::vstore_uniq)
|
||||
mk_bounded(self, rscope, a_t, ty::vstore_uniq)
|
||||
}
|
||||
ast::ty_vstore(a_t, ast::vstore_box) {
|
||||
mk_vstore(self, rscope, a_t, ty::vstore_box)
|
||||
mk_bounded(self, rscope, a_t, ty::vstore_box)
|
||||
}
|
||||
ast::ty_vstore(a_t, ast::vstore_fixed(some(u))) {
|
||||
mk_vstore(self, rscope, a_t, ty::vstore_fixed(u))
|
||||
mk_bounded(self, rscope, a_t, ty::vstore_fixed(u))
|
||||
}
|
||||
ast::ty_vstore(_, ast::vstore_fixed(none)) {
|
||||
tcx.sess.span_bug(
|
||||
ast_ty.span,
|
||||
"implied fixed length in ast_ty_vstore_to_vstore");
|
||||
"implied fixed length for bound");
|
||||
}
|
||||
ast::ty_constr(t, cs) {
|
||||
let mut out_cs = [];
|
||||
@ -1656,7 +1688,7 @@ fn do_autoderef(fcx: @fn_ctxt, sp: span, t: ty::t) -> ty::t {
|
||||
}
|
||||
|
||||
fn resolve_type_vars_if_possible(fcx: @fn_ctxt, typ: ty::t) -> ty::t {
|
||||
alt infer::fixup_vars(fcx.infcx, typ) {
|
||||
alt infer::resolve_deep(fcx.infcx, typ, false) {
|
||||
result::ok(new_type) { ret new_type; }
|
||||
result::err(_) { ret typ; }
|
||||
}
|
||||
@ -1731,7 +1763,7 @@ mod writeback {
|
||||
fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t) ->
|
||||
option<ty::t> {
|
||||
if !ty::type_has_vars(typ) { ret some(typ); }
|
||||
alt infer::fixup_vars(fcx.infcx, typ) {
|
||||
alt infer::resolve_deep(fcx.infcx, typ, true) {
|
||||
result::ok(new_type) { ret some(new_type); }
|
||||
result::err(e) {
|
||||
if !fcx.ccx.tcx.sess.has_errors() {
|
||||
@ -1852,7 +1884,7 @@ mod writeback {
|
||||
fn visit_local(l: @ast::local, wbcx: wb_ctxt, v: wb_vt) {
|
||||
if !wbcx.success { ret; }
|
||||
let var_id = lookup_local(wbcx.fcx, l.span, l.node.id);
|
||||
alt infer::resolve_var(wbcx.fcx.infcx, var_id) {
|
||||
alt infer::resolve_deep_var(wbcx.fcx.infcx, var_id, true) {
|
||||
result::ok(lty) {
|
||||
#debug["Type for local %s (id %d) resolved to %s",
|
||||
pat_to_str(l.node.pat), l.node.id,
|
||||
@ -1998,12 +2030,18 @@ fn universally_quantify_from_sty(fcx: @fn_ctxt,
|
||||
bound_tys.map {|x| fcx.ty_to_str(x) }];
|
||||
indent {||
|
||||
let tcx = fcx.tcx();
|
||||
let isr = collect_bound_regions_in_tys(tcx, @nil, bound_tys) { |_id|
|
||||
fcx.next_region_var()
|
||||
let isr = collect_bound_regions_in_tys(tcx, @nil, bound_tys) { |br|
|
||||
let rvar = fcx.next_region_var();
|
||||
#debug["Bound region %s maps to %s",
|
||||
bound_region_to_str(fcx.ccx.tcx, br),
|
||||
region_to_str(fcx.ccx.tcx, rvar)];
|
||||
rvar
|
||||
};
|
||||
ty::fold_sty_to_ty(fcx.ccx.tcx, sty) { |t|
|
||||
let t_res = ty::fold_sty_to_ty(fcx.ccx.tcx, sty) { |t|
|
||||
replace_bound_regions(tcx, span, isr, t)
|
||||
}
|
||||
};
|
||||
#debug["Result of universal quant. is %s", fcx.ty_to_str(t_res)];
|
||||
t_res
|
||||
}
|
||||
}
|
||||
|
||||
@ -4477,7 +4515,7 @@ mod vtable {
|
||||
|
||||
fn fixup_ty(fcx: @fn_ctxt, sp: span, ty: ty::t) -> ty::t {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
alt infer::fixup_vars(fcx.infcx, ty) {
|
||||
alt infer::resolve_deep(fcx.infcx, ty, true) {
|
||||
result::ok(new_type) { new_type }
|
||||
result::err(e) {
|
||||
tcx.sess.span_fatal(
|
||||
|
Loading…
Reference in New Issue
Block a user