1
Fork 0

Make most of the compiler aware of return-by-reference

tyencode/tydecode still don't know about it. return_ref will be extended to take
arguments anyway.
This commit is contained in:
Marijn Haverbeke 2011-09-14 11:01:42 +02:00
parent c1c083cd66
commit 51dae63c44
4 changed files with 34 additions and 31 deletions

View file

@ -218,7 +218,10 @@ fn enc_ty_fn(w: io::writer, cx: @ctxt, args: [ty::arg], out: ty::t,
} else { w.write_char(';'); } } else { w.write_char(';'); }
enc_constr(w, cx, c); enc_constr(w, cx, c);
} }
alt cf { noreturn. { w.write_char('!'); } _ { enc_ty(w, cx, out); } } alt cf {
noreturn. { w.write_char('!'); }
_ { enc_ty(w, cx, out); }
}
} }
// FIXME less copy-and-paste // FIXME less copy-and-paste

View file

@ -279,7 +279,7 @@ type constr = constr_general<uint>;
// Data structures used in type unification // Data structures used in type unification
tag type_err { tag type_err {
terr_mismatch; terr_mismatch;
terr_controlflow_mismatch; terr_ret_style_mismatch(ast::ret_style, ast::ret_style);
terr_box_mutability; terr_box_mutability;
terr_vec_mutability; terr_vec_mutability;
terr_tuple_size(uint, uint); terr_tuple_size(uint, uint);
@ -1952,26 +1952,13 @@ mod unify {
_expected_constrs: [@constr], actual_constrs: [@constr]) -> _expected_constrs: [@constr], actual_constrs: [@constr]) ->
result { result {
if e_proto != a_proto { ret ures_err(terr_mismatch); } if e_proto != a_proto { ret ures_err(terr_mismatch); }
alt expected_cf { if actual_cf != ast::noreturn && actual_cf != expected_cf {
ast::return_val. { }
// ok
ast::noreturn. {
alt actual_cf {
ast::noreturn. {
// ok
}
_ {
/* even though typestate checking is mostly /* even though typestate checking is mostly
responsible for checking control flow annotations, responsible for checking control flow annotations,
this check is necessary to ensure that the this check is necessary to ensure that the
annotation in an object method matches the annotation in an object method matches the
declared object type */ declared object type */
ret ures_err(terr_ret_style_mismatch(expected_cf, actual_cf));
ret ures_err(terr_controlflow_mismatch);
}
}
}
} }
let t = let t =
unify_fn_common(cx, expected, actual, expected_inputs, unify_fn_common(cx, expected, actual, expected_inputs,
@ -2470,9 +2457,16 @@ mod unify {
fn type_err_to_str(err: ty::type_err) -> str { fn type_err_to_str(err: ty::type_err) -> str {
alt err { alt err {
terr_mismatch. { ret "types differ"; } terr_mismatch. { ret "types differ"; }
terr_controlflow_mismatch. { terr_ret_style_mismatch(expect, actual) {
ret "returning function used where non-returning function" + fn to_str(s: ast::ret_style) -> str {
" was expected"; alt s {
ast::noreturn. { "non-returning" }
ast::return_val. { "return-by-value" }
ast::return_ref. { "return-by-reference" }
}
}
ret to_str(actual) + " function found where " + to_str(expect) +
" function was expected";
} }
terr_box_mutability. { ret "boxed values differ in mutability"; } terr_box_mutability. { ret "boxed values differ in mutability"; }
terr_vec_mutability. { ret "vectors differ in mutability"; } terr_vec_mutability. { ret "vectors differ in mutability"; }

View file

@ -1224,6 +1224,7 @@ fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl, constrs: [@ast::constr]) {
if decl.output.node != ast::ty_nil { if decl.output.node != ast::ty_nil {
space_if_not_bol(s); space_if_not_bol(s);
word_space(s, "->"); word_space(s, "->");
if decl.cf == ast::return_ref { word(s.s, "&"); }
print_type(s, decl.output); print_type(s, decl.output);
} }
} }
@ -1419,9 +1420,11 @@ fn print_ty_fn(s: ps, proto: ast::proto, id: option::t<ast::ident>,
space_if_not_bol(s); space_if_not_bol(s);
ibox(s, indent_unit); ibox(s, indent_unit);
word_space(s, "->"); word_space(s, "->");
alt cf { if cf == ast::noreturn {
ast::return_val. { print_type(s, output); } word_nbsp(s, "!")
ast::noreturn. { word_nbsp(s, "!"); } } else {
if cf == ast::return_ref { word(s.s, "&"); }
print_type(s, output);
} }
end(s); end(s);
} }

View file

@ -58,9 +58,12 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
s += str::connect(strs, ", "); s += str::connect(strs, ", ");
s += ")"; s += ")";
if struct(cx, output) != ty_nil { if struct(cx, output) != ty_nil {
alt cf { s += " -> ";
ast::noreturn. { s += " -> !"; } if cf == ast::noreturn {
ast::return_val. { s += " -> " + ty_to_str(cx, output); } s += "!";
} else {
if cf == ast::return_ref { s += "&"; }
s += ty_to_str(cx, output);
} }
} }
s += constrs_str(constrs); s += constrs_str(constrs);