Skip to content

Commit 1bc6735

Browse files
committed
---
yaml --- r: 15612 b: refs/heads/try c: 0d3658b h: refs/heads/master v: v3
1 parent 3d77639 commit 1bc6735

File tree

5 files changed

+228
-157
lines changed

5 files changed

+228
-157
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: 68f88125115fb239c79efa655570fdcae821765c
5+
refs/heads/try: 0d3658bb43455fc1d52662dca17789e689914879
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/libcore/result.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ checking for overflow:
142142
assert incd == [2u, 3u, 4u];
143143
}
144144
"]
145-
fn map<T,U:copy,V:copy>(ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
145+
fn map<T,U:copy,V:copy>(
146+
ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
147+
146148
let mut vs: [V] = [];
147149
vec::reserve(vs, vec::len(ts));
148150
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> {
154156
ret ok(vs);
155157
}
156158

159+
fn map_opt<T,U:copy,V:copy>(
160+
o_t: option<T>, op: fn(T) -> result<V,U>) -> result<option<V>,U> {
161+
162+
alt o_t {
163+
none { ok(none) }
164+
some(t) {
165+
alt op(t) {
166+
ok(v) { ok(some(v)) }
167+
err(e) { err(e) }
168+
}
169+
}
170+
}
171+
}
172+
157173
#[doc = "Same as map, but it operates over two parallel vectors.
158174
159175
A precondition is used here to ensure that the vectors are the same

branches/try/src/rustc/middle/infer.rs

Lines changed: 138 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ export new_infer_ctxt;
1717
export mk_subty;
1818
export mk_eqty;
1919
export mk_assignty;
20-
export resolve_type_structure;
21-
export fixup_vars;
22-
export resolve_var;
20+
export resolve_shallow;
21+
export resolve_deep;
22+
export resolve_deep_var;
2323
export compare_tys;
2424
export fixup_err, fixup_err_to_str;
2525

@@ -92,16 +92,23 @@ fn compare_tys(tcx: ty::ctxt, a: ty::t, b: ty::t) -> ures {
9292
mk_eqty(infcx, a, b)
9393
}
9494

95-
fn resolve_type_structure(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
96-
cx.resolve_ty(a)
95+
// Resolves one level of type structure but not any type variables
96+
// that may be nested within.
97+
fn resolve_shallow(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
98+
resolver(cx, false, false).resolve(a)
9799
}
98100

99-
fn resolve_var(cx: infer_ctxt, vid: ty_vid) -> fres<ty::t> {
100-
cx.fixup_ty(ty::mk_var(cx.tcx, vid))
101+
// see resolve_deep()
102+
fn resolve_deep_var(cx: infer_ctxt, vid: ty_vid,
103+
force_vars: bool) -> fres<ty::t> {
104+
resolver(cx, true, force_vars).resolve(ty::mk_var(cx.tcx, vid))
101105
}
102106

103-
fn fixup_vars(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
104-
cx.fixup_ty(a)
107+
// Resolves all levels of type structure. If `force_vars` is true,
108+
// then we will resolve unconstrained type/region variables to
109+
// something arbitrary. Otherwise, we preserve them as variables.
110+
fn resolve_deep(cx: infer_ctxt, a: ty::t, force_vars: bool) -> fres<ty::t> {
111+
resolver(cx, true, force_vars).resolve(a)
105112
}
106113

107114
impl methods for ures {
@@ -555,141 +562,149 @@ impl unify_methods for infer_ctxt {
555562
}
556563
}
557564

558-
impl resolve_methods for infer_ctxt {
559-
fn rok(t: ty::t) -> fres<ty::t> {
560-
#debug["Resolve OK: %s", t.to_str(self)];
561-
ok(t)
562-
}
563-
564-
fn rerr<T>(v: fixup_err) -> fres<T> {
565-
#debug["Resolve error: %?", v];
566-
err(v)
567-
}
565+
// Resolution is the process of removing type variables and replacing
566+
// them with their inferred values. There are several "modes" for
567+
// resolution. The first is a shallow resolution: this only resolves
568+
// one layer, but does not resolve any nested variables. So, for
569+
// example, if we have two variables A and B, and the constraint that
570+
// A <: [B] and B <: int, then shallow resolution on A would yield
571+
// [B]. Deep resolution, on the other hand, would yield [int].
572+
//
573+
// But there is one more knob: the force_vars variable controls the
574+
// behavior in the face of unconstrained variables. If we have A, B
575+
// and only the constraint that A <: B, then the result is [_|_] if
576+
// force_vars is true and [B] otherwise. We use force_vars == true
577+
// when resolving types after typeck, but false otherwise (for
578+
// example, when pretty-printing them for errors).
579+
580+
type resolve_state = @{
581+
infcx: infer_ctxt,
582+
deep: bool,
583+
force_vars: bool,
584+
mut err: option<fixup_err>,
585+
mut r_seen: [region_vid],
586+
mut v_seen: [ty_vid]
587+
};
568588

569-
fn resolve_var<V: copy vid, T:copy to_str>(
570-
vb: vals_and_bindings<V, T>, bot_guard: fn(T)->bool,
571-
vid: V, unbound: fn() -> fres<T>) -> fres<T> {
589+
fn resolver(infcx: infer_ctxt, deep: bool, fvars: bool) -> resolve_state {
590+
@{infcx: infcx,
591+
deep: deep,
592+
force_vars: fvars,
593+
mut err: none,
594+
mut r_seen: [],
595+
mut v_seen: []}
596+
}
572597

573-
let {root:_, bounds} = self.get(vb, vid);
598+
impl methods for resolve_state {
599+
fn resolve(typ: ty::t) -> fres<ty::t> {
600+
self.err = none;
574601

575-
#debug["resolve_var(%s) bounds=%s",
576-
vid.to_str(), bounds.to_str(self)];
602+
// n.b. This is a hokey mess because the current fold doesn't
603+
// allow us to pass back errors in any useful way.
577604

578-
// Nonobvious: prefer the most specific type
579-
// (i.e., the lower bound) to the more general
580-
// one. More general types in Rust (e.g., fn())
581-
// tend to carry more restrictions or higher
582-
// perf. penalties, so it pays to know more.
583-
584-
alt bounds {
585-
{ ub:_, lb:some(t) } if !bot_guard(t) { ok(t) }
586-
{ ub:some(t), lb:_ } { ok(t) }
587-
{ ub:_, lb:some(t) } { ok(t) }
588-
{ ub:none, lb:none } { unbound() }
605+
assert vec::is_empty(self.v_seen) && vec::is_empty(self.r_seen);
606+
let rty = self.resolve1(typ);
607+
assert vec::is_empty(self.v_seen) && vec::is_empty(self.r_seen);
608+
alt self.err {
609+
none {
610+
#debug["Resolved %s to %s (deep=%b, force_vars=%b)",
611+
ty_to_str(self.infcx.tcx, typ),
612+
ty_to_str(self.infcx.tcx, rty),
613+
self.deep,
614+
self.force_vars];
615+
ret ok(rty);
616+
}
617+
some(e) { ret err(e); }
589618
}
590619
}
591620

592-
fn resolve_ty_var(vid: ty_vid) -> fres<ty::t> {
593-
ret self.resolve_var(
594-
self.vb,
595-
{|t| type_is_bot(t) },
596-
vid,
597-
{|| ok(ty::mk_bot(self.tcx)) });
598-
}
599-
600-
fn resolve_region_var(rid: region_vid) -> fres<ty::region> {
601-
ret self.resolve_var(
602-
self.rb,
603-
{|_t| false },
604-
rid,
605-
{|| ok(ty::re_static) });
606-
}
607-
608-
fn resolve_ty(typ: ty::t) -> fres<ty::t> {
609-
alt ty::get(typ).struct {
621+
fn resolve1(typ: ty::t) -> ty::t {
622+
let tb = ty::get(typ);
623+
alt tb.struct {
610624
ty::ty_var(vid) { self.resolve_ty_var(vid) }
611-
ty::ty_rptr(ty::re_var(rid), base_ty) {
612-
alt self.resolve_region_var(rid) {
613-
err(terr) { err(terr) }
614-
ok(region) {
615-
self.rok(ty::mk_rptr(self.tcx, region, base_ty))
616-
}
617-
}
625+
_ if !tb.has_regions && !self.deep { typ }
626+
_ {
627+
ty::fold_regions_and_ty(
628+
self.infcx.tcx, typ,
629+
{ |r| self.resolve_region(r) },
630+
{ |t| self.resolve_if_deep(t) },
631+
{ |t| self.resolve_if_deep(t) })
618632
}
619-
_ { self.rok(typ) }
620633
}
621634
}
622635

623-
fn fixup_region(r: ty::region,
624-
&r_seen: [region_vid],
625-
err: @mut option<fixup_err>) -> ty::region {
626-
alt r {
627-
ty::re_var(rid) if vec::contains(r_seen, rid) {
628-
*err = some(cyclic_region(rid)); r
629-
}
636+
fn resolve_if_deep(typ: ty::t) -> ty::t {
637+
if !self.deep {typ} else {self.resolve1(typ)}
638+
}
630639

631-
ty::re_var(rid) {
632-
alt self.resolve_region_var(rid) {
633-
result::ok(r1) {
634-
vec::push(r_seen, rid);
635-
let r2 = self.fixup_region(r1, r_seen, err);
636-
vec::pop(r_seen);
637-
ret r2;
638-
}
639-
result::err(e) { *err = some(e); r }
640-
}
641-
}
640+
fn resolve_region(orig: ty::region) -> ty::region {
641+
alt orig {
642+
ty::re_var(rid) { self.resolve_region_var(rid) }
643+
_ { orig }
644+
}
645+
}
642646

643-
_ { r }
647+
fn resolve_region_var(rid: region_vid) -> ty::region {
648+
if vec::contains(self.r_seen, rid) {
649+
self.err = some(cyclic_region(rid));
650+
ret ty::re_var(rid);
651+
} else {
652+
vec::push(self.r_seen, rid);
653+
let r = self.resolve_var(
654+
self.infcx.rb,
655+
{|_t| false },
656+
rid,
657+
{||
658+
if self.force_vars {ty::re_static}
659+
else {ty::re_var(rid)}
660+
});
661+
vec::pop(self.r_seen);
662+
ret r;
663+
}
664+
}
665+
666+
fn resolve_ty_var(vid: ty_vid) -> ty::t {
667+
if vec::contains(self.v_seen, vid) {
668+
self.err = some(cyclic_ty(vid));
669+
ret ty::mk_var(self.infcx.tcx, vid);
670+
} else {
671+
vec::push(self.v_seen, vid);
672+
let tcx = self.infcx.tcx;
673+
let t0 = self.resolve_var(
674+
self.infcx.vb,
675+
{|t| type_is_bot(t) },
676+
vid,
677+
{||
678+
if self.force_vars {ty::mk_bot(tcx)}
679+
else {ty::mk_var(tcx, vid)}
680+
});
681+
let t1 = self.resolve1(t0);
682+
vec::pop(self.v_seen);
683+
ret t1;
644684
}
645685
}
646686

647-
fn fixup_ty1(ty: ty::t,
648-
&ty_seen: [ty_vid],
649-
&r_seen: [region_vid],
650-
err: @mut option<fixup_err>) -> ty::t {
651-
let tb = ty::get(ty);
652-
if !tb.has_vars { ret ty; }
653-
alt tb.struct {
654-
ty::ty_var(vid) if vec::contains(ty_seen, vid) {
655-
*err = some(cyclic_ty(vid)); ty
656-
}
687+
fn resolve_var<V: copy vid, T:copy to_str>(
688+
vb: vals_and_bindings<V, T>, bot_guard: fn(T)->bool,
689+
vid: V, unbound: fn() -> T) -> T {
657690

658-
ty::ty_var(vid) {
659-
alt self.resolve_ty_var(vid) {
660-
result::err(e) { *err = some(e); ty }
661-
result::ok(ty1) {
662-
vec::push(ty_seen, vid);
663-
let ty2 = self.fixup_ty1(ty1, ty_seen, r_seen, err);
664-
vec::pop(ty_seen);
665-
ret ty2;
666-
}
667-
}
668-
}
691+
let {root:_, bounds} = self.infcx.get(vb, vid);
669692

670-
ty::ty_rptr(r, {ty: base_ty, mutbl: m}) {
671-
let base_ty1 = self.fixup_ty1(base_ty, ty_seen, r_seen, err);
672-
let r1 = self.fixup_region(r, r_seen, err);
673-
ret ty::mk_rptr(self.tcx, r1, {ty: base_ty1, mutbl: m});
674-
}
693+
#debug["resolve_var(%s) bounds=%s",
694+
vid.to_str(),
695+
bounds.to_str(self.infcx)];
675696

676-
sty {
677-
ty::fold_sty_to_ty(self.tcx, sty) {|t|
678-
self.fixup_ty1(t, ty_seen, r_seen, err)
679-
}
680-
}
681-
}
682-
}
697+
// Nonobvious: prefer the most specific type
698+
// (i.e., the lower bound) to the more general
699+
// one. More general types in Rust (e.g., fn())
700+
// tend to carry more restrictions or higher
701+
// perf. penalties, so it pays to know more.
683702

684-
fn fixup_ty(typ: ty::t) -> fres<ty::t> {
685-
#debug["fixup_ty(%s)", ty_to_str(self.tcx, typ)];
686-
let mut ty_seen = [];
687-
let mut r_seen = [];
688-
let unresolved = @mut none;
689-
let rty = self.fixup_ty1(typ, ty_seen, r_seen, unresolved);
690-
alt *unresolved {
691-
none { ret self.rok(rty); }
692-
some(e) { ret self.rerr(e); }
703+
alt bounds {
704+
{ ub:_, lb:some(t) } if !bot_guard(t) { t }
705+
{ ub:some(t), lb:_ } { t }
706+
{ ub:_, lb:some(t) } { t }
707+
{ ub:none, lb:none } { unbound() }
693708
}
694709
}
695710
}

branches/try/src/rustc/middle/ty.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export expr_ty_params_and_ty;
3737
export expr_is_lval;
3838
export field_ty;
3939
export fold_ty, fold_sty_to_ty, fold_region, fold_regions, fold_ty_var;
40+
export fold_regions_and_ty;
4041
export field;
4142
export field_idx;
4243
export get_field;
@@ -147,6 +148,7 @@ export item_path_str;
147148
export ast_ty_to_ty_cache_entry;
148149
export atttce_unresolved, atttce_resolved;
149150
export mach_sty;
151+
export ty_sort_str;
150152

151153
// Data types
152154

0 commit comments

Comments
 (0)