Skip to content

Commit bd4aeef

Browse files
committed
Beginnings of support for constrained types
Programs with constrained types now parse and typecheck, but typestate doesn't check them specially, so the one relevant test case so far is XFAILed. Also rewrote all of the constraint-related data structures in the process (again), for some reason. I got rid of a superfluous data structure in the context that was mapping front-end constraints to resolved constraints, instead handling constraints in the same way in which everything else gets resolved.
1 parent da2a7e5 commit bd4aeef

20 files changed

+606
-366
lines changed

src/comp/driver/rustc.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ fn compile_input(session::session sess, ast::crate_cfg cfg, str input,
134134
bind resolve::resolve_crate(sess, ast_map, crate));
135135
auto freevars =
136136
time(time_passes, "freevar finding",
137-
bind freevars::annotate_freevars(sess, d._0, crate));
138-
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1, ast_map, freevars);
137+
bind freevars::annotate_freevars(sess, d, crate));
138+
auto ty_cx = ty::mk_ctxt(sess, d, ast_map, freevars);
139139
time[()](time_passes, "typechecking",
140140
bind typeck::check_crate(ty_cx, crate));
141141
if (sess.get_opts().run_typestate) {
@@ -200,8 +200,8 @@ fn pretty_print_input(session::session sess, ast::crate_cfg cfg,
200200
case (ppm_typed) {
201201
auto amap = middle::ast_map::map_crate(*crate);
202202
auto d = resolve::resolve_crate(sess, amap, crate);
203-
auto freevars = freevars::annotate_freevars(sess, d._0, crate);
204-
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1, amap, freevars);
203+
auto freevars = freevars::annotate_freevars(sess, d, crate);
204+
auto ty_cx = ty::mk_ctxt(sess, d, amap, freevars);
205205
typeck::check_crate(ty_cx, crate);
206206
ann = rec(pre=ann_paren_for_expr,
207207
post=bind ann_typed_post(ty_cx, _));

src/comp/metadata/tydecode.rs

+58-34
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import std::option;
77
import std::option::none;
88
import std::option::some;
99
import syntax::ast;
10+
import syntax::ast::*;
1011
import ast::respan;
1112
import middle::ty;
1213

@@ -65,13 +66,15 @@ fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
6566
}
6667
}
6768

