diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index bd613b06574..ae71acdaa11 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -119,7 +119,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt) { } ast::expr_ret(oexpr) { if sc.ret_style == ast::return_ref && !is_none(oexpr) { - check_ret_ref(*cx, option::get(oexpr)); + check_ret_ref(*cx, sc, option::get(oexpr)); } handled = false; } @@ -266,18 +266,53 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { ret bindings; } -fn check_ret_ref(cx: ctx, expr: @ast::expr) { +fn check_ret_ref(cx: ctx, sc: scope, expr: @ast::expr) { let root = expr_root(cx.tcx, expr, false); let bad = none; + let mut_field = mut_field(root.ds); alt path_def(cx, root.ex) { none. { bad = some("temporary"); } - some(ast::def_arg(_, mode)) { - if mode == ast::by_move { bad = some("move-mode parameter"); } - if mut_field(root.ds) { bad = some("mutable field"); } + some(ast::def_local(did)) | some(ast::def_binding(did)) | + some(ast::def_arg(did, _)) { + let cur_node = did.node; + while true { + alt cx.tcx.items.find(cur_node) { + some(ast_map::node_arg(arg)) { + if arg.mode == ast::by_move { + bad = some("move-mode parameter"); + } + break; + } + _ {} + } + alt vec::find({|b| b.node_id == cur_node}, sc.bs) { + some(b) { + if vec::len(b.unsafe_tys) > 0u { + mut_field = true; + break; + } + if is_none(b.root_var) { + bad = some("function-local value"); + break; + } + if b.copied == copied { + bad = some("implicitly copied reference"); + break; + } + b.copied = not_allowed; + cur_node = option::get(b.root_var); + } + none. { + bad = some("function-local value"); + break; + } + } + } } // FIXME allow references to constants and static items? - _ { bad = some("non-argument value"); } + _ { bad = some("non-local value"); } } + if mut_field { 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/resolve.rs b/src/comp/middle/resolve.rs index 37370b0b4f0..4068c2e7c8e 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -347,7 +347,6 @@ fn visit_fn_with_scope(e: @env, f: ast::_fn, tp: [ast::ty_param], sp: span, // here's where we need to set up the mapping // for f's constrs in the table. - for c: @ast::constr in f.decl.constraints { resolve_constr(e, c, sc, v); } visit::visit_fn(f, tp, sp, name, id, cons(scope_fn(f.decl, f.proto, tp), @sc), v); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 63cae740cc4..e1f3ae190a4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3530,7 +3530,8 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t, let to_zero = []; let to_revoke = []; - let tcx = bcx_tcx(cx); + 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; // Arg 0: Output pointer. @@ -3549,7 +3550,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t, } let retty = ty::ty_fn_ret(tcx, fn_ty); let llretslot_res = if by_ref { - rslt(cx, alloca(cx, T_ptr(type_of_or_i8(cx, retty)))) + rslt(cx, alloca(cx, T_ptr(type_of_or_i8(bcx, retty)))) } else { alloc_ty(bcx, retty) }; bcx = llretslot_res.bcx; let llretslot = llretslot_res.val; @@ -3568,7 +3569,8 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t, // type deep in a structure -- which the caller has a concrete view // of. If so, cast the caller's view of the restlot to the callee's // view, for the sake of making a type-compatible call. - let llretty = T_ptr(type_of_inner(bcx_ccx(bcx), bcx.sp, retty)); + let llretty = T_ptr(type_of_inner(ccx, bcx.sp, retty)); + if by_ref { llretty = T_ptr(llretty); } llargs += [PointerCast(cx, llretslot, llretty)]; } else { llargs += [llretslot]; } @@ -3588,7 +3590,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t, let lli = if ty::type_contains_params(tcx, retty) { let body_ty = ty::mk_iter_body_fn(tcx, retty); - let body_llty = type_of_inner(bcx_ccx(cx), cx.sp, body_ty); + let body_llty = type_of_inner(ccx, cx.sp, body_ty); PointerCast(bcx, lli, T_ptr(body_llty)) } else { lli }; llargs += [Load(cx, lli)]; @@ -3600,7 +3602,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t, // First we figure out the caller's view of the types of the arguments. // This will be needed if this is a generic call, because the callee has // to cast her view of the arguments to the caller's view. - let arg_tys = type_of_explicit_args(bcx_ccx(cx), cx.sp, args); + let arg_tys = type_of_explicit_args(ccx, cx.sp, args); let i = 0u; for e: @ast::expr in es { if is_terminated(bcx) { @@ -3631,15 +3633,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr, let cx = new_scope_block_ctxt(in_cx, "call"); Br(in_cx, cx.llbb); let f_res = trans_lval_gen(cx, f); - let fn_ty: ty::t; - alt f_res.method_ty { - some(meth) { - // self-call - fn_ty = meth; - } - _ { fn_ty = ty::expr_ty(bcx_tcx(cx), f); } - } - + let fn_ty = ty::expr_ty(bcx_tcx(cx), f); let bcx = f_res.res.bcx; let faddr = f_res.res.val;