diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-09-14 17:18:48 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-09-14 17:30:38 +0200 |
| commit | 93de2f0b7498cbc6a304ba3cb80f5a3ea57b8bc7 (patch) | |
| tree | dd42794a80d712ff07af81493bd12231924e3e21 | |
| parent | 1cabe37155bf83af04ce7814186fbef096a253cb (diff) | |
| download | rust-93de2f0b7498cbc6a304ba3cb80f5a3ea57b8bc7.tar.gz rust-93de2f0b7498cbc6a304ba3cb80f5a3ea57b8bc7.zip | |
Add syntax and representation for return-by-mutably-rooted-ref
This will be used in the near future to decide what can safely be done with the returned reference. Issue #918
| -rw-r--r-- | src/comp/metadata/tydecode.rs | 18 | ||||
| -rw-r--r-- | src/comp/metadata/tyencode.rs | 4 | ||||
| -rw-r--r-- | src/comp/middle/alias.rs | 17 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 13 | ||||
| -rw-r--r-- | src/comp/middle/trans_objects.rs | 4 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/ast_util.rs | 7 | ||||
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/print/pprust.rs | 10 | ||||
| -rw-r--r-- | src/comp/util/ppaux.rs | 10 |
11 files changed, 55 insertions, 34 deletions
diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs index cc342fe4647..b4ea33a1277 100644 --- a/src/comp/metadata/tydecode.rs +++ b/src/comp/metadata/tydecode.rs @@ -21,8 +21,6 @@ type str_def = fn(str) -> ast::def_id; type pstate = {data: @[u8], crate: int, mutable pos: uint, len: uint, tcx: ty::ctxt}; -tag ty_or_bang { a_ty(ty::t); a_bang; } - fn peek(st: @pstate) -> u8 { ret st.data[st.pos]; } fn next(st: @pstate) -> u8 { @@ -54,10 +52,12 @@ fn parse_ty_data(data: @[u8], crate_num: int, pos: uint, len: uint, ret result; } -fn parse_ty_or_bang(st: @pstate, sd: str_def) -> ty_or_bang { +fn parse_ret_ty(st: @pstate, sd: str_def) -> (ast::ret_style, ty::t) { alt peek(st) as char { - '!' { next(st); ret a_bang; } - _ { ret a_ty(parse_ty(st, sd)); } + '!' { next(st); (ast::noreturn, ty::mk_bot(st.tcx)) } + '&' { next(st); (ast::return_ref(false), parse_ty(st, sd)) } + '^' { next(st); (ast::return_ref(true), parse_ty(st, sd)) } + _ { (ast::return_val, parse_ty(st, sd)) } } } @@ -387,12 +387,8 @@ fn parse_ty_fn(st: @pstate, sd: str_def) -> } st.pos += 1u; // eat the ']' let cs = parse_constrs(st, sd); - alt parse_ty_or_bang(st, sd) { - a_bang. { - ret {args: inputs, ty: ty::mk_bot(st.tcx), cf: ast::noreturn, cs: cs}; - } - a_ty(t) { ret {args: inputs, ty: t, cf: ast::return_val, cs: cs}; } - } + let (ret_style, ret_ty) = parse_ret_ty(st, sd); + ret {args: inputs, ty: ret_ty, cf: ret_style, cs: cs}; } diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs index 5103fbd917d..234968cd97c 100644 --- a/src/comp/metadata/tyencode.rs +++ b/src/comp/metadata/tyencode.rs @@ -220,6 +220,10 @@ fn enc_ty_fn(w: io::writer, cx: @ctxt, args: [ty::arg], out: ty::t, } alt cf { noreturn. { w.write_char('!'); } + return_ref(mut) { + w.write_char(mut ? '^' : '&'); + enc_ty(w, cx, out); + } _ { enc_ty(w, cx, out); } } } diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index ae71acdaa11..c8536ef2ddb 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -66,7 +66,7 @@ fn visit_fn(cx: @ctx, f: ast::_fn, _tp: [ast::ty_param], _sp: span, // Non capturing functions start out fresh. _ { [] } }; - if f.decl.cf == ast::return_ref && !is_none(f.body.node.expr) { + if ast_util::ret_by_ref(f.decl.cf) && !is_none(f.body.node.expr) { // FIXME this will be easier to lift once have DPS cx.tcx.sess.span_err(option::get(f.body.node.expr).span, "reference-returning functions may not " + @@ -118,8 +118,13 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) { check_assign(cx, dest, src, sc, v); } ast::expr_ret(oexpr) { - if sc.ret_style == ast::return_ref && !is_none(oexpr) { - check_ret_ref(*cx, sc, option::get(oexpr)); + if !is_none(oexpr) { + alt sc.ret_style { + ast::return_ref(mut) { + check_ret_ref(*cx, sc, mut, option::get(oexpr)); + } + _ {} + } } handled = false; } @@ -176,7 +181,7 @@ fn cant_copy(cx: ctx, b: binding) -> bool { fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { let fty = ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f)); - let ret_ref = ty::ty_fn_ret_style(cx.tcx, fty) == ast::return_ref; + let ret_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(cx.tcx, fty)); let arg_ts = ty::ty_fn_args(cx.tcx, fty); let mut_roots: [{arg: uint, node: node_id}] = []; let bindings = []; @@ -266,7 +271,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { ret bindings; } -fn check_ret_ref(cx: ctx, sc: scope, expr: @ast::expr) { +fn check_ret_ref(cx: ctx, sc: scope, mut: bool, expr: @ast::expr) { let root = expr_root(cx.tcx, expr, false); let bad = none; let mut_field = mut_field(root.ds); @@ -312,7 +317,7 @@ fn check_ret_ref(cx: ctx, sc: scope, expr: @ast::expr) { // FIXME allow references to constants and static items? _ { bad = some("non-local value"); } } - if mut_field { bad = some("mutable field"); } + if mut_field && !mut { bad = some("mutable field"); } alt bad { some(name) { cx.tcx.sess.span_err(expr.span, "can not return a reference " + diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index fbdbe9f269a..ba495934387 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -101,7 +101,7 @@ fn type_of_fn(cx: @crate_ctxt, sp: span, proto: ast::proto, // Given a function type and a count of ty params, construct an llvm type fn type_of_fn_from_ty(cx: @crate_ctxt, sp: span, fty: ty::t, ty_param_count: uint) -> TypeRef { - let by_ref = ty::ty_fn_ret_style(cx.tcx, fty) == ast::return_ref; + let by_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(cx.tcx, fty)); ret type_of_fn(cx, sp, ty::ty_fn_proto(cx.tcx, fty), false, by_ref, ty::ty_fn_args(cx.tcx, fty), ty::ty_fn_ret(cx.tcx, fty), ty_param_count); @@ -2969,7 +2969,7 @@ fn trans_field(cx: @block_ctxt, sp: span, v: ValueRef, t0: ty::t, let v = GEP(r.bcx, vtbl, [C_int(0), C_int(ix as int)]); let tcx = bcx_tcx(cx); let fn_ty: ty::t = ty::method_ty_to_fn_ty(tcx, methods[ix]); - let ret_ref = ty::ty_fn_ret_style(tcx, fn_ty) == ast::return_ref; + let ret_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(tcx, fn_ty)); let ll_fn_ty = type_of_fn(bcx_ccx(cx), sp, ty::ty_fn_proto(tcx, fn_ty), true, ret_ref, ty::ty_fn_args(tcx, fn_ty), @@ -3532,7 +3532,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>, let ccx = bcx_ccx(cx); let tcx = ccx.tcx; let bcx: @block_ctxt = cx; - let by_ref = ty::ty_fn_ret_style(tcx, fn_ty) == ast::return_ref; + let by_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(tcx, fn_ty)); // Arg 0: Output pointer. // FIXME: test case looks like @@ -3629,7 +3629,8 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr, // with trans_call. let fn_expr_ty = ty::expr_ty(bcx_tcx(in_cx), f); let fn_ty = ty::type_autoderef(bcx_tcx(in_cx), fn_expr_ty); - let by_ref = ty::ty_fn_ret_style(bcx_tcx(in_cx), fn_ty) == ast::return_ref; + let by_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(bcx_tcx(in_cx), + fn_ty)); // Things that return by reference must put their arguments (FIXME only // the referenced arguments) into the outer scope, so that they are still // alive when the return value is used. @@ -4391,7 +4392,7 @@ fn trans_ret(cx: @block_ctxt, e: option::t<@ast::expr>) -> result { let t = ty::expr_ty(bcx_tcx(cx), x); let lv = trans_lval(cx, x); bcx = lv.res.bcx; - if cx.fcx.ret_style == ast::return_ref { + if ast_util::ret_by_ref(cx.fcx.ret_style) { assert lv.is_mem; Store(bcx, lv.res.val, cx.fcx.llretptr); } else { @@ -5364,7 +5365,7 @@ fn decl_fn_and_pair_full(ccx: @crate_ctxt, sp: span, path: [str], _flav: str, alt ty::struct(ccx.tcx, node_type) { ty::ty_fn(proto, inputs, output, rs, _) { llfty = type_of_fn(ccx, sp, proto, false, - rs == ast::return_ref, inputs, output, + ast_util::ret_by_ref(rs), inputs, output, vec::len(ty_params)); } _ { ccx.sess.bug("decl_fn_and_pair(): fn item doesn't have fn type!"); } diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 5f538c24eca..a74ee6ba9ed 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -882,7 +882,7 @@ fn process_normal_mthd(cx: @local_ctxt, m: @ast::method, self_ty: ty::t, alt ty::struct(cx.ccx.tcx, node_id_type(cx.ccx, m.node.id)) { ty::ty_fn(proto, inputs, output, rs, _) { llfnty = type_of_fn(cx.ccx, m.span, proto, true, - rs == ast::return_ref, inputs, output, + ast_util::ret_by_ref(rs), inputs, output, vec::len(ty_params)); } } @@ -933,7 +933,7 @@ fn populate_self_stack(bcx: @block_ctxt, self_stack: ValueRef, fn type_of_meth(ccx: @crate_ctxt, sp: span, m: @ty::method, tps: [ast::ty_param]) -> TypeRef { - type_of_fn(ccx, sp, m.proto, true, m.cf == ast::return_ref, + type_of_fn(ccx, sp, m.proto, true, ast_util::ret_by_ref(m.cf), m.inputs, m.output, vec::len(tps)) } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index dc9353dc2fd..e03a3c80a00 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -2471,7 +2471,7 @@ fn type_err_to_str(err: ty::type_err) -> str { alt s { ast::noreturn. { "non-returning" } ast::return_val. { "return-by-value" } - ast::return_ref. { "return-by-reference" } + ast::return_ref(_) { "return-by-reference" } } } ret to_str(actual) + " function found where " + to_str(expect) + diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 15d05cfe243..f064519cca3 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -381,7 +381,7 @@ tag ret_style { noreturn; // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) return_val; // everything else - return_ref; + return_ref(bool); } type _fn = {decl: fn_decl, proto: proto, body: blk}; diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index 1c11a56272e..b6c4eb9a929 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -213,6 +213,13 @@ fn ternary_to_if(e: @expr) -> @expr { } } +fn ret_by_ref(style: ret_style) -> bool { + alt style { + return_ref(_) { true } + _ { false } + } +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 8309afb85a2..543f2e65383 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -445,7 +445,7 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) { } else { let style = ast::return_val; if eat(p, token::BINOP(token::AND)) { - style = ast::return_ref; + style = ast::return_ref(eat(p, token::NOT)); }; (style, parse_ty(p, false)) } diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index beb22544fda..92ecceb7ad1 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -1224,7 +1224,10 @@ fn print_fn_args_and_ret(s: ps, decl: ast::fn_decl, constrs: [@ast::constr]) { if decl.output.node != ast::ty_nil { space_if_not_bol(s); word_space(s, "->"); - if decl.cf == ast::return_ref { word(s.s, "&"); } + alt decl.cf { + ast::return_ref(mut) { word(s.s, mut ? "&!" : "&"); } + _ {} + } print_type(s, decl.output); } } @@ -1423,7 +1426,10 @@ fn print_ty_fn(s: ps, proto: ast::proto, id: option::t<ast::ident>, if cf == ast::noreturn { word_nbsp(s, "!") } else { - if cf == ast::return_ref { word(s.s, "&"); } + alt cf { + ast::return_ref(mut) { word(s.s, mut ? "&!" : "&"); } + _ {} + } print_type(s, output); } end(s); diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs index 3aa002c50fe..7e84c08a1d0 100644 --- a/src/comp/util/ppaux.rs +++ b/src/comp/util/ppaux.rs @@ -59,11 +59,13 @@ fn ty_to_str(cx: ctxt, typ: t) -> str { s += ")"; if struct(cx, output) != ty_nil { s += " -> "; - if cf == ast::noreturn { - s += "!"; - } else { - if cf == ast::return_ref { s += "&"; } + alt cf { + ast::noreturn. { s += "!"; } + ast::return_ref(mut) { + s += mut ? "&!" : "&"; s += ty_to_str(cx, output); + } + ast::return_val. { s += ty_to_str(cx, output); } } } s += constrs_str(constrs); |