68-
fn parse_constrs(@pstate st, str_def sd) -> (@ty::constr_def)[] {
69-
let (@ty::constr_def)[] rslt = ~[];
69+
fn parse_constrs(@pstate st, str_def sd) -> (@ty::constr)[] {
70+
let (@ty::constr)[] rslt = ~[];
7071
alt (peek(st) as char) {
7172
case (':') {
72-
do {
73+
do {
7374
next(st);
74-
rslt += ~[parse_constr(st, sd)];
75+
let @ty::constr one = parse_constr[uint](st, sd,
76+
parse_constr_arg);
77+
rslt += ~[one];
7578
} while (peek(st) as char == ';')
7679
}
7780
case (_) { }
@@ -102,40 +105,50 @@ fn parse_path(@pstate st, str_def sd) -> ast::path {
102105
fail "parse_path: ill-formed path";
103106
}
104107

105-
fn parse_constr(@pstate st, str_def sd) -> @ty::constr_def {
106-
let (@ast::constr_arg)[] args = ~[];
108+
type arg_parser[T] = fn (@pstate st, str_def sd)
109+
-> ast::constr_arg_general_[T];
110+
111+
fn parse_constr_arg(@pstate st, str_def sd) -> ast::fn_constr_arg {
112+
alt (peek(st) as char) {
113+
case ('*') {
114+
st.pos += 1u;
115+
ret ast::carg_base;
116+
}
117+
case (?c) {
118+
/* how will we disambiguate between
119+
an arg index and a lit argument? */
120+
if (c >= '0' && c <= '9') {
121+
next(st);
122+
// FIXME
123+
ret ast::carg_ident((c as uint) - 48u);
124+
}
125+
else {
126+
log_err("Lit args are unimplemented");
127+
fail; // FIXME
128+
}
129+
/*
130+
else {
131+
auto lit = parse_lit(st, sd, ',');
132+
args += [respan(st.span, ast::carg_lit(lit))];
133+
}
134+
*/
135+
}
136+
}
137+
}
138+
139+
fn parse_constr[T](@pstate st, str_def sd, arg_parser[T] pser)
140+
-> @ty::constr_general[T] {
107141
auto sp = rec(lo=0u,hi=0u); // FIXME: use a real span
108-
let ast::path pth = parse_path(st, sd);
142+
let (@sp_constr_arg[T])[] args = ~[];
143+
let path pth = parse_path(st, sd);
109144
let char ignore = next(st) as char;
110145
assert(ignore as char == '(');
111146
auto def = parse_def(st, sd);
147+
let constr_arg_general_[T] an_arg;
112148
do {
113-
alt (peek(st) as char) {
114-
case ('*') {
115-
st.pos += 1u;
116-
args += ~[@respan(sp, ast::carg_base)];
117-
}
118-
case (?c) {
119-
/* how will we disambiguate between
120-
an arg index and a lit argument? */
121-
if (c >= '0' && c <= '9') {
122-
// FIXME
123-
args += ~[@respan(sp,
124-
ast::carg_ident((c as uint) - 48u))];
125-
ignore = next(st) as char;
126-
}
127-
else {
128-
log_err("Lit args are unimplemented");
129-
fail; // FIXME
130-
}
131-
/*
132-
else {
133-
auto lit = parse_lit(st, sd, ',');
134-
args += [respan(st.span, ast::carg_lit(lit))];
135-
}
136-
*/
137-
}
138-
}
149+
an_arg = pser(st, sd);
150+
// FIXME use a real span
151+
args += ~[@respan(sp, an_arg)];
139152
ignore = next(st) as char;
140153
} while (ignore == ';');
141154
assert(ignore == ')');
@@ -335,7 +348,7 @@ fn parse_hex(@pstate st) -> uint {
335348
}
336349

337350
fn parse_ty_fn(@pstate st, str_def sd) ->
338-
tup(ty::arg[], ty::t, ast::controlflow, (@ty::constr_def)[]) {
351+
tup(ty::arg[], ty::t, ast::controlflow, (@ty::constr)[]) {
339352
assert (next(st) as char == '[');
340353
let ty::arg[] inputs = ~[];
341354
while (peek(st) as char != ']') {
@@ -384,3 +397,14 @@ fn parse_def_id(&u8[] buf) -> ast::def_id {
384397
auto def_id = uint::parse_buf(def_part_vec, 10u) as int;
385398
ret tup(crate_num, def_id);
386399
}
400+
401+
//
402+
// Local Variables:
403+
// mode: rust
404+
// fill-column: 78;
405+
// indent-tabs-mode: nil
406+
// c-basic-offset: 4
407+
// buffer-file-coding-system: utf-8-unix
408+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
409+
// End:
410+
//

src/comp/metadata/tyencode.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import std::int;
88
import std::uint;
99
import syntax::ast::*;
1010
import middle::ty;
11-
import syntax::print::pprust::lit_to_str;
11+
import syntax::print::pprust::*;
1212
import util::common;
1313

1414
export ctxt;
@@ -199,8 +199,9 @@ fn enc_proto(&ioivec::writer w, proto proto) {
199199
case (proto_fn) { w.write_char('F'); }
200200
}
201201
}
202+
202203
fn enc_ty_fn(&ioivec::writer w, &@ctxt cx, &ty::arg[] args, &ty::t out,
203-
&controlflow cf, &(@ty::constr_def)[] constrs) {
204+
&controlflow cf, &(@ty::constr)[] constrs) {
204205
w.write_char('[');
205206
for (ty::arg arg in args) {
206207
alt (arg.mode) {
@@ -214,7 +215,7 @@ fn enc_ty_fn(&ioivec::writer w, &@ctxt cx, &ty::arg[] args, &ty::t out,
214215
}
215216
w.write_char(']');
216217
auto colon = true;
217-
for (@ty::constr_def c in constrs) {
218+
for (@ty::constr c in constrs) {
218219
if (colon) {
219220
w.write_char(':');
220221
colon = false;
@@ -227,7 +228,8 @@ fn enc_ty_fn(&ioivec::writer w, &@ctxt cx, &ty::arg[] args, &ty::t out,
227228
}
228229

229230
}
230-
fn enc_constr(&ioivec::writer w, &@ctxt cx, &@ty::constr_def c) {
231+
232+
fn enc_constr(&ioivec::writer w, &@ctxt cx, &@ty::constr c) {
231233
w.write_str(path_to_str(c.node.path));
232234
w.write_char('(');
233235
w.write_str(cx.ds(c.node.id));

src/comp/middle/resolve.rs

+13-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
import syntax::ast;
3+
import syntax::ast::*;
34
import ast::ident;
45
import ast::fn_ident;
56
import ast::def;
@@ -19,6 +20,7 @@ import middle::ty::constr_table;
1920
import syntax::visit;
2021
import visit::vt;
2122
import std::ivec;
23+
import std::int;
2224
import std::map::hashmap;
2325
import std::list;
2426
import std::list::list;
@@ -28,6 +30,7 @@ import std::option;
2830
import std::option::some;
2931
import std::option::none;
3032
import std::str;
33+
import syntax::print::pprust::*;
3134

3235
export resolve_crate;
3336
export def_map;
@@ -109,7 +112,6 @@ type def_map = hashmap[node_id, def];
109112
type env =
110113
rec(cstore::cstore cstore,
111114
def_map def_map,
112-
constr_table fn_constrs,
113115
ast_map::map ast_map,
114116
hashmap[ast::node_id, import_state] imports,
115117
hashmap[ast::node_id, @indexed_mod] mod_map,
@@ -124,12 +126,11 @@ tag dir { inside; outside; }
124126

125127
tag namespace { ns_value; ns_type; ns_module; }
126128

127-
fn resolve_crate(session sess, &ast_map::map amap, @ast::crate crate) ->
128-
tup(def_map, constr_table) {
129+
fn resolve_crate(session sess, &ast_map::map amap, @ast::crate crate)
130+
-> def_map {
129131
auto e =
130132
@rec(cstore=sess.get_cstore(),
131133
def_map=new_int_hash[def](),
132-
fn_constrs = new_int_hash[ty::constr_def[]](),
133134
ast_map=amap,
134135
imports=new_int_hash[import_state](),
135136
mod_map=new_int_hash[@indexed_mod](),
@@ -140,7 +141,7 @@ fn resolve_crate(session sess, &ast_map::map amap, @ast::crate crate) ->
140141
resolve_imports(*e);
141142
check_for_collisions(e, *crate);
142143
resolve_names(e, crate);
143-
ret tup(e.def_map, e.fn_constrs);
144+
ret e.def_map;
144145
}
145146

146147

@@ -249,7 +250,7 @@ fn resolve_names(&@env e, &@ast::crate c) {
249250
visit_arm=bind walk_arm(e, _, _, _),
250251
visit_expr=bind walk_expr(e, _, _, _),
251252
visit_ty=bind walk_ty(e, _, _, _),
252-
visit_constr=bind walk_constr(e, _, _, _),
253+
visit_constr=bind walk_constr(e, _, _, _, _, _),
253254
visit_fn=bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
254255
with *visit::default_visitor());
255256
visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v));
@@ -277,10 +278,9 @@ fn resolve_names(&@env e, &@ast::crate c) {
277278
case (_) { }
278279
}
279280
}
280-
fn walk_constr(@env e, &@ast::constr c, &scopes sc, &vt[scopes] v) {
281-
maybe_insert(e, c.node.id,
282-
lookup_path_strict(*e, sc, c.span, c.node.path.node,
283-
ns_value));
281+
fn walk_constr(@env e, &ast::path p, &span sp, node_id id,
282+
&scopes sc, &vt[scopes] v) {
283+
maybe_insert(e, id, lookup_path_strict(*e, sc, sp, p.node, ns_value));
284284
}
285285
fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
286286
for (@ast::pat p in a.pats) { walk_pat(*e, sc, p); }
@@ -411,29 +411,18 @@ fn resolve_constr(@env e, node_id id, &@ast::constr c, &scopes sc,
411411
if (option::is_some(new_def)) {
412412
alt (option::get(new_def)) {
413413
case (ast::def_fn(?pred_id, ast::pure_fn)) {
414-
let ty::constr_general[uint] c_ =
415-
rec(path=c.node.path, args=c.node.args, id=pred_id);
416-
let ty::constr_def new_constr = respan(c.span, c_);
417-
add_constr(e, id, new_constr);
414+
e.def_map.insert(c.node.id, ast::def_fn(pred_id,
415+
ast::pure_fn));
418416
}
419417
case (_) {
420418
e.sess.span_err(c.span,
421419
"Non-predicate in constraint: " +
422-
ast::path_to_str(c.node.path));
420+
path_to_str(c.node.path));
423421
}
424422
}
425423
}
426424
}
427425

428-
fn add_constr(&@env e, node_id id, &ty::constr_def c) {
429-
e.fn_constrs.insert(id,
430-
alt (e.fn_constrs.find(id)) {
431-
case (none) { ~[c] }
432-
case (some(?cs)) { cs + ~[c] }
433-
});
434-
}
435-
436-
437426
// Import resolution
438427
fn resolve_import(&env e, &@ast::view_item it, scopes sc) {
439428
auto defid;

0 commit comments

Comments
 (0)