Skip to content

Commit 051f24d

Browse files
committed
add static region and also fix regions to be contravariant
1 parent f1afb0b commit 051f24d

File tree

12 files changed

+146
-72
lines changed

12 files changed

+146
-72
lines changed

src/librustsyntax/ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ type region = {id: node_id, node: region_};
442442
enum region_ {
443443
re_inferred,
444444
re_named(ident),
445-
re_self
445+
re_self,
446+
re_static
446447
}
447448

448449
#[auto_serialize]

src/librustsyntax/parse/parser.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ fn parse_region(p: parser) -> ast::region {
434434
p.bump(); p.bump();
435435
if string == "self" {
436436
ast::re_self
437+
} else if string == "static" {
438+
ast::re_static
437439
} else {
438440
ast::re_named(string)
439441
}

src/librustsyntax/print/pprust.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ fn print_region(s: ps, region: ast::region) {
322322
ast::re_inferred { /* no-op */ }
323323
ast::re_named(name) { word(s.s, name); word(s.s, "."); }
324324
ast::re_self { word(s.s, "self"); word(s.s, "."); }
325+
ast::re_static { word(s.s, "static"); word(s.s, "."); }
325326
}
326327
}
327328

src/rustc/metadata/tyencode.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ fn enc_region(w: io::writer, r: ty::region) {
140140
w.write_uint(id.to_uint());
141141
w.write_char('|');
142142
}
143+
ty::re_static {
144+
w.write_char('t');
145+
}
143146
}
144147
}
145148
fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {

src/rustc/middle/infer.rs

Lines changed: 98 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import util::ppaux::{ty_to_str, mt_to_str};
99
import result::{result, extensions, ok, err, map, map2, iter2};
1010
import ty::type_is_bot;
1111
import driver::session::session;
12+
import util::common::{indent, indenter};
1213

1314
export infer_ctxt;
1415
export new_infer_ctxt;
@@ -66,25 +67,31 @@ fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
6667
}
6768

6869
fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
69-
#debug[">> mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
70-
cx.commit {||
71-
cx.tys(a, b)
70+
#debug["mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
71+
indent {||
72+
cx.commit {||
73+
cx.tys(a, b)
74+
}
7275
}
7376
}
7477

7578
fn mk_eqty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
76-
#debug[">> mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
77-
cx.commit {||
78-
cx.eq_tys(a, b)
79+
#debug["mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
80+
indent {||
81+
cx.commit {||
82+
cx.eq_tys(a, b)
83+
}
7984
}
8085
}
8186

