Skip to content

Commit a08a376

Browse files
catamorphismgraydon
authored andcommitted
Make controlflow part of a function type
Change ty_fn to have a controlflow field. A 'controlflow' is essentially a bit of data that says whether or not this function never returns to the caller (if it never returns, that means it calls "fail" or another "never-returns" function on every control path). Also add syntax for annotating functions that never return: fn foo() -> ! { fail; } for example. Functions marked with ! implicitly have a result type of ty_bot, which is a new type that this commit also adds.
1 parent 3dd2877 commit a08a376

File tree

12 files changed

+213
-121
lines changed

12 files changed

+213
-121
lines changed

src/comp/front/ast.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ type mt = rec(@ty ty, mutability mut);
307307
type ty_field = rec(ident ident, mt mt);
308308
type ty_arg = rec(mode mode, @ty ty);
309309
type ty_method = rec(proto proto, ident ident,
310-
vec[ty_arg] inputs, @ty output);
310+
vec[ty_arg] inputs, @ty output,
311+
controlflow cf);
311312
type ty = spanned[ty_];
312313
tag ty_ {
313314
ty_nil;
@@ -330,7 +331,7 @@ tag ty_ {
330331
ty_chan(@ty);
331332
ty_tup(vec[mt]);
332333
ty_rec(vec[ty_field]);
333-
ty_fn(proto, vec[ty_arg], @ty);
334+
ty_fn(proto, vec[ty_arg], @ty, controlflow);
334335
ty_obj(vec[ty_method]);
335336
ty_path(path, ann);
336337
ty_type;

src/comp/front/creader.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import middle::ty;
1313
import back::x86;
1414
import util::common;
1515
import util::common::span;
16+
import util::common::a_bang;
17+
import util::common::a_ty;
1618

1719
import std::str;
1820
import std::uint;
@@ -47,6 +49,8 @@ type str_def = fn(str) -> ast::def_id;
4749
type pstate = rec(vec[u8] data, int crate,
4850
mutable uint pos, uint len, ty::ctxt tcx);
4951

52+
type ty_or_bang = util::common::ty_or_bang[ty::t];
53+
5054
fn peek(@pstate st) -> u8 {
5155
ret st.data.(st.pos);
5256
}
@@ -64,9 +68,17 @@ fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len,
6468
ret result;
6569
}
6670

71+
fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
72+
alt (peek(st) as char) {
73+
case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
74+
case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
75+
}
76+
}
77+
6778
fn parse_ty(@pstate st, str_def sd) -> ty::t {
6879
alt (next(st) as char) {
6980
case ('n') { ret ty::mk_nil(st.tcx); }
81+
case ('z') { ret ty::mk_bot(st.tcx); }
7082
case ('b') { ret ty::mk_bool(st.tcx); }
7183
case ('i') { ret ty::mk_int(st.tcx); }
7284
case ('u') { ret ty::mk_uint(st.tcx); }
@@ -127,11 +139,11 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
127139
}
128140
case ('F') {
129141
auto func = parse_ty_fn(st, sd);
130-
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1);
142+
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2);
131143
}
132144
case ('W') {
133145
auto func = parse_ty_fn(st, sd);
134-
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1);
146+
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2);
135147
}
136148
case ('N') {
137149
auto abi;
@@ -159,9 +171,10 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
159171
}
160172
auto func = parse_ty_fn(st, sd);
161173
methods += [rec(proto=proto,
162-
ident=name,
163-
inputs=func._0,
164-
output=func._1)];
174+
ident=name,
175+
inputs=func._0,
176+
output=func._1,
177+
cf=func._2)];
165178
}
166179
st.pos += 1u;
167180
ret ty::mk_obj(st.tcx, methods);
@@ -240,7 +253,8 @@ fn parse_hex(@pstate st) -> uint {
240253
ret n;
241254
}
242255

