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.
This commit is contained in:
parent
3dd2877975
commit
a08a376d6e
12 changed files with 213 additions and 121 deletions
|
@ -307,7 +307,8 @@ type mt = rec(@ty ty, mutability mut);
|
|||
type ty_field = rec(ident ident, mt mt);
|
||||
type ty_arg = rec(mode mode, @ty ty);
|
||||
type ty_method = rec(proto proto, ident ident,
|
||||
vec[ty_arg] inputs, @ty output);
|
||||
vec[ty_arg] inputs, @ty output,
|
||||
controlflow cf);
|
||||
type ty = spanned[ty_];
|
||||
tag ty_ {
|
||||
ty_nil;
|
||||
|
@ -330,7 +331,7 @@ tag ty_ {
|
|||
ty_chan(@ty);
|
||||
ty_tup(vec[mt]);
|
||||
ty_rec(vec[ty_field]);
|
||||
ty_fn(proto, vec[ty_arg], @ty);
|
||||
ty_fn(proto, vec[ty_arg], @ty, controlflow);
|
||||
ty_obj(vec[ty_method]);
|
||||
ty_path(path, ann);
|
||||
ty_type;
|
||||
|
|
|
@ -13,6 +13,8 @@ import middle::ty;
|
|||
import back::x86;
|
||||
import util::common;
|
||||
import util::common::span;
|
||||
import util::common::a_bang;
|
||||
import util::common::a_ty;
|
||||
|
||||
import std::str;
|
||||
import std::uint;
|
||||
|
@ -47,6 +49,8 @@ type str_def = fn(str) -> ast::def_id;
|
|||
type pstate = rec(vec[u8] data, int crate,
|
||||
mutable uint pos, uint len, ty::ctxt tcx);
|
||||
|
||||
type ty_or_bang = util::common::ty_or_bang[ty::t];
|
||||
|
||||
fn peek(@pstate st) -> u8 {
|
||||
ret st.data.(st.pos);
|
||||
}
|
||||
|
@ -64,9 +68,17 @@ fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len,
|
|||
ret result;
|
||||
}
|
||||
|
||||
fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
|
||||
alt (peek(st) as char) {
|
||||
case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
|
||||
case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_ty(@pstate st, str_def sd) -> ty::t {
|
||||
alt (next(st) as char) {
|
||||
case ('n') { ret ty::mk_nil(st.tcx); }
|
||||
case ('z') { ret ty::mk_bot(st.tcx); }
|
||||
case ('b') { ret ty::mk_bool(st.tcx); }
|
||||
case ('i') { ret ty::mk_int(st.tcx); }
|
||||
case ('u') { ret ty::mk_uint(st.tcx); }
|
||||
|
@ -127,11 +139,11 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
|
|||
}
|
||||
case ('F') {
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2);
|
||||
}
|
||||
case ('W') {
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1);
|
||||
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2);
|
||||
}
|
||||
case ('N') {
|
||||
auto abi;
|
||||
|
@ -159,9 +171,10 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
|
|||
}
|
||||
auto func = parse_ty_fn(st, sd);
|
||||
methods += [rec(proto=proto,
|
||||
ident=name,
|
||||
inputs=func._0,
|
||||
output=func._1)];
|
||||
ident=name,
|
||||
inputs=func._0,
|
||||
output=func._1,
|
||||
cf=func._2)];
|
||||
}
|
||||
st.pos += 1u;
|
||||
ret ty::mk_obj(st.tcx, methods);
|
||||
|
@ -240,7 +253,8 @@ fn parse_hex(@pstate st) -> uint {
|
|||
ret n;
|
||||
}
|
||||
|
||||
fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t) {
|
||||
fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
|
||||
ast::controlflow) {
|
||||
assert (next(st) as char == '[');
|
||||
let vec[ty::arg] inputs = [];
|
||||
while (peek(st) as char != ']') {
|
||||
|
@ -252,7 +266,15 @@ fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t) {
|
|||
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
|
||||
}
|
||||
st.pos = st.pos + 1u;
|
||||
ret tup(inputs, parse_ty(st, sd));
|
||||
auto res = parse_ty_or_bang(st, sd);
|
||||
alt (res) {
|
||||
case (a_bang[ty::t]) {
|
||||
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn);
|
||||
}
|
||||
case (a_ty[ty::t](?t)) {
|
||||
ret tup(inputs, t, ast::return);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -550,7 +572,7 @@ fn get_tag_variants(ty::ctxt tcx, ast::def_id def)
|
|||
auto ctor_ty = item_type(item, external_crate_id, tcx);
|
||||
let vec[ty::t] arg_tys = [];
|
||||
alt (ty::struct(tcx, ctor_ty)) {
|
||||
case (ty::ty_fn(_, ?args, _)) {
|
||||
case (ty::ty_fn(_, ?args, _, _)) {
|
||||
for (ty::arg a in args) {
|
||||
arg_tys += [a.ty];
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import util::common::filename;
|
|||
import util::common::span;
|
||||
import util::common::new_str_hash;
|
||||
import util::data::interner;
|
||||
import util::common::a_bang;
|
||||
import util::common::a_ty;
|
||||
|
||||
tag restriction {
|
||||
UNRESTRICTED;
|
||||
|
@ -23,10 +25,7 @@ tag file_type {
|
|||
SOURCE_FILE;
|
||||
}
|
||||
|
||||
tag ty_or_bang {
|
||||
a_ty(@ast::ty);
|
||||
a_bang;
|
||||
}
|
||||
type ty_or_bang = util::common::ty_or_bang[@ast::ty];
|
||||
|
||||
state type parser =
|
||||
state obj {
|
||||
|
@ -351,14 +350,24 @@ fn parse_ty_fn(ast::proto proto, &parser p, uint lo)
|
|||
parse_constrs(p);
|
||||
|
||||
let @ast::ty output;
|
||||
auto cf = ast::return;
|
||||
if (p.peek() == token::RARROW) {
|
||||
p.bump();
|
||||
output = parse_ty(p);
|
||||
auto tmp = parse_ty_or_bang(p);
|
||||
alt (tmp) {
|
||||
case (a_ty[@ast::ty](?t)) {
|
||||
output = t;
|
||||
}
|
||||
case (a_bang[@ast::ty]) {
|
||||
output = @spanned(lo, inputs.span.hi, ast::ty_bot);
|
||||
cf = ast::noreturn;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output = @spanned(lo, inputs.span.hi, ast::ty_nil);
|
||||
}
|
||||
|
||||
ret ast::ty_fn(proto, inputs.node, output);
|
||||
ret ast::ty_fn(proto, inputs.node, output, cf);
|
||||
}
|
||||
|
||||
fn parse_proto(&parser p) -> ast::proto {
|
||||
|
@ -377,9 +386,9 @@ fn parse_ty_obj(&parser p, &mutable uint hi) -> ast::ty_ {
|
|||
auto f = parse_ty_fn(proto, p, flo);
|
||||
expect(p, token::SEMI);
|
||||
alt (f) {
|
||||
case (ast::ty_fn(?proto, ?inputs, ?output)) {
|
||||
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
|
||||
ret rec(proto=proto, ident=ident,
|
||||
inputs=inputs, output=output);
|
||||
inputs=inputs, output=output, cf=cf);
|
||||
}
|
||||
}
|
||||
fail;
|
||||
|
@ -457,8 +466,8 @@ fn parse_ty_constrs(@ast::ty t, &parser p) -> @ast::ty {
|
|||
|
||||
fn parse_ty_or_bang(&parser p) -> ty_or_bang {
|
||||
alt (p.peek()) {
|
||||
case (token::NOT) { p.bump(); ret a_bang; }
|
||||
case (_) { ret a_ty(parse_ty(p)); }
|
||||
case (token::NOT) { p.bump(); ret a_bang[@ast::ty]; }
|
||||
case (_) { ret a_ty[@ast::ty](parse_ty(p)); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,7 +539,7 @@ fn parse_ty(&parser p) -> @ast::ty {
|
|||
auto flo = p.get_last_lo_pos();
|
||||
t = parse_ty_fn(ast::proto_fn, p, flo);
|
||||
alt (t) {
|
||||
case (ast::ty_fn(_, _, ?out)) {
|
||||
case (ast::ty_fn(_, _, ?out, _)) {
|
||||
hi = out.span.hi;
|
||||
}
|
||||
}
|
||||
|
@ -538,7 +547,7 @@ fn parse_ty(&parser p) -> @ast::ty {
|
|||
auto flo = p.get_last_lo_pos();
|
||||
t = parse_ty_fn(ast::proto_iter, p, flo);
|
||||
alt (t) {
|
||||
case (ast::ty_fn(_, _, ?out)) {
|
||||
case (ast::ty_fn(_, _, ?out, _)) {
|
||||
hi = out.span.hi;
|
||||
}
|
||||
}
|
||||
|
@ -1735,15 +1744,16 @@ fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
|
|||
p.bump();
|
||||
res = parse_ty_or_bang(p);
|
||||
} else {
|
||||
res = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
|
||||
res = a_ty[@ast::ty](@spanned(inputs.span.lo, inputs.span.hi,
|
||||
ast::ty_nil));
|
||||
}
|
||||
|
||||
alt (res) {
|
||||
case (a_ty(?t)) {
|
||||
case (a_ty[@ast::ty](?t)) {
|
||||
ret rec(inputs=inputs.node, output=t,
|
||||
purity=purity, cf=ast::return);
|
||||
}
|
||||
case (a_bang) {
|
||||
case (a_bang[@ast::ty]) {
|
||||
ret rec(inputs=inputs.node,
|
||||
output=@spanned(p.get_lo_pos(),
|
||||
p.get_hi_pos(), ast::ty_bot),
|
||||
|
|
|
@ -67,7 +67,7 @@ type ast_fold[ENV] =
|
|||
(fn(&ENV e, &span sp,
|
||||
ast::proto proto,
|
||||
&vec[rec(ast::mode mode, @ty ty)] inputs,
|
||||
&@ty output) -> @ty) fold_ty_fn,
|
||||
&@ty output, &controlflow cf) -> @ty) fold_ty_fn,
|
||||
|
||||
(fn(&ENV e, &span sp, &ast::path p,
|
||||
&ann a) -> @ty) fold_ty_path,
|
||||
|
@ -423,12 +423,12 @@ fn fold_ty[ENV](&ENV env, &ast_fold[ENV] fld, &@ty t) -> @ty {
|
|||
let vec[ast::ty_method] meths_ = [];
|
||||
for (ast::ty_method m in meths) {
|
||||
auto tfn = fold_ty_fn(env_, fld, t.span, m.proto,
|
||||
m.inputs, m.output);
|
||||
m.inputs, m.output, m.cf);
|
||||
alt (tfn.node) {
|
||||
case (ast::ty_fn(?p, ?ins, ?out)) {
|
||||
case (ast::ty_fn(?p, ?ins, ?out, ?cf)) {
|
||||
vec::push[ast::ty_method]
|
||||
(meths_, rec(proto=p, inputs=ins,
|
||||
output=out with m));
|
||||
output=out, cf=cf with m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -440,8 +440,8 @@ fn fold_ty[ENV](&ENV env, &ast_fold[ENV] fld, &@ty t) -> @ty {
|
|||
ret fld.fold_ty_path(env_, t.span, pth_, ann);
|
||||
}
|
||||
|
||||
case (ast::ty_fn(?proto, ?inputs, ?output)) {
|
||||
ret fold_ty_fn(env_, fld, t.span, proto, inputs, output);
|
||||
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
|
||||
ret fold_ty_fn(env_, fld, t.span, proto, inputs, output, cf);
|
||||
}
|
||||
|
||||
case (ast::ty_chan(?ty)) {
|
||||
|
@ -459,7 +459,7 @@ fn fold_ty[ENV](&ENV env, &ast_fold[ENV] fld, &@ty t) -> @ty {
|
|||
fn fold_ty_fn[ENV](&ENV env, &ast_fold[ENV] fld, &span sp,
|
||||
ast::proto proto,
|
||||
&vec[rec(ast::mode mode, @ty ty)] inputs,
|
||||
&@ty output) -> @ty {
|
||||
&@ty output, &controlflow cf) -> @ty {
|
||||
auto output_ = fold_ty(env, fld, output);
|
||||
let vec[rec(ast::mode mode, @ty ty)] inputs_ = [];
|
||||
for (rec(ast::mode mode, @ty ty) input in inputs) {
|
||||
|
@ -467,7 +467,7 @@ fn fold_ty_fn[ENV](&ENV env, &ast_fold[ENV] fld, &span sp,
|
|||
auto input_ = rec(ty=ty_ with input);
|
||||
inputs_ += [input_];
|
||||
}
|
||||
ret fld.fold_ty_fn(env, sp, proto, inputs_, output_);
|
||||
ret fld.fold_ty_fn(env, sp, proto, inputs_, output_, cf);
|
||||
}
|
||||
|
||||
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,
|
|||
fn identity_fold_ty_fn[ENV](&ENV env, &span sp,
|
||||
ast::proto proto,
|
||||
&vec[rec(ast::mode mode, @ty ty)] inputs,
|
||||
&@ty output) -> @ty {
|
||||
ret @respan(sp, ast::ty_fn(proto, inputs, output));
|
||||
&@ty output, &controlflow cf) -> @ty {
|
||||
ret @respan(sp, ast::ty_fn(proto, inputs, output, cf));
|
||||
}
|
||||
|
||||
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] {
|
|||
fold_ty_tup = bind identity_fold_ty_tup[ENV](_,_,_),
|
||||
fold_ty_rec = bind identity_fold_ty_rec[ENV](_,_,_),
|
||||
fold_ty_obj = bind identity_fold_ty_obj[ENV](_,_,_),
|
||||
fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_),
|
||||
fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_,_),
|
||||
fold_ty_path = bind identity_fold_ty_path[ENV](_,_,_,_),
|
||||
fold_ty_chan = bind identity_fold_ty_chan[ENV](_,_,_),
|
||||
fold_ty_port = bind identity_fold_ty_port[ENV](_,_,_),
|
||||
|
|
|
@ -144,6 +144,7 @@ mod Encode {
|
|||
fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
|
||||
alt (st) {
|
||||
case (ty::ty_nil) { w.write_char('n'); }
|
||||
case (ty::ty_bot) { w.write_char('z'); }
|
||||
case (ty::ty_bool) { w.write_char('b'); }
|
||||
case (ty::ty_int) { w.write_char('i'); }
|
||||
case (ty::ty_uint) { w.write_char('u'); }
|
||||
|
@ -193,9 +194,9 @@ mod Encode {
|
|||
}
|
||||
w.write_char(']');
|
||||
}
|
||||
case (ty::ty_fn(?proto,?args,?out)) {
|
||||
case (ty::ty_fn(?proto,?args,?out,?cf)) {
|
||||
enc_proto(w, proto);
|
||||
enc_ty_fn(w, cx, args, out);
|
||||
enc_ty_fn(w, cx, args, out, cf);
|
||||
}
|
||||
case (ty::ty_native_fn(?abi,?args,?out)) {
|
||||
w.write_char('N');
|
||||
|
@ -207,14 +208,14 @@ mod Encode {
|
|||
case (ast::native_abi_cdecl) { w.write_char('c'); }
|
||||
case (ast::native_abi_llvm) { w.write_char('l'); }
|
||||
}
|
||||
enc_ty_fn(w, cx, args, out);
|
||||
enc_ty_fn(w, cx, args, out, ast::return);
|
||||
}
|
||||
case (ty::ty_obj(?methods)) {
|
||||
w.write_str("O[");
|
||||
for (ty::method m in methods) {
|
||||
enc_proto(w, m.proto);
|
||||
w.write_str(m.ident);
|
||||
enc_ty_fn(w, cx, m.inputs, m.output);
|
||||
enc_ty_fn(w, cx, m.inputs, m.output, m.cf);
|
||||
}
|
||||
w.write_char(']');
|
||||
}
|
||||
|
@ -250,14 +251,22 @@ mod Encode {
|
|||
}
|
||||
}
|
||||
|
||||
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out) {
|
||||
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out,
|
||||
&ast::controlflow cf) {
|
||||
w.write_char('[');
|
||||
for (ty::arg arg in args) {
|
||||
if (arg.mode == ty::mo_alias) { w.write_char('&'); }
|
||||
enc_ty(w, cx, arg.ty);
|
||||
}
|
||||
w.write_char(']');
|
||||
enc_ty(w, cx, out);
|
||||
alt (cf) {
|
||||
case (ast::noreturn) {
|
||||
w.write_char('!');
|
||||
}
|
||||
case (_) {
|
||||
enc_ty(w, cx, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -807,7 +807,7 @@ fn type_of_inner(&@crate_ctxt cx, &ast::span sp, &ty::t t) -> TypeRef {
|
|||
}
|
||||
llty = T_struct(tys);
|
||||
}
|
||||
case (ty::ty_fn(?proto, ?args, ?out)) {
|
||||
case (ty::ty_fn(?proto, ?args, ?out, _)) {
|
||||
llty = T_fn_pair(cx.tn, type_of_fn(cx, sp, proto, args, out, 0u));
|
||||
}
|
||||
case (ty::ty_native_fn(?abi, ?args, ?out)) {
|
||||
|
@ -882,7 +882,7 @@ fn type_of_arg(@local_ctxt cx, &ast::span sp, &ty::arg arg) -> TypeRef {
|
|||
fn type_of_ty_param_count_and_ty(@local_ctxt lcx, &ast::span sp,
|
||||
&ty::ty_param_count_and_ty tpt) -> TypeRef {
|
||||
alt (ty::struct(lcx.ccx.tcx, tpt._1)) {
|
||||
case (ty::ty_fn(?proto, ?inputs, ?output)) {
|
||||
case (ty::ty_fn(?proto, ?inputs, ?output, _)) {
|
||||
auto llfnty = type_of_fn(lcx.ccx, sp, proto,
|
||||
inputs, output, tpt._0);
|
||||
ret T_fn_pair(lcx.ccx.tn, llfnty);
|
||||
|
@ -2114,7 +2114,7 @@ fn make_free_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
|
|||
rslt = trans_non_gc_free(cx_, b);
|
||||
}
|
||||
|
||||
case (ty::ty_fn(_,_,_)) {
|
||||
case (ty::ty_fn(_,_,_,_)) {
|
||||
|
||||
auto box_cell =
|
||||
cx.build.GEP(v0,
|
||||
|
@ -2186,7 +2186,7 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
|
|||
rslt = decr_refcnt_maybe_free(cx, box_cell, v0, t);
|
||||
}
|
||||
|
||||
case (ty::ty_fn(_,_,_)) {
|
||||
case (ty::ty_fn(_,_,_,_)) {
|
||||
|
||||
auto box_cell =
|
||||
cx.build.GEP(v0,
|
||||
|
@ -2650,7 +2650,7 @@ fn iter_structural_ty_full(&@block_ctxt cx,
|
|||
// N-ary variant.
|
||||
auto fn_ty = variant.ctor_ty;
|
||||
alt (ty::struct(bcx.fcx.lcx.ccx.tcx, fn_ty)) {
|
||||
case (ty::ty_fn(_, ?args, _)) {
|
||||
case (ty::ty_fn(_, ?args, _, _)) {
|
||||
auto j = 0;
|
||||
for (ty::arg a in args) {
|
||||
auto v = [C_int(0), C_int(j as int)];
|
||||
|
@ -2700,7 +2700,7 @@ fn iter_structural_ty_full(&@block_ctxt cx,
|
|||
|
||||
ret res(next_cx, C_nil());
|
||||
}
|
||||
case (ty::ty_fn(_,_,_)) {
|
||||
case (ty::ty_fn(_,_,_,_)) {
|
||||
auto box_cell_a =
|
||||
cx.build.GEP(av,
|
||||
[C_int(0),
|
||||
|
@ -4386,7 +4386,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, &ast::ann ann) -> lval_result {
|
|||
case (ast::def_variant(?tid, ?vid)) {
|
||||
auto v_tyt = ty::lookup_item_type(cx.fcx.lcx.ccx.tcx, vid);
|
||||
alt (ty::struct(cx.fcx.lcx.ccx.tcx, v_tyt._1)) {
|
||||
case (ty::ty_fn(_, _, _)) {
|
||||
case (ty::ty_fn(_, _, _, _)) {
|
||||
// N-ary variant.
|
||||
ret lval_generic_fn(cx, v_tyt, vid, ann);
|
||||
}
|
||||
|
@ -4429,7 +4429,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, &ast::ann ann) -> lval_result {
|
|||
ret lval_generic_fn(cx, tyt, did, ann);
|
||||
}
|
||||
case (_) {
|
||||
cx.fcx.lcx.ccx.sess.unimpl("def variant in trans");
|
||||
cx.fcx.lcx.ccx.sess.span_unimpl(cx.sp, "def variant in trans");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6578,7 +6578,7 @@ fn is_terminated(&@block_ctxt cx) -> bool {
|
|||
|
||||
fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
|
||||
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx.node_types, ann))) {
|
||||
case (ty::ty_fn(_, ?arg_tys, _)) {
|
||||
case (ty::ty_fn(_, ?arg_tys, _, _)) {
|
||||
ret arg_tys;
|
||||
}
|
||||
}
|
||||
|
@ -6587,7 +6587,7 @@ fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
|
|||
|
||||
fn ret_ty_of_fn_ty(&@crate_ctxt ccx, ty::t t) -> ty::t {
|
||||
alt (ty::struct(ccx.tcx, t)) {
|
||||
case (ty::ty_fn(_, _, ?ret_ty)) {
|
||||
case (ty::ty_fn(_, _, ?ret_ty, _)) {
|
||||
ret ret_ty;
|
||||
}
|
||||
}
|
||||
|
@ -6739,7 +6739,7 @@ fn trans_vtbl(@local_ctxt cx,
|
|||
|
||||
auto llfnty = T_nil();
|
||||
alt (ty::struct(cx.ccx.tcx, node_ann_type(cx.ccx, m.node.ann))) {
|
||||
case (ty::ty_fn(?proto, ?inputs, ?output)) {
|
||||
case (ty::ty_fn(?proto, ?inputs, ?output, _)) {
|
||||
llfnty = type_of_fn_full(cx.ccx, m.span, proto,
|
||||
some[TypeRef](llself_ty),
|
||||
inputs, output,
|
||||
|
@ -7099,7 +7099,7 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &ast::span sp,
|
|||
auto llfty;
|
||||
auto llpairty;
|
||||
alt (ty::struct(ccx.tcx, node_ann_type(ccx, ann))) {
|
||||
case (ty::ty_fn(?proto, ?inputs, ?output)) {
|
||||
case (ty::ty_fn(?proto, ?inputs, ?output, _)) {
|
||||
llfty = type_of_fn(ccx, sp, proto, inputs, output,
|
||||
vec::len[ast::ty_param](ty_params));
|
||||
llpairty = T_fn_pair(ccx.tn, llfty);
|
||||
|
|
|
@ -381,20 +381,16 @@ fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow {
|
|||
}
|
||||
}
|
||||
|
||||
/* conservative approximation: uses the mapping if e refers to a known
|
||||
function or method, assumes returning otherwise.
|
||||
There's no case for fail b/c we assume e is the callee and it
|
||||
seems unlikely that one would apply "fail" to arguments. */
|
||||
/* Use e's type to determine whether it returns.
|
||||
If it has a function type with a ! annotation,
|
||||
the answer is noreturn. */
|
||||
fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
|
||||
auto f = expr_ann(e).id;
|
||||
alt (ccx.tcx.def_map.find(f)) {
|
||||
case (some[def](def_fn(?d))) {
|
||||
ret controlflow_def_id(ccx, d);
|
||||
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx.node_types,
|
||||
expr_ann(e)))) {
|
||||
case (ty::ty_fn(_,_,_,?cf)) {
|
||||
ret cf;
|
||||
}
|
||||
case (some[def](def_obj_field(?d))) {
|
||||
ret controlflow_def_id(ccx, d);
|
||||
}
|
||||
case (_) {
|
||||
case (_) {
|
||||
ret return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import std::option::some;
|
|||
import driver::session;
|
||||
import front::ast;
|
||||
import front::ast::mutability;
|
||||
import front::ast::controlflow;
|
||||
import front::creader;
|
||||
import middle::metadata;
|
||||
import util::common;
|
||||
|
@ -49,7 +50,8 @@ type field = rec(ast::ident ident, mt mt);
|
|||
type method = rec(ast::proto proto,
|
||||
ast::ident ident,
|
||||
vec[arg] inputs,
|
||||
t output);
|
||||
t output,
|
||||
controlflow cf);
|
||||
|
||||
tag any_item {
|
||||
any_item_rust(@ast::item);
|
||||
|
@ -76,7 +78,7 @@ type ty_ctxt = ctxt; // Needed for disambiguation from unify::ctxt.
|
|||
// Convert from method type to function type. Pretty easy; we just drop
|
||||
// 'ident'.
|
||||
fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
|
||||
ret mk_fn(cx, m.proto, m.inputs, m.output);
|
||||
ret mk_fn(cx, m.proto, m.inputs, m.output, m.cf);
|
||||
}
|
||||
|
||||
// Never construct these manually. These are interned.
|
||||
|
@ -113,7 +115,7 @@ tag sty {
|
|||
ty_task;
|
||||
ty_tup(vec[mt]);
|
||||
ty_rec(vec[field]);
|
||||
ty_fn(ast::proto, vec[arg], t);
|
||||
ty_fn(ast::proto, vec[arg], t, controlflow);
|
||||
ty_native_fn(ast::native_abi, vec[arg], t);
|
||||
ty_obj(vec[method]);
|
||||
ty_var(int); // ephemeral type var
|
||||
|
@ -135,6 +137,7 @@ type unify_handler = obj {
|
|||
|
||||
tag type_err {
|
||||
terr_mismatch;
|
||||
terr_controlflow_mismatch;
|
||||
terr_box_mutability;
|
||||
terr_vec_mutability;
|
||||
terr_tuple_size(uint, uint);
|
||||
|
@ -358,7 +361,7 @@ fn mk_raw_ty(&ctxt cx, &sty st, &option::t[str] cname) -> raw_t {
|
|||
}
|
||||
}
|
||||
|
||||
case (ty_fn(_, ?args, ?tt)) {
|
||||
case (ty_fn(_, ?args, ?tt, _)) {
|
||||
derive_flags_sig(cx, has_params, has_bound_params,
|
||||
has_vars, has_locals, args, tt);
|
||||
}
|
||||
|
@ -462,8 +465,9 @@ fn mk_imm_tup(&ctxt cx, &vec[t] tys) -> t {
|
|||
|
||||
fn mk_rec(&ctxt cx, &vec[field] fs) -> t { ret gen_ty(cx, ty_rec(fs)); }
|
||||
|
||||
fn mk_fn(&ctxt cx, &ast::proto proto, &vec[arg] args, &t ty) -> t {
|
||||
ret gen_ty(cx, ty_fn(proto, args, ty));
|
||||
fn mk_fn(&ctxt cx, &ast::proto proto, &vec[arg] args, &t ty,
|
||||
&controlflow cf) -> t {
|
||||
ret gen_ty(cx, ty_fn(proto, args, ty, cf));
|
||||
}
|
||||
|
||||
fn mk_native_fn(&ctxt cx, &ast::native_abi abi, &vec[arg] args, &t ty) -> t {
|
||||
|
@ -635,7 +639,7 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
|
|||
}
|
||||
}
|
||||
|
||||
case (ty_fn(?proto, ?inputs, ?output)) {
|
||||
case (ty_fn(?proto, ?inputs, ?output, _)) {
|
||||
s += fn_to_str(cx, proto, none[ast::ident], inputs, output);
|
||||
}
|
||||
|
||||
|
@ -721,7 +725,7 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
|
|||
walk_ty(cx, walker, fl.mt.ty);
|
||||
}
|
||||
}
|
||||
case (ty_fn(?proto, ?args, ?ret_ty)) {
|
||||
case (ty_fn(?proto, ?args, ?ret_ty, _)) {
|
||||
for (arg a in args) {
|
||||
walk_ty(cx, walker, a.ty);
|
||||
}
|
||||
|
@ -805,14 +809,14 @@ fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
|
|||
}
|
||||
ty = copy_cname(cx, mk_rec(cx, new_fields), ty);
|
||||
}
|
||||
case (ty_fn(?proto, ?args, ?ret_ty)) {
|
||||
case (ty_fn(?proto, ?args, ?ret_ty, ?cf)) {
|
||||
let vec[arg] new_args = [];
|
||||
for (arg a in args) {
|
||||
auto new_ty = fold_ty(cx, fld, a.ty);
|
||||
new_args += [rec(mode=a.mode, ty=new_ty)];
|
||||
}
|
||||
ty = copy_cname(cx, mk_fn(cx, proto, new_args,
|
||||
fold_ty(cx, fld, ret_ty)), ty);
|
||||
fold_ty(cx, fld, ret_ty), cf), ty);
|
||||
}
|
||||
case (ty_native_fn(?abi, ?args, ?ret_ty)) {
|
||||
let vec[arg] new_args = [];
|
||||
|
@ -832,8 +836,8 @@ fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
|
|||
ty=fold_ty(cx, fld, a.ty))];
|
||||
}
|
||||
new_methods += [rec(proto=m.proto, ident=m.ident,
|
||||
inputs=new_args,
|
||||
output=fold_ty(cx, fld, m.output))];
|
||||
inputs=new_args,
|
||||
output=fold_ty(cx, fld, m.output), cf=m.cf)];
|
||||
}
|
||||
ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
|
||||
}
|
||||
|
@ -885,7 +889,7 @@ fn type_is_structural(&ctxt cx, &t ty) -> bool {
|
|||
case (ty_tup(_)) { ret true; }
|
||||
case (ty_rec(_)) { ret true; }
|
||||
case (ty_tag(_,_)) { ret true; }
|
||||
case (ty_fn(_,_,_)) { ret true; }
|
||||
case (ty_fn(_,_,_,_)) { ret true; }
|
||||
case (ty_obj(_)) { ret true; }
|
||||
case (_) { ret false; }
|
||||
}
|
||||
|
@ -1206,7 +1210,7 @@ fn hash_type_structure(&sty st) -> uint {
|
|||
}
|
||||
ret h;
|
||||
}
|
||||
case (ty_fn(_, ?args, ?rty)) { ret hash_fn(25u, args, rty); }
|
||||
case (ty_fn(_, ?args, ?rty, _)) { ret hash_fn(25u, args, rty); }
|
||||
case (ty_native_fn(_, ?args, ?rty)) { ret hash_fn(26u, args, rty); }
|
||||
case (ty_obj(?methods)) {
|
||||
auto h = 27u;
|
||||
|
@ -1405,10 +1409,11 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
|
|||
case (_) { ret false; }
|
||||
}
|
||||
}
|
||||
case (ty_fn(?p_a, ?args_a, ?rty_a)) {
|
||||
case (ty_fn(?p_a, ?args_a, ?rty_a, ?cf_a)) {
|
||||
alt (b) {
|
||||
case (ty_fn(?p_b, ?args_b, ?rty_b)) {
|
||||
case (ty_fn(?p_b, ?args_b, ?rty_b, ?cf_b)) {
|
||||
ret p_a == p_b &&
|
||||
cf_a == cf_b &&
|
||||
equal_fn(args_a, rty_a, args_b, rty_b);
|
||||
}
|
||||
case (_) { ret false; }
|
||||
|
@ -1635,7 +1640,7 @@ fn type_contains_bound_params(&ctxt cx, &t typ) -> bool {
|
|||
|
||||
fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
|
||||
alt (struct(cx, fty)) {
|
||||
case (ty::ty_fn(_, ?a, _)) { ret a; }
|
||||
case (ty::ty_fn(_, ?a, _, _)) { ret a; }
|
||||
case (ty::ty_native_fn(_, ?a, _)) { ret a; }
|
||||
}
|
||||
fail;
|
||||
|
@ -1643,7 +1648,7 @@ fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
|
|||
|
||||
fn ty_fn_proto(&ctxt cx, &t fty) -> ast::proto {
|
||||
alt (struct(cx, fty)) {
|
||||
case (ty::ty_fn(?p, _, _)) { ret p; }
|
||||
case (ty::ty_fn(?p, _, _, _)) { ret p; }
|
||||
}
|
||||
fail;
|
||||
}
|
||||
|
@ -1657,7 +1662,7 @@ fn ty_fn_abi(&ctxt cx, &t fty) -> ast::native_abi {
|
|||
|
||||
fn ty_fn_ret(&ctxt cx, &t fty) -> t {
|
||||
alt (struct(cx, fty)) {
|
||||
case (ty::ty_fn(_, _, ?r)) { ret r; }
|
||||
case (ty::ty_fn(_, _, ?r, _)) { ret r; }
|
||||
case (ty::ty_native_fn(_, _, ?r)) { ret r; }
|
||||
}
|
||||
fail;
|
||||
|
@ -1665,7 +1670,7 @@ fn ty_fn_ret(&ctxt cx, &t fty) -> t {
|
|||
|
||||
fn is_fn_ty(&ctxt cx, &t fty) -> bool {
|
||||
alt (struct(cx, fty)) {
|
||||
case (ty::ty_fn(_, _, _)) { ret true; }
|
||||
case (ty::ty_fn(_, _, _, _)) { ret true; }
|
||||
case (ty::ty_native_fn(_, _, _)) { ret true; }
|
||||
case (_) { ret false; }
|
||||
}
|
||||
|
@ -2088,12 +2093,32 @@ mod unify {
|
|||
&t expected,
|
||||
&t actual,
|
||||
&vec[arg] expected_inputs, &t expected_output,
|
||||
&vec[arg] actual_inputs, &t actual_output)
|
||||
&vec[arg] actual_inputs, &t actual_output,
|
||||
&controlflow expected_cf, &controlflow actual_cf)
|
||||
-> result {
|
||||
|
||||
if (e_proto != a_proto) {
|
||||
ret ures_err(terr_mismatch, expected, actual);
|
||||
}
|
||||
alt (expected_cf) {
|
||||
case (ast::return) { } // ok
|
||||
case (ast::noreturn) {
|
||||
alt (actual_cf) {
|
||||
case (ast::noreturn) {
|
||||
// ok
|
||||
}
|
||||
case (_) {
|
||||
/* even though typestate checking is mostly
|
||||
responsible for checking control flow annotations,
|
||||
this check is necessary to ensure that the
|
||||
annotation in an object method matches the
|
||||
declared object type */
|
||||
ret ures_err(terr_controlflow_mismatch,
|
||||
expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto t = unify_fn_common(cx, expected, actual,
|
||||
expected_inputs, expected_output,
|
||||
actual_inputs, actual_output);
|
||||
|
@ -2102,7 +2127,8 @@ mod unify {
|
|||
ret r;
|
||||
}
|
||||
case (fn_common_res_ok(?result_ins, ?result_out)) {
|
||||
auto t2 = mk_fn(cx.tcx, e_proto, result_ins, result_out);
|
||||
auto t2 = mk_fn(cx.tcx, e_proto, result_ins, result_out,
|
||||
actual_cf);
|
||||
ret ures_ok(t2);
|
||||
}
|
||||
}
|
||||
|
@ -2160,14 +2186,16 @@ mod unify {
|
|||
e_meth.proto, a_meth.proto,
|
||||
expected, actual,
|
||||
e_meth.inputs, e_meth.output,
|
||||
a_meth.inputs, a_meth.output);
|
||||
a_meth.inputs, a_meth.output,
|
||||
e_meth.cf, a_meth.cf);
|
||||
alt (r) {
|
||||
case (ures_ok(?tfn)) {
|
||||
alt (struct(cx.tcx, tfn)) {
|
||||
case (ty_fn(?proto, ?ins, ?out)) {
|
||||
case (ty_fn(?proto, ?ins, ?out, ?cf)) {
|
||||
result_meths += [rec(inputs = ins,
|
||||
output = out
|
||||
with e_meth)];
|
||||
output = out,
|
||||
cf = cf
|
||||
with e_meth)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2539,13 +2567,16 @@ mod unify {
|
|||
}
|
||||
}
|
||||
|
||||
case (ty::ty_fn(?ep, ?expected_inputs, ?expected_output)) {
|
||||
case (ty::ty_fn(?ep, ?expected_inputs,
|
||||
?expected_output, ?expected_cf)) {
|
||||
alt (struct(cx.tcx, actual)) {
|
||||
case (ty::ty_fn(?ap, ?actual_inputs, ?actual_output)) {
|
||||
case (ty::ty_fn(?ap, ?actual_inputs,
|
||||
?actual_output, ?actual_cf)) {
|
||||
ret unify_fn(cx, ep, ap,
|
||||
expected, actual,
|
||||
expected_inputs, expected_output,
|
||||
actual_inputs, actual_output);
|
||||
actual_inputs, actual_output,
|
||||
expected_cf, actual_cf);
|
||||
}
|
||||
|
||||
case (_) {
|
||||
|
@ -2732,6 +2763,10 @@ fn type_err_to_str(&ty::type_err err) -> str {
|
|||
case (terr_mismatch) {
|
||||
ret "types differ";
|
||||
}
|
||||
case (terr_controlflow_mismatch) {
|
||||
ret "returning function used where non-returning function"
|
||||
+ " was expected";
|
||||
}
|
||||
case (terr_box_mutability) {
|
||||
ret "boxed values differ in mutability";
|
||||
}
|
||||
|
@ -2911,7 +2946,7 @@ fn lookup_item_type(ctxt cx, ast::def_id did) -> ty_param_count_and_ty {
|
|||
|
||||
fn ret_ty_of_fn_ty(ty_ctxt tcx, t a_ty) -> t {
|
||||
alt (ty::struct(tcx, a_ty)) {
|
||||
case (ty::ty_fn(_, _, ?ret_ty)) {
|
||||
case (ty::ty_fn(_, _, ?ret_ty, _)) {
|
||||
ret ret_ty;
|
||||
}
|
||||
case (_) {
|
||||
|
|
|
@ -314,11 +314,11 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
|
|||
typ = ty::mk_rec(tcx, flds);
|
||||
}
|
||||
|
||||
case (ast::ty_fn(?proto, ?inputs, ?output)) {
|
||||
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
|
||||
auto f = bind ast_arg_to_arg(tcx, getter, _);
|
||||
auto i = vec::map[ast::ty_arg, arg](f, inputs);
|
||||
auto out_ty = ast_ty_to_ty(tcx, getter, output);
|
||||
typ = ty::mk_fn(tcx, proto, i, out_ty);
|
||||
typ = ty::mk_fn(tcx, proto, i, out_ty, cf);
|
||||
}
|
||||
|
||||
case (ast::ty_path(?path, ?ann)) {
|
||||
|
@ -346,11 +346,13 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
|
|||
for (ast::ty_method m in meths) {
|
||||
auto ins = vec::map[ast::ty_arg, arg](f, m.inputs);
|
||||
auto out = ast_ty_to_ty(tcx, getter, m.output);
|
||||
vec::push[ty::method](tmeths,
|
||||
let ty::method new_m =
|
||||
rec(proto=m.proto,
|
||||
ident=m.ident,
|
||||
inputs=ins,
|
||||
output=out));
|
||||
output=out,
|
||||
cf=m.cf);
|
||||
vec::push[ty::method](tmeths, new_m);
|
||||
}
|
||||
|
||||
typ = ty::mk_obj(tcx, ty::sort_methods(tmeths));
|
||||
|
@ -458,7 +460,7 @@ mod collect {
|
|||
&ast::def_id def_id) -> ty::ty_param_count_and_ty {
|
||||
auto input_tys = vec::map[ast::arg,arg](ty_of_arg, decl.inputs);
|
||||
auto output_ty = convert(decl.output);
|
||||
auto t_fn = ty::mk_fn(cx.tcx, proto, input_tys, output_ty);
|
||||
auto t_fn = ty::mk_fn(cx.tcx, proto, input_tys, output_ty, decl.cf);
|
||||
auto ty_param_count = vec::len[ast::ty_param](ty_params);
|
||||
auto tpt = tup(ty_param_count, t_fn);
|
||||
cx.tcx.tcache.insert(def_id, tpt);
|
||||
|
@ -513,7 +515,7 @@ mod collect {
|
|||
auto inputs = vec::map[ast::arg,arg](f, m.node.meth.decl.inputs);
|
||||
auto output = convert(m.node.meth.decl.output);
|
||||
ret rec(proto=m.node.meth.proto, ident=m.node.ident,
|
||||
inputs=inputs, output=output);
|
||||
inputs=inputs, output=output, cf=m.node.meth.decl.cf);
|
||||
}
|
||||
|
||||
fn ty_of_obj(@ctxt cx,
|
||||
|
@ -542,7 +544,8 @@ mod collect {
|
|||
vec::push[arg](t_inputs, rec(mode=ty::mo_alias, ty=t_field));
|
||||
}
|
||||
|
||||
auto t_fn = ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj._1);
|
||||
auto t_fn = ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj._1,
|
||||
ast::return);
|
||||
|
||||
auto tpt = tup(t_obj._0, t_fn);
|
||||
cx.tcx.tcache.insert(ctor_id, tpt);
|
||||
|
@ -675,7 +678,8 @@ mod collect {
|
|||
args += [rec(mode=ty::mo_alias, ty=arg_ty)];
|
||||
}
|
||||
auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
|
||||
result_ty = ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t);
|
||||
result_ty = ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t,
|
||||
ast::return);
|
||||
}
|
||||
|
||||
auto tpt = tup(ty_param_count, result_ty);
|
||||
|
@ -782,7 +786,7 @@ mod collect {
|
|||
// TODO: typechecker botch
|
||||
let vec[arg] no_args = [];
|
||||
auto t = ty::mk_fn(cx.tcx, ast::proto_fn, no_args,
|
||||
ty::mk_nil(cx.tcx));
|
||||
ty::mk_nil(cx.tcx), ast::return);
|
||||
write::ty_only(cx.tcx, m.node.ann.id, t);
|
||||
}
|
||||
}
|
||||
|
@ -1073,7 +1077,7 @@ fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
|
|||
|
||||
auto tpt = ty::lookup_item_type(ccx.tcx, vid);
|
||||
alt (struct(ccx.tcx, tpt._1)) {
|
||||
case (ty::ty_fn(_, ?ins, _)) {
|
||||
case (ty::ty_fn(_, ?ins, _, _)) {
|
||||
// N-ary variant.
|
||||
for (ty::arg arg in ins) {
|
||||
auto arg_ty = bind_params_in_type(ccx.tcx, arg.ty);
|
||||
|
@ -1660,7 +1664,7 @@ fn check_pat(&@stmt_ctxt scx, &@ast::pat pat) {
|
|||
|
||||
alt (struct(scx.fcx.ccx.tcx, t)) {
|
||||
// N-ary variants have function types.
|
||||
case (ty::ty_fn(_, ?args, ?tag_ty)) {
|
||||
case (ty::ty_fn(_, ?args, ?tag_ty, _)) {
|
||||
auto arg_len = vec::len[arg](args);
|
||||
auto subpats_len = vec::len[@ast::pat](subpats);
|
||||
if (arg_len != subpats_len) {
|
||||
|
@ -1798,8 +1802,8 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
|||
auto rt_0 = next_ty_var(scx);
|
||||
auto t_0;
|
||||
alt (struct(scx.fcx.ccx.tcx, expr_ty(scx.fcx.ccx.tcx, f))) {
|
||||
case (ty::ty_fn(?proto, _, _)) {
|
||||
t_0 = ty::mk_fn(scx.fcx.ccx.tcx, proto, arg_tys_0, rt_0);
|
||||
case (ty::ty_fn(?proto, _, _, ?cf)) {
|
||||
t_0 = ty::mk_fn(scx.fcx.ccx.tcx, proto, arg_tys_0, rt_0, cf);
|
||||
}
|
||||
case (ty::ty_native_fn(?abi, _, _)) {
|
||||
t_0 = ty::mk_native_fn(scx.fcx.ccx.tcx, abi, arg_tys_0, rt_0);
|
||||
|
@ -2236,8 +2240,9 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
|||
let vec[ty::arg] arg_tys_1 = [];
|
||||
auto rt_1;
|
||||
auto fty = expr_ty(scx.fcx.ccx.tcx, f);
|
||||
auto t_1;
|
||||
alt (struct(scx.fcx.ccx.tcx, fty)) {
|
||||
case (ty::ty_fn(?proto, ?arg_tys, ?rt)) {
|
||||
case (ty::ty_fn(?proto, ?arg_tys, ?rt, ?cf)) {
|
||||
proto_1 = proto;
|
||||
rt_1 = rt;
|
||||
|
||||
|
@ -2253,14 +2258,14 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
|||
}
|
||||
i += 1u;
|
||||
}
|
||||
t_1 = ty::mk_fn(scx.fcx.ccx.tcx, proto_1, arg_tys_1, rt_1,
|
||||
cf);
|
||||
}
|
||||
case (_) {
|
||||
log_err "LHS of bind expr didn't have a function type?!";
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
auto t_1 = ty::mk_fn(scx.fcx.ccx.tcx, proto_1, arg_tys_1, rt_1);
|
||||
write::ty_only_fixup(scx, a.id, t_1);
|
||||
}
|
||||
|
||||
|
@ -2277,7 +2282,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
|||
auto rt_1 = ty::mk_nil(scx.fcx.ccx.tcx); // FIXME: typestate botch
|
||||
auto fty = expr_ty(scx.fcx.ccx.tcx, f);
|
||||
alt (struct(scx.fcx.ccx.tcx, fty)) {
|
||||
case (ty::ty_fn(_,_,?rt)) { rt_1 = rt; }
|
||||
case (ty::ty_fn(_,_,?rt,_)) { rt_1 = rt; }
|
||||
case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
|
||||
case (_) {
|
||||
log_err "LHS of call expr didn't have a function type?!";
|
||||
|
@ -2321,7 +2326,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
|||
// Check the return type
|
||||
auto fty = expr_ty(scx.fcx.ccx.tcx, f);
|
||||
alt (struct(scx.fcx.ccx.tcx, fty)) {
|
||||
case (ty::ty_fn(_,_,?rt)) {
|
||||
case (ty::ty_fn(_,_,?rt,_)) {
|
||||
alt (struct(scx.fcx.ccx.tcx, rt)) {
|
||||
case (ty::ty_nil) {
|
||||
// This is acceptable
|
||||
|
@ -2485,7 +2490,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
|||
}
|
||||
auto meth = methods.(ix);
|
||||
auto t = ty::mk_fn(scx.fcx.ccx.tcx, meth.proto,
|
||||
meth.inputs, meth.output);
|
||||
meth.inputs, meth.output, meth.cf);
|
||||
write::ty_only_fixup(scx, a.id, t);
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ fn walk_ty(&ast_visitor v, @ast::ty t) {
|
|||
walk_ty(v, f.mt.ty);
|
||||
}
|
||||
}
|
||||
case (ast::ty_fn(_, ?args, ?out)) {
|
||||
case (ast::ty_fn(_, ?args, ?out, _)) {
|
||||
for (ast::ty_arg a in args) {
|
||||
walk_ty(v, a.ty);
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@ fn print_type(ps s, &@ast::ty ty) {
|
|||
alt (ty.node) {
|
||||
case (ast::ty_nil) {wrd(s.s, "()");}
|
||||
case (ast::ty_bool) {wrd(s.s, "bool");}
|
||||
case (ast::ty_bot) {wrd(s.s, "_|_");}
|
||||
case (ast::ty_int) {wrd(s.s, "int");}
|
||||
case (ast::ty_uint) {wrd(s.s, "uint");}
|
||||
case (ast::ty_float) {wrd(s.s, "float");}
|
||||
|
@ -188,15 +189,15 @@ fn print_type(ps s, &@ast::ty ty) {
|
|||
for (ast::ty_method m in methods) {
|
||||
hbox(s);
|
||||
print_ty_fn(s, m.proto, option::some[str](m.ident),
|
||||
m.inputs, m.output);
|
||||
m.inputs, m.output, m.cf);
|
||||
wrd(s.s, ";");
|
||||
end(s.s);
|
||||
line(s.s);
|
||||
}
|
||||
bclose_c(s, ty.span);
|
||||
}
|
||||
case (ast::ty_fn(?proto,?inputs,?output)) {
|
||||
print_ty_fn(s, proto, option::none[str], inputs, output);
|
||||
case (ast::ty_fn(?proto,?inputs,?output,?cf)) {
|
||||
print_ty_fn(s, proto, option::none[str], inputs, output, cf);
|
||||
}
|
||||
case (ast::ty_path(?path,_)) {
|
||||
print_path(s, path);
|
||||
|
@ -978,7 +979,8 @@ fn print_string(ps s, str st) {
|
|||
}
|
||||
|
||||
fn print_ty_fn(ps s, ast::proto proto, option::t[str] id,
|
||||
vec[ast::ty_arg] inputs, @ast::ty output) {
|
||||
vec[ast::ty_arg] inputs, @ast::ty output,
|
||||
ast::controlflow cf) {
|
||||
if (proto == ast::proto_fn) {wrd(s.s, "fn");}
|
||||
else {wrd(s.s, "iter");}
|
||||
alt (id) {
|
||||
|
@ -998,7 +1000,14 @@ fn print_ty_fn(ps s, ast::proto proto, option::t[str] id,
|
|||
space(s.s);
|
||||
hbox(s);
|
||||
wrd1(s, "->");
|
||||
print_type(s, output);
|
||||
alt (cf) {
|
||||
case (ast::return) {
|
||||
print_type(s, output);
|
||||
}
|
||||
case (ast::noreturn) {
|
||||
wrd1(s, "!");
|
||||
}
|
||||
}
|
||||
end(s.s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,11 @@ tag ty_mach {
|
|||
ty_f64;
|
||||
}
|
||||
|
||||
tag ty_or_bang[T] {
|
||||
a_ty(T);
|
||||
a_bang;
|
||||
}
|
||||
|
||||
fn ty_mach_to_str(ty_mach tm) -> str {
|
||||
alt (tm) {
|
||||
case (ty_u8) { ret "u8"; }
|
||||
|
|
Loading…
Reference in a new issue