Skip to content

Commit 846f00a

Browse files
committed
---
yaml --- r: 15443 b: refs/heads/try c: c1c60c0 h: refs/heads/master i: 15441: 322b7c9 15439: e5931f0 v: v3
1 parent cf171bc commit 846f00a

File tree

4 files changed

+128
-66
lines changed

4 files changed

+128
-66
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: 8967c4b409396edf610967b329f0bf6cbcee4a2f
5+
refs/heads/try: c1c60c023ec3b9b5bb85aa68d00667c4ab61ee00
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

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

Lines changed: 117 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -201,41 +201,11 @@ impl of st for ty::region {
201201
}
202202
}
203203

204-
// Most of these methods, like tys() and so forth, take two parameters
205-
// a and b and they are tasked with "ensuring that a is a subtype of
206-
// b". They return success or failure. They make changes in-place to
207-
// the variable bindings: these changes are recorded in the `bindings`
208-
// array, which then allows the changes to be rolled back if needed.
209-
//
210-
// The merge() and merge_bnds() methods are somewhat different in that
211-
// they compute a new type range for a variable (generally a subset of
212-
// the old range). They therefore return a result.
213-
impl unify_methods for infer_ctxt {
214-
fn uok() -> ures {
215-
ok(())
216-
}
217-
218-
fn uerr(e: ty::type_err) -> ures {
219-
#debug["Unification error: %?", e];
220-
err(e)
221-
}
222-
223-
fn set<V:copy vid, T:copy to_str>(
224-
vb: vals_and_bindings<V, T>, vid: V,
225-
+new_v: var_value<V, T>) {
226-
227-
let old_v = vb.vals.get(vid.to_uint());
228-
vec::push(vb.bindings, (vid, old_v));
229-
vb.vals.insert(vid.to_uint(), new_v);
230-
231-
#debug["Updating variable %s from %s to %s",
232-
vid.to_str(), old_v.to_str(self), new_v.to_str(self)];
233-
}
234-
235-
fn set_ty(vid: ty_vid, +new_v: var_value<ty_vid, ty::t>) {
236-
self.set(self.vb, vid, new_v);
237-
}
204+
fn uok() -> ures {
205+
ok(())
206+
}
238207

208+
impl methods for infer_ctxt {
239209
fn commit<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
240210

241211
assert self.vb.bindings.len() == 0u;
@@ -276,6 +246,21 @@ impl unify_methods for infer_ctxt {
276246
}
277247
ret r;
278248
}
249+
}
250+
251+
impl unify_methods for infer_ctxt {
252+
253+
fn set<V:copy vid, T:copy to_str>(
254+
vb: vals_and_bindings<V, T>, vid: V,
255+
+new_v: var_value<V, T>) {
256+
257+
let old_v = vb.vals.get(vid.to_uint());
258+
vec::push(vb.bindings, (vid, old_v));
259+
vb.vals.insert(vid.to_uint(), new_v);
260+
261+
#debug["Updating variable %s from %s to %s",
262+
vid.to_str(), old_v.to_str(self), new_v.to_str(self)];
263+
}
279264

280265
fn get<V:copy vid, T:copy>(
281266
vb: vals_and_bindings<V, T>, vid: V)
@@ -397,7 +382,7 @@ impl unify_methods for infer_ctxt {
397382
// be relatable:
398383
self.bnds(bnds.lb, bnds.ub).then {||
399384
self.set(vb, v_id, bounded(bnds));
400-
self.uok()
385+
uok()
401386
}
402387
}}}}}
403388
}
@@ -414,7 +399,7 @@ impl unify_methods for infer_ctxt {
414399
a_id.to_str(), a_bounds.to_str(self),
415400
b_id.to_str(), b_bounds.to_str(self)];
416401

417-
if a_id == b_id { ret self.uok(); }
402+
if a_id == b_id { ret uok(); }
418403

419404
// If both A's UB and B's LB have already been bound to types,
420405
// see if we can make those types subtypes.
@@ -437,7 +422,7 @@ impl unify_methods for infer_ctxt {
437422
// A remains a subtype of B. Actually, there are other options,
438423
// but that's the route we choose to take.
439424
self.set_var_to_merged_bounds(vb, a_id, a_bounds, b_bounds).then {||
440-
self.uok()
425+
uok()
441426
}
442427
}
443428

