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. { } /* even though typestate checking is mostly
// ok responsible for checking control flow annotations,
ast::noreturn. { this check is necessary to ensure that the
alt actual_cf { annotation in an object method matches the
ast::noreturn. { declared object type */
// ok ret ures_err(terr_ret_style_mismatch(expected_cf, actual_cf));
}
_ {
/* 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);
}
}
}
} }
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);