243-
fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t) {
256+
fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
257+
ast::controlflow) {
244258
assert (next(st) as char == '[');
245259
let vec[ty::arg] inputs = [];
246260
while (peek(st) as char != ']') {
@@ -252,7 +266,15 @@ fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t) {
252266
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
253267
}
254268
st.pos = st.pos + 1u;
255-
ret tup(inputs, parse_ty(st, sd));
269+
auto res = parse_ty_or_bang(st, sd);
270+
alt (res) {
271+
case (a_bang[ty::t]) {
272+
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn);
273+
}
274+
case (a_ty[ty::t](?t)) {
275+
ret tup(inputs, t, ast::return);
276+
}
277+
}
256278
}
257279

258280

@@ -550,7 +572,7 @@ fn get_tag_variants(ty::ctxt tcx, ast::def_id def)
550572
auto ctor_ty = item_type(item, external_crate_id, tcx);
551573
let vec[ty::t] arg_tys = [];
552574
alt (ty::struct(tcx, ctor_ty)) {
553-
case (ty::ty_fn(_, ?args, _)) {
575+
case (ty::ty_fn(_, ?args, _, _)) {
554576
for (ty::arg a in args) {
555577
arg_tys += [a.ty];
556578
}

src/comp/front/parser.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import util::common::filename;
1212
import util::common::span;
1313
import util::common::new_str_hash;
1414
import util::data::interner;
15+
import util::common::a_bang;
16+
import util::common::a_ty;
1517

1618
tag restriction {
1719
UNRESTRICTED;
@@ -23,10 +25,7 @@ tag file_type {
2325
SOURCE_FILE;
2426
}
2527

26-
tag ty_or_bang {
27-
a_ty(@ast::ty);
28-
a_bang;
29-
}
28+
type ty_or_bang = util::common::ty_or_bang[@ast::ty];
3029

3130
state type parser =
3231
state obj {
@@ -351,14 +350,24 @@ fn parse_ty_fn(ast::proto proto, &parser p, uint lo)
351350
parse_constrs(p);
352351

353352
let @ast::ty output;
353+
auto cf = ast::return;
354354
if (p.peek() == token::RARROW) {
355355
p.bump();
356-
output = parse_ty(p);
356+
auto tmp = parse_ty_or_bang(p);
357+
alt (tmp) {
358+
case (a_ty[@ast::ty](?t)) {
359+
output = t;
360+
}
361+
case (a_bang[@ast::ty]) {
362+
output = @spanned(lo, inputs.span.hi, ast::ty_bot);
363+
cf = ast::noreturn;
364+
}
365+
}
357366
} else {
358367
output = @spanned(lo, inputs.span.hi, ast::ty_nil);
359368
}
360369

361-
ret ast::ty_fn(proto, inputs.node, output);
370+
ret ast::ty_fn(proto, inputs.node, output, cf);
362371
}
363372

364373
fn parse_proto(&parser p) -> ast::proto {
@@ -377,9 +386,9 @@ fn parse_ty_obj(&parser p, &mutable uint hi) -> ast::ty_ {
377386
auto f = parse_ty_fn(proto, p, flo);
378387
expect(p, token::SEMI);
379388
alt (f) {
380-
case (ast::ty_fn(?proto, ?inputs, ?output)) {
389+
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
381390
ret rec(proto=proto, ident=ident,
382-
inputs=inputs, output=output);
391+
inputs=inputs, output=output, cf=cf);
383392
}
384393
}
385394
fail;
@@ -457,8 +466,8 @@ fn parse_ty_constrs(@ast::ty t, &parser p) -> @ast::ty {
457466

458467
fn parse_ty_or_bang(&parser p) -> ty_or_bang {
459468
alt (p.peek()) {
460-
case (token::NOT) { p.bump(); ret a_bang; }
461-
case (_) { ret a_ty(parse_ty(p)); }
469+
case (token::NOT) { p.bump(); ret a_bang[@ast::ty]; }
470+
case (_) { ret a_ty[@ast::ty](parse_ty(p)); }
462471
}
463472
}
464473

@@ -530,15 +539,15 @@ fn parse_ty(&parser p) -> @ast::ty {
530539
auto flo = p.get_last_lo_pos();
531540
t = parse_ty_fn(ast::proto_fn, p, flo);
532541
alt (t) {
533-
case (ast::ty_fn(_, _, ?out)) {
542+
case (ast::ty_fn(_, _, ?out, _)) {
534543
hi = out.span.hi;
535544
}
536545
}
537546
} else if (eat_word(p, "iter")) {
538547
auto flo = p.get_last_lo_pos();
539548
t = parse_ty_fn(ast::proto_iter, p, flo);
540549
alt (t) {
541-
case (ast::ty_fn(_, _, ?out)) {
550+
case (ast::ty_fn(_, _, ?out, _)) {
542551
hi = out.span.hi;
543552
}
544553
}
@@ -1735,15 +1744,16 @@ fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
17351744
p.bump();
17361745
res = parse_ty_or_bang(p);
17371746
} else {
1738-
res = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
1747+
res = a_ty[@ast::ty](@spanned(inputs.span.lo, inputs.span.hi,
1748+
ast::ty_nil));
17391749
}
17401750

17411751
alt (res) {
1742-
case (a_ty(?t)) {
1752+
case (a_ty[@ast::ty](?t)) {
17431753
ret rec(inputs=inputs.node, output=t,
17441754
purity=purity, cf=ast::return);
17451755
}
1746-
case (a_bang) {
1756+
case (a_bang[@ast::ty]) {
17471757
ret rec(inputs=inputs.node,
17481758
output=@spanned(p.get_lo_pos(),
17491759
p.get_hi_pos(), ast::ty_bot),

src/comp/middle/fold.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ type ast_fold[ENV] =
6767
(fn(&ENV e, &span sp,
6868
ast::proto proto,
6969
&vec[rec(ast::mode mode, @ty ty)] inputs,
70-
&@ty output) -> @ty) fold_ty_fn,
70+
&@ty output, &controlflow cf) -> @ty) fold_ty_fn,
7171

7272
(fn(&ENV e, &span sp, &ast::path p,
7373
&ann a) -> @ty) fold_ty_path,
@@ -423,12 +423,12 @@ fn fold_ty[ENV](&ENV env, &ast_fold[ENV] fld, &@ty t) -> @ty {
423423
let vec[ast::ty_method] meths_ = [];
424424
for (ast::ty_method m in meths) {
425425
auto tfn = fold_ty_fn(env_, fld, t.span, m.proto,
426-
m.inputs, m.output);
426+
m.inputs, m.output, m.cf);
427427
alt (tfn.node) {
428-
case (ast::ty_fn(?p, ?ins, ?out)) {
428+
case (ast::ty_fn(?p, ?ins, ?out, ?cf)) {
429429
vec::push[ast::ty_method]
430430
(meths_, rec(proto=p, inputs=ins,
431-
output=out with m));
431+
output=out, cf=cf with m));
432432
}
433433
}
434434
}
@@ -440,8 +440,8 @@ fn fold_ty[ENV](&ENV env, &ast_fold[ENV] fld, &@ty t) -> @ty {
440440
ret fld.fold_ty_path(env_, t.span, pth_, ann);
441441
}
442442

443-
case (ast::ty_fn(?proto, ?inputs, ?output)) {
444-
ret fold_ty_fn(env_, fld, t.span, proto, inputs, output);
443+
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
444+
ret fold_ty_fn(env_, fld, t.span, proto, inputs, output, cf);
445445
}
446446

447447
case (ast::ty_chan(?ty)) {
@@ -459,15 +459,15 @@ fn fold_ty[ENV](&ENV env, &ast_fold[ENV] fld, &@ty t) -> @ty {
459459
fn fold_ty_fn[ENV](&ENV env, &ast_fold[ENV] fld, &span sp,
460460
ast::proto proto,
461461
&vec[rec(ast::mode mode, @ty ty)] inputs,
462-
&@ty output) -> @ty {
462+
&@ty output, &controlflow cf) -> @ty {
463463
auto output_ = fold_ty(env, fld, output);
464464
let vec[rec(ast::mode mode, @ty ty)] inputs_ = [];
465465
for (rec(ast::mode mode, @ty ty) input in inputs) {
466466
auto ty_ = fold_ty(env, fld, input.ty);
467467
auto input_ = rec(ty=ty_ with input);
468468
inputs_ += [input_];
469469
}
470-
ret fld.fold_ty_fn(env, sp, proto, inputs_, output_);
470+
ret fld.fold_ty_fn(env, sp, proto, inputs_, output_, cf);
471471
}
472472

473473
fn fold_decl[ENV](&ENV env, &ast_fold[ENV] fld, &@decl d) -> @decl {
@@ -1264,8 +1264,8 @@ fn identity_fold_ty_obj[ENV](&ENV env, &span sp,
12641264
fn identity_fold_ty_fn[ENV](&ENV env, &span sp,
12651265
ast::proto proto,
12661266
&vec[rec(ast::mode mode, @ty ty)] inputs,
1267-
&@ty output) -> @ty {
1268-
ret @respan(sp, ast::ty_fn(proto, inputs, output));
1267+
&@ty output, &controlflow cf) -> @ty {
1268+
ret @respan(sp, ast::ty_fn(proto, inputs, output, cf));
12691269
}
12701270

12711271
fn identity_fold_ty_path[ENV](&ENV env, &span sp, &ast::path p,
@@ -1742,7 +1742,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
17421742
fold_ty_tup = bind identity_fold_ty_tup[ENV](_,_,_),
17431743
fold_ty_rec = bind identity_fold_ty_rec[ENV](_,_,_),
17441744
fold_ty_obj = bind identity_fold_ty_obj[ENV](_,_,_),
1745-
fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_),
1745+
fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_,_),
17461746
fold_ty_path = bind identity_fold_ty_path[ENV](_,_,_,_),
17471747
fold_ty_chan = bind identity_fold_ty_chan[ENV](_,_,_),
17481748
fold_ty_port = bind identity_fold_ty_port[ENV](_,_,_),

src/comp/middle/metadata.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ mod Encode {
144144
fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
145145
alt (st) {
146146
case (ty::ty_nil) { w.write_char('n'); }
147+
case (ty::ty_bot) { w.write_char('z'); }
147148
case (ty::ty_bool) { w.write_char('b'); }
148149
case (ty::ty_int) { w.write_char('i'); }
149150
case (ty::ty_uint) { w.write_char('u'); }
@@ -193,9 +194,9 @@ mod Encode {
193194
}
194195
w.write_char(']');
195196
}
196-
case (ty::ty_fn(?proto,?args,?out)) {
197+
case (ty::ty_fn(?proto,?args,?out,?cf)) {
197198
enc_proto(w, proto);
198-
enc_ty_fn(w, cx, args, out);
199+
enc_ty_fn(w, cx, args, out, cf);
199200
}
200201
case (ty::ty_native_fn(?abi,?args,?out)) {
201202
w.write_char('N');
@@ -207,14 +208,14 @@ mod Encode {
207208
case (ast::native_abi_cdecl) { w.write_char('c'); }
208209
case (ast::native_abi_llvm) { w.write_char('l'); }
209210
}
210-
enc_ty_fn(w, cx, args, out);
211+
enc_ty_fn(w, cx, args, out, ast::return);
211212
}
212213
case (ty::ty_obj(?methods)) {
213214
w.write_str("O[");
214215
for (ty::method m in methods) {
215216
enc_proto(w, m.proto);
216217
w.write_str(m.ident);
217-
enc_ty_fn(w, cx, m.inputs, m.output);
218+
enc_ty_fn(w, cx, m.inputs, m.output, m.cf);
218219
}
219220
w.write_char(']');
220221
}
@@ -250,14 +251,22 @@ mod Encode {
250251
}
251252
}
252253

253-
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out) {
254+
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out,
255+
&ast::controlflow cf) {
254256
w.write_char('[');
255257
for (ty::arg arg in args) {
256258
if (arg.mode == ty::mo_alias) { w.write_char('&'); }
257259
enc_ty(w, cx, arg.ty);
258260
}
259261
w.write_char(']');
260-
enc_ty(w, cx, out);
262+
alt (cf) {
263+
case (ast::noreturn) {
264+
w.write_char('!');
265+
}
266+
case (_) {
267+
enc_ty(w, cx, out);
268+
}
269+
}
261270
}
262271

263272
}

0 commit comments

Comments
 (0)