@@ -470,7 +455,7 @@ impl unify_methods for infer_ctxt {
470455
actual_constr: @ty::type_constr) -> ures {
471456

472457
let err_res =
473-
self.uerr(ty::terr_constr_mismatch(expected, actual_constr));
458+
err(ty::terr_constr_mismatch(expected, actual_constr));
474459

475460
if expected.node.id != actual_constr.node.id { ret err_res; }
476461
let expected_arg_len = vec::len(expected.node.args);
@@ -505,7 +490,7 @@ impl unify_methods for infer_ctxt {
505490
}
506491
i += 1u;
507492
}
508-
ret self.uok();
493+
ret uok();
509494
}
510495

511496
fn bnds<T:copy to_str st>(
@@ -517,7 +502,7 @@ impl unify_methods for infer_ctxt {
517502
(none, none) |
518503
(some(_), none) |
519504
(none, some(_)) {
520-
self.uok()
505+
uok()
521506
}
522507
(some(t_a), some(t_b)) {
523508
t_a.sub(self, t_b)
@@ -534,7 +519,7 @@ impl unify_methods for infer_ctxt {
534519
self.constrs(a, b)
535520
}
536521
} else {
537-
self.uerr(ty::terr_constr_len(bs.len(), as.len()))
522+
err(ty::terr_constr_len(bs.len(), as.len()))
538523
}
539524
}
540525

@@ -688,33 +673,103 @@ impl resolve_methods for infer_ctxt {
688673
}
689674
}
690675

676+
// ______________________________________________________________________
677+
// Type assignment
678+
//
679+
// True if rvalues of type `a` can be assigned to lvalues of type `b`.
680+
681+
impl assignment for infer_ctxt {
682+
fn assign_tys(a: ty::t, b: ty::t,
683+
encl_blk_id: ast::node_id) -> ures {
684+
685+
#debug["assign_tys(%s, %s)", a.to_str(self), b.to_str(self)];
686+
let _r = indenter();
687+
688+
alt (ty::get(a).struct, ty::get(b).struct) {
689+
(ty::ty_bot, _) {
690+
uok()
691+
}
692+
693+
(ty::ty_var(a_id), ty::ty_var(b_id)) {
694+
let {root:_, bounds:a_bounds} = self.get(self.vb, a_id);
695+
let {root:_, bounds:b_bounds} = self.get(self.vb, b_id);
696+
self.assign_vars_or_sub(a, b, a_bounds, b_bounds, encl_blk_id)
697+
}
698+
699+
(ty::ty_var(a_id), _) {
700+
let {root:_, bounds:a_bounds} = self.get(self.vb, a_id);
701+
let b_bounds = {lb: some(b), ub: none};
702+
self.assign_vars_or_sub(a, b, a_bounds, b_bounds, encl_blk_id)
703+
}
704+
705+
(_, ty::ty_var(b_id)) {
706+
let a_bounds = {lb: none, ub: some(a)};
707+
let {root:_, bounds: b_bounds} = self.get(self.vb, b_id);
708+
self.assign_vars_or_sub(a, b, a_bounds, b_bounds, encl_blk_id)
709+
}
710+
711+
(ty::ty_box(a_mt), ty::ty_rptr(_, _)) |
712+
(ty::ty_uniq(a_mt), ty::ty_rptr(_, _)) {
713+
let a_r = ty::re_scope(encl_blk_id);
714+
let a_ty = ty::mk_rptr(self.tcx, a_r, a_mt);
715+
self.sub_tys(a_ty, b).to_ures()
716+
}
717+
718+
_ {
719+
self.sub_tys(a, b).to_ures()
720+
}
721+
}
722+
}
723+
724+
fn assign_tys_or_sub(a: ty::t, b: ty::t,
725+
a_b: ty::t, b_b: ty::t,
726+
encl_blk_id: ast::node_id) -> ures {
727+
self.try {||
728+
self.assign_tys(a_b, b_b, encl_blk_id)
729+
}.chain_err {|_e|
730+
self.sub_tys(a, b)
731+
}
732+
}
733+
734+
fn assign_vars_or_sub(a: ty::t, b: ty::t,
735+
a_bounds: bounds<ty::t>, b_bounds: bounds<ty::t>,
736+
encl_blk_id: ast::node_id) -> ures {
737+
738+
alt (a_bounds.ub, b_bounds.lb) {
739+
(some(a_ub), some(b_lb)) {
740+
self.assign_tys_or_sub(a, b, a_ub, b_lb, encl_blk_id)
741+
}
742+
_ {
743+
self.sub_tys(a, b).to_ures()
744+
}
745+
}
746+
}
747+
}
748+
691749
// ______________________________________________________________________
692750
// Type combining
693751
//
694-
// There are two type combiners, lub and gub. The first computes the
695-
// Least Upper Bound of two types `a` and `b`---that is, a mutual
752+
// There are three type combiners, sub, lub, and gub. `sub` is a bit
753+
// different from the other two: it takes two types and makes the first
754+
// a subtype of the other, or fails if this cannot be done. It does
755+
// return a new type but its return value is meaningless---it is only
756+
// there to allow for greater code reuse.
757+
//
758+
// `lub` and `glb` compute the Least Upper Bound and Greatest Lower
759+
// Bound respectively of two types `a` and `b`. The LUB is a mutual
696760
// supertype type `c` where `a <: c` and `b <: c`. As the name
697-
// implies, it tries to pick the most precise `c` possible. `glb`
698-
// computes the greatest lower bound---that is, it computes a mutual
699-
// subtype, aiming for the most general such type possible. Both
700-
// computations may fail.
761+
// implies, it tries to pick the most precise `c` possible. The GLB
762+
// is a mutual subtype, aiming for the most general such type
763+
// possible. Both computations may fail.
701764
//
702765
// There is a lot of common code for these operations, which is
703-
// abstracted out into functions named `c_X()` which take a combiner
766+
// abstracted out into functions named `super_X()` which take a combiner
704767
// instance as the first parameter. This would be better implemented
705768
// using traits.
706769
//
707-
// The `c_X()` top-level items work for *both LUB and GLB*: any
708-
// operation which varies between LUB and GLB will be dynamically
709-
// dispatched using a `self.Y()` operation.
710-
//
711-
// In principle, the subtyping relation computed above could be built
712-
// on the combine framework---this would result in less code but would
713-
// be less efficient. There is a significant performance gain from
714-
// not recreating types unless we need to. Even so, we could write
715-
// the routines with a few more generics in there to mask type
716-
// construction (which is, after all, the significant expense) but I
717-
// haven't gotten around to it.
770+
// The `super_X()` top-level items work for *sub, lub, and glb*: any
771+
// operation which varies will be dynamically dispatched using a
772+
// `self.Y()` operation.
718773