8287
fn compare_tys(tcx: ty::ctxt, a: ty::t, b: ty::t) -> ures {
8388
let infcx = new_infer_ctxt(tcx);
84-
#debug[">> compare_tys(%s == %s)", a.to_str(infcx), b.to_str(infcx)];
85-
infcx.commit {||
86-
mk_subty(infcx, a, b).then {||
87-
mk_subty(infcx, b, a)
89+
#debug["compare_tys(%s == %s)", a.to_str(infcx), b.to_str(infcx)];
90+
indent {||
91+
infcx.commit {||
92+
mk_subty(infcx, a, b).then {||
93+
mk_subty(infcx, b, a)
94+
}
8895
}
8996
}
9097
}
@@ -226,24 +233,22 @@ impl unify_methods for infer_ctxt {
226233
self.set(self.vb, vid, new_v);
227234
}
228235

229-
fn commit<T:copy,E:copy>(f: fn() -> result<T,E>) -> result<T,E> {
236+
fn commit<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
230237

231238
assert self.vb.bindings.len() == 0u;
232239
assert self.rb.bindings.len() == 0u;
233240

234-
let r = self.try(f);
241+
let r <- self.try(f);
235242

236243
// TODO---could use a vec::clear() that ran destructors but kept
237244
// the vec at its currently allocated length
238245
self.vb.bindings = [];
239246
self.rb.bindings = [];
240247

241-
#debug[">> Commit result: %?", r];
242-
243248
ret r;
244249
}
245250

246-
fn try<T:copy,E:copy>(f: fn() -> result<T,E>) -> result<T,E> {
251+
fn try<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
247252

248253
fn rollback_to<V:copy vid, T:copy>(
249254
vb: vals_and_bindings<V, T>, len: uint) {
@@ -257,7 +262,7 @@ impl unify_methods for infer_ctxt {
257262
let vbl = self.vb.bindings.len();
258263
let rbl = self.rb.bindings.len();
259264
#debug["try(vbl=%u, rbl=%u)", vbl, rbl];
260-
let r = f();
265+
let r <- f();
261266
alt r {
262267
result::ok(_) { #debug["try--ok"]; }
263268
result::err(_) {
@@ -309,6 +314,9 @@ impl unify_methods for infer_ctxt {
309314
a: bound<V>, b: bound<V>,
310315
merge_op: fn(V,V) -> cres<V>) -> cres<bound<V>> {
311316

317+
#debug["merge_bnd(%s,%s)", a.to_str(self), b.to_str(self)];
318+
let _r = indenter();
319+
312320
alt (a, b) {
313321
(none, none) {
314322
ok(none)
@@ -332,6 +340,7 @@ impl unify_methods for infer_ctxt {
332340
lub: fn(V,V) -> cres<V>,
333341
glb: fn(V,V) -> cres<V>) -> cres<bounds<V>> {
334342

343+
let _r = indenter();
335344
self.merge_bnd(a.ub, b.ub, glb).chain {|ub|
336345
#debug["glb of ubs %s and %s is %s",
337346
a.ub.to_str(self), b.ub.to_str(self),
@@ -383,6 +392,7 @@ impl unify_methods for infer_ctxt {
383392
// them explicitly gives the type inferencer more
384393
// information and helps to produce tighter bounds
385394
// when necessary.
395+
indent {||
386396
self.bnds(a.lb, b.ub).then {||
387397
self.bnds(b.lb, a.ub).then {||
388398
self.merge_bnd(a.ub, b.ub, {|x, y| x.glb(self, y)}).chain {|ub|
@@ -395,10 +405,10 @@ impl unify_methods for infer_ctxt {
395405
// the new bounds must themselves
396406
// be relatable:
397407
self.bnds(bnds.lb, bnds.ub).then {||
398-
self.set(vb, v_id, bounded(bnds));
399-
self.uok()
408+
self.set(vb, v_id, bounded(bnds));
409+
self.uok()
400410
}
401-
}}}}
411+
}}}}}
402412
}
403413

404414
fn vars<V:copy vid, T:copy to_str st>(
@@ -465,46 +475,29 @@ impl unify_methods for infer_ctxt {
465475
}
466476

467477
fn regions(a: ty::region, b: ty::region) -> ures {
468-
alt (a, b) { // XXX
469-
(ty::re_var(a_id), ty::re_var(b_id)) {
470-
self.vars(self.rb, a_id, b_id)
471-
}
472-
(ty::re_var(a_id), _) {
473-
self.vart(self.rb, a_id, b)
474-
}
475-
(_, ty::re_var(b_id)) {
476-
self.tvar(self.rb, a, b_id)
477-
}
478-
479-
(ty::re_free(a_id, _), ty::re_scope(b_id)) |
480-
(ty::re_scope(a_id), ty::re_free(b_id, _)) |
481-
(ty::re_scope(a_id), ty::re_scope(b_id)) {
482-
let rm = self.tcx.region_map;
483-
alt region::nearest_common_ancestor(rm, a_id, b_id) {
484-
some(r_id) if r_id == a_id { self.uok() }
485-
_ { err(ty::terr_regions_differ(false, b, a)) }
486-
}
487-
}
478+
#debug["regions(%s <= %s)", a.to_str(self), b.to_str(self)];
479+
indent {||
480+
alt (a, b) {
481+
(ty::re_var(a_id), ty::re_var(b_id)) {
482+
self.vars(self.rb, a_id, b_id)
483+
}
484+
(ty::re_var(a_id), _) {
485+
self.vart(self.rb, a_id, b)
486+
}
487+
(_, ty::re_var(b_id)) {
488+
self.tvar(self.rb, a, b_id)
489+
}
488490

489-
// For these types, we cannot define any additional relationship:
490-
(ty::re_free(_, _), ty::re_free(_, _)) |
491-
(ty::re_bound(_), ty::re_bound(_)) |
492-
(ty::re_bound(_), ty::re_free(_, _)) |
493-
(ty::re_bound(_), ty::re_scope(_)) |
494-
(ty::re_free(_, _), ty::re_bound(_)) |
495-
(ty::re_scope(_), ty::re_bound(_)) {
496-
if a == b {
497-
self.uok()
498-
} else {
499-
err(ty::terr_regions_differ(false, b, a))
491+
_ {
492+
lub(self).c_regions(a, b).chain {|r|
493+
if b == r {
494+
self.uok()
495+
} else {
496+
err(ty::terr_regions_differ(false, b, a))
497+
}
498+
}
499+
}
500500
}
501-
}
502-
503-
(ty::re_default, _) |
504-
(_, ty::re_default) {
505-
// actually a compiler bug, I think.
506-
err(ty::terr_regions_differ(false, b, a))
507-
}
508501
}
509502
}
510503

@@ -657,16 +650,17 @@ impl unify_methods for infer_ctxt {
657650
a: bound<T>, b: bound<T>) -> ures {
658651

659652
#debug("bnds(%s <: %s)", a.to_str(self), b.to_str(self));
660-
661-
alt (a, b) {
662-
(none, none) |
663-
(some(_), none) |
664-
(none, some(_)) {
665-
self.uok()
666-
}
667-
(some(t_a), some(t_b)) {
668-
t_a.st(self, t_b)
669-
}
653+
indent {||
654+
alt (a, b) {
655+
(none, none) |
656+
(some(_), none) |
657+
(none, some(_)) {
658+
self.uok()
659+
}
660+
(some(t_a), some(t_b)) {
661+
t_a.st(self, t_b)
662+
}
663+
}
670664
}
671665
}
672666

@@ -744,7 +738,9 @@ impl unify_methods for infer_ctxt {
744738

745739
(ty::ty_rptr(a_r, a_mt), ty::ty_rptr(b_r, b_mt)) {
746740
self.mts(a_mt, b_mt).then {||
747-
self.regions(a_r, b_r)
741+
// Non-obvious: for &a.T to be a subtype of &b.T, &a
742+
// must exist for LONGER than &b. That is, &b <= &a.
743+
self.regions(b_r, a_r)
748744
}
749745
}
750746

@@ -972,8 +968,11 @@ iface combine {
972968

973969
// Combining regions (along with some specific cases that are
974970
// different for LUB/GLB):
971+
fn c_contraregions(
972+
a: ty::region, b: ty::region) -> cres<ty::region>;
975973
fn c_regions(
976974
a: ty::region, b: ty::region) -> cres<ty::region>;
975+
fn c_regions_static(r: ty::region) -> cres<ty::region>;
977976
fn c_regions_scope_scope(
978977
a: ty::region, a_id: ast::node_id,
979978
b: ty::region, b_id: ast::node_id) -> cres<ty::region>;
@@ -1045,11 +1044,13 @@ fn c_var_t<V:copy vid, C:combine, T:copy to_str st>(
10451044
alt self.bnd(a_bounds) {
10461045
some(a_bnd) {
10471046
// If a has an upper bound, return it.
1047+
#debug["bnd=some(%s)", a_bnd.to_str(self.infcx())];
10481048
ret c_ts(a_bnd, b);
10491049
}
10501050
none {
10511051
// If a does not have an upper bound, make b the upper bound of a
10521052
// and then return b.
1053+
#debug["bnd=none"];
10531054
let a_bounds = self.with_bnd(a_bounds, b);
10541055
self.infcx().bnds(a_bounds.lb, a_bounds.ub).then {||
10551056
self.infcx().set(vb, a_id, bounded(a_bounds));
@@ -1162,6 +1163,7 @@ fn c_tys<C:combine>(
11621163
// Fast path.
11631164
if a == b { ret ok(a); }
11641165

1166+
indent {||
11651167
alt (ty::get(a).struct, ty::get(b).struct) {
11661168
(ty::ty_bot, _) { self.c_bot(b) }
11671169
(_, ty::ty_bot) { self.c_bot(b) }
@@ -1249,7 +1251,7 @@ fn c_tys<C:combine>(
12491251
}
12501252

12511253
(ty::ty_rptr(a_r, a_mt), ty::ty_rptr(b_r, b_mt)) {
1252-
self.c_regions(a_r, b_r).chain {|r|
1254+
self.c_contraregions(a_r, b_r).chain {|r|
12531255
self.c_mts(a_mt, b_mt).chain {|mt|
12541256
ok(ty::mk_rptr(tcx, r, mt))
12551257
}
@@ -1293,6 +1295,7 @@ fn c_tys<C:combine>(
12931295

12941296
_ { err(ty::terr_mismatch) }
12951297
}
1298+
}
12961299
}
12971300

12981301
fn c_regions<C:combine>(
@@ -1303,7 +1306,12 @@ fn c_regions<C:combine>(
13031306
a.to_str(self.infcx()),
13041307
b.to_str(self.infcx())];
13051308

1309+
indent {||
13061310
alt (a, b) {
1311+
(ty::re_static, r) | (r, ty::re_static) {
1312+
self.c_regions_static(r)
1313+
}
1314+
13071315
(ty::re_var(a_id), ty::re_var(b_id)) {
13081316
c_vars(self, self.infcx().rb,
13091317
a, a_id, b_id,
@@ -1352,6 +1360,7 @@ fn c_regions<C:combine>(
13521360
err(ty::terr_regions_differ(false, b, a))
13531361
}
13541362
}
1363+
}
13551364
}
13561365

13571366
impl of combine for lub {
@@ -1443,6 +1452,16 @@ impl of combine for lub {
14431452
ret c_regions(self, a, b);
14441453
}
14451454

1455+
fn c_contraregions(a: ty::region, b: ty::region) -> cres<ty::region> {
1456+
ret glb(self.infcx()).c_regions(a, b);
1457+
}
1458+
1459+
fn c_regions_static(_r: ty::region) -> cres<ty::region> {
1460+
// LUB of `r` and static is always static---what's bigger than
1461+
// that?
1462+
ret ok(ty::re_static);
1463+
}
1464+
14461465
fn c_regions_free_scope(
14471466
a: ty::region, _a_id: ast::node_id, _a_br: ty::bound_region,
14481467
_b: ty::region, _b_id: ast::node_id) -> cres<ty::region> {
@@ -1573,6 +1592,16 @@ impl of combine for glb {
15731592
ret c_regions(self, a, b);
15741593
}
15751594

1595+
fn c_contraregions(a: ty::region, b: ty::region) -> cres<ty::region> {
1596+
ret lub(self.infcx()).c_regions(a, b);
1597+
}
1598+
1599+
fn c_regions_static(r: ty::region) -> cres<ty::region> {
1600+
// GLB of `r` and static is always `r`; static is bigger than
1601+
// everything
1602+
ret ok(r);
1603+
}
1604+
15761605
fn c_regions_free_scope(
15771606
_a: ty::region, _a_id: ast::node_id, _a_br: ty::bound_region,
15781607
b: ty::region, _b_id: ast::node_id) -> cres<ty::region> {

src/rustc/middle/region.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ fn resolve_region_binding(cx: ctxt, span: span, region: ast::region) {
377377
// }
378378
}
379379

380+
ast::re_static { /* fallthrough */ }
381+
380382
ast::re_named(ident) {
381383
alt cx.scope.resolve_ident(ident) {
382384
some(r) {

src/rustc/middle/regionck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
2828
alt ty::get(t).struct {
2929
ty::ty_rptr(region, _) {
3030
alt region {
31-
ty::re_bound(_) | ty::re_free(_, _) {
31+
ty::re_bound(_) | ty::re_free(_, _) | ty::re_static {
3232
/* ok */
3333
}
3434
ty::re_scope(rbi) {

0 commit comments

Comments
 (0)