719774
type cres<T> = result<T,ty::type_err>;
720775

@@ -736,7 +791,7 @@ iface combine {
736791
fn regions(a: ty::region, b: ty::region) -> cres<ty::region>;
737792
}
738793

739-
enum sub = infer_ctxt; // "less than" == "subtype" or "subregion"
794+
enum sub = infer_ctxt; // "subtype", "subregion" etc
740795
enum lub = infer_ctxt; // "least upper bound" (common supertype)
741796
enum glb = infer_ctxt; // "greatest lower bound" (common subtype)
742797

@@ -1445,7 +1500,8 @@ impl of combine for glb {
14451500
// ______________________________________________________________________
14461501
// Lattice operations on variables
14471502
//
1448-
// this is common code used by both LUB and GLB
1503+
// This is common code used by both LUB and GLB to compute the LUB/GLB
1504+
// for pairs of variables or for variables and values.
14491505

14501506
iface lattice_ops {
14511507
fn bnd<T:copy>(b: bounds<T>) -> option<T>;

branches/try/src/test/compile-fail/vec-concat-bug.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
// xfail-test
2-
31
fn concat<T: copy>(v: [const [const T]]) -> [T] {
42
let mut r = [];
53

64
// Earlier versions of our type checker accepted this:
7-
for v.each {|inner|
8-
//!^ ERROR found `[const 'a]` (values differ in mutability)
5+
vec::iter(v) {|&&inner: [T]|
6+
//!^ ERROR values differ in mutability
7+
//!^^ ERROR values differ in mutability
98
r += inner;
109
}
1110

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn foo(x: &uint) -> &uint { x }
2+
3+
fn main() {
4+
let p = @3u;
5+
let r = foo(p);
6+
assert *p == *r;
7+
}

0 commit comments

Comments
 (0)