infer modes rather than overwriting with expected ty
This commit is contained in:
parent
5163606d06
commit
77b06d24cd
@ -382,7 +382,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
|
||||
let args_ty: ast::ty = nospan(ast::ty_vec(args_mt));
|
||||
|
||||
let args_arg: ast::arg =
|
||||
{mode: ast::by_val,
|
||||
{mode: ast::expl(ast::by_val),
|
||||
ty: @args_ty,
|
||||
ident: "args",
|
||||
id: cx.sess.next_node_id()};
|
||||
|
@ -353,7 +353,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
|
||||
'#' { ast::by_val }
|
||||
};
|
||||
st.pos += 1u;
|
||||
inputs += [{mode: mode, ty: parse_ty(st, conv)}];
|
||||
inputs += [{mode: ast::expl(mode), ty: parse_ty(st, conv)}];
|
||||
}
|
||||
st.pos += 1u; // eat the ']'
|
||||
let cs = parse_constrs(st, conv);
|
||||
|
@ -203,16 +203,12 @@ fn enc_proto(w: io::writer, proto: proto) {
|
||||
fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
|
||||
w.write_char('[');
|
||||
for arg: ty::arg in ft.inputs {
|
||||
alt arg.mode {
|
||||
alt ty::resolved_mode(cx.tcx, arg.mode) {
|
||||
by_mut_ref { w.write_char('&'); }
|
||||
by_move { w.write_char('-'); }
|
||||
by_copy { w.write_char('+'); }
|
||||
by_ref { w.write_char('='); }
|
||||
by_val { w.write_char('#'); }
|
||||
// tediously, this has to be there until there's a way
|
||||
// to constraint post-typeck types not to contain a mode_infer
|
||||
mode_infer { cx.tcx.sess.bug("enc_ty_fn: shouldn't see \
|
||||
mode_infer"); }
|
||||
}
|
||||
enc_ty(w, cx, arg.ty);
|
||||
}
|
||||
|
@ -82,9 +82,11 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
|
||||
let fty = ty::node_id_to_type(cx.tcx, id);
|
||||
let args = ty::ty_fn_args(cx.tcx, fty);
|
||||
for arg in args {
|
||||
if arg.mode == ast::by_val &&
|
||||
ty::type_has_dynamic_size(cx.tcx, arg.ty) {
|
||||
alt ty::resolved_mode(cx.tcx, arg.mode) {
|
||||
ast::by_val if ty::type_has_dynamic_size(cx.tcx, arg.ty) {
|
||||
err(*cx, sp, "can not pass a dynamically-sized type by value");
|
||||
}
|
||||
_ { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +228,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
|
||||
for arg_t: ty::arg in arg_ts {
|
||||
let arg = args[i];
|
||||
let root = expr_root(cx, arg, false);
|
||||
if arg_t.mode == ast::by_mut_ref {
|
||||
alt ty::resolved_mode(cx.tcx, arg_t.mode) {
|
||||
ast::by_mut_ref {
|
||||
alt path_def(cx, arg) {
|
||||
some(def) {
|
||||
let dnum = ast_util::def_id_of_def(def).node;
|
||||
@ -234,18 +237,21 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
ast::by_ref | ast::by_val | ast::by_move | ast::by_copy { }
|
||||
}
|
||||
let root_var = path_def_id(cx, root.ex);
|
||||
let arg_copied = alt ty::resolved_mode(cx.tcx, arg_t.mode) {
|
||||
ast::by_move | ast::by_copy { copied }
|
||||
ast::by_mut_ref { not_allowed }
|
||||
ast::by_ref | ast::by_val { not_copied }
|
||||
};
|
||||
bindings += [@{node_id: arg.id,
|
||||
span: arg.span,
|
||||
root_var: root_var,
|
||||
local_id: 0u,
|
||||
unsafe_tys: unsafe_set(root.mut),
|
||||
mutable copied: alt arg_t.mode {
|
||||
ast::by_move | ast::by_copy { copied }
|
||||
ast::by_mut_ref { not_allowed }
|
||||
_ { not_copied }
|
||||
}}];
|
||||
mutable copied: arg_copied}];
|
||||
i += 1u;
|
||||
}
|
||||
let f_may_close =
|
||||
@ -279,7 +285,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
|
||||
for unsafe_ty in b.unsafe_tys {
|
||||
let i = 0u;
|
||||
for arg_t: ty::arg in arg_ts {
|
||||
let mut_alias = arg_t.mode == ast::by_mut_ref;
|
||||
let mut_alias =
|
||||
(ast::by_mut_ref == ty::arg_mode(cx.tcx, arg_t));
|
||||
if i != j &&
|
||||
ty_can_unsafely_include(cx, unsafe_ty, arg_t.ty,
|
||||
mut_alias) &&
|
||||
|
@ -28,7 +28,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
|
||||
v.visit_expr(f, cx, v);
|
||||
let i = 0u;
|
||||
for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
|
||||
cx.allow_block = arg_t.mode == by_ref;
|
||||
cx.allow_block = (ty::arg_mode(cx.tcx, arg_t) == by_ref);
|
||||
v.visit_expr(args[i], cx, v);
|
||||
i += 1u;
|
||||
}
|
||||
|
@ -165,7 +165,10 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
|
||||
expr_call(f, args, _) {
|
||||
let i = 0u;
|
||||
for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) {
|
||||
alt arg_t.mode { by_copy { maybe_copy(cx, args[i]); } _ {} }
|
||||
alt ty::arg_mode(cx.tcx, arg_t) {
|
||||
by_copy { maybe_copy(cx, args[i]); }
|
||||
by_ref | by_val | by_mut_ref | by_move { }
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
|
||||
fns += [arg];
|
||||
}
|
||||
_ {
|
||||
alt arg_ts[i].mode {
|
||||
alt ty::arg_mode(cx.tcx, arg_ts[i]) {
|
||||
by_mut_ref { clear_if_path(cx, arg, v, false); }
|
||||
_ { v.visit_expr(arg, cx, v); }
|
||||
}
|
||||
@ -286,11 +286,21 @@ fn clear_in_current(cx: ctx, my_def: node_id, to: bool) {
|
||||
fn clear_def_if_path(cx: ctx, d: def, to: bool)
|
||||
-> option<node_id> {
|
||||
alt d {
|
||||
def_local(def_id, let_copy) | def_arg(def_id, by_copy) |
|
||||
def_arg(def_id, by_move) {
|
||||
def_local(def_id, let_copy) {
|
||||
clear_in_current(cx, def_id.node, to);
|
||||
some(def_id.node)
|
||||
}
|
||||
def_arg(def_id, m) {
|
||||
alt ty::resolved_mode(cx.tcx, m) {
|
||||
by_copy | by_move {
|
||||
clear_in_current(cx, def_id.node, to);
|
||||
some(def_id.node)
|
||||
}
|
||||
by_ref | by_val | by_mut_ref {
|
||||
none
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {
|
||||
none
|
||||
}
|
||||
|
@ -228,10 +228,10 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
|
||||
let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
|
||||
let i = 0u;
|
||||
for arg_t: ty::arg in arg_ts {
|
||||
alt arg_t.mode {
|
||||
alt ty::resolved_mode(cx.tcx, arg_t.mode) {
|
||||
by_mut_ref { check_lval(cx, args[i], msg_mut_ref); }
|
||||
by_move { check_lval(cx, args[i], msg_move_out); }
|
||||
_ {}
|
||||
by_ref | by_val | by_copy { }
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
@ -267,8 +267,12 @@ fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
|
||||
def_use(_) {
|
||||
some("static item")
|
||||
}
|
||||
def_arg(_, by_ref) | def_arg(_, by_val) |
|
||||
def_arg(_, mode_infer) { some("argument") }
|
||||
def_arg(_, m) {
|
||||
alt ty::resolved_mode(cx.tcx, m) {
|
||||
by_ref | by_val { some("argument") }
|
||||
by_mut_ref | by_move | by_copy { none }
|
||||
}
|
||||
}
|
||||
def_self(_) { some("self argument") }
|
||||
def_upvar(_, inner, node_id) {
|
||||
let ty = ty::node_id_to_type(cx.tcx, node_id);
|
||||
|
@ -63,16 +63,18 @@ fn type_of(cx: @crate_ctxt, t: ty::t) : type_has_static_size(cx, t)
|
||||
|
||||
fn type_of_explicit_args(cx: @crate_ctxt, inputs: [ty::arg]) ->
|
||||
[TypeRef] {
|
||||
let atys = [];
|
||||
for arg in inputs {
|
||||
let tcx = ccx_tcx(cx);
|
||||
vec::map(inputs) {|arg|
|
||||
let arg_ty = arg.ty;
|
||||
// FIXME: would be nice to have a constraint on arg
|
||||
// that would obviate the need for this check
|
||||
check non_ty_var(cx, arg_ty);
|
||||
let llty = type_of_inner(cx, arg_ty);
|
||||
atys += [if arg.mode == ast::by_val { llty } else { T_ptr(llty) }];
|
||||
alt ty::resolved_mode(tcx, arg.mode) {
|
||||
ast::by_val { llty }
|
||||
_ { T_ptr(llty) }
|
||||
}
|
||||
}
|
||||
ret atys;
|
||||
}
|
||||
|
||||
|
||||
@ -2981,15 +2983,16 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
|
||||
let lv = trans_temp_lval(cx, e);
|
||||
let bcx = lv.bcx;
|
||||
let val = lv.val;
|
||||
let arg_mode = ty::resolved_mode(ccx.tcx, arg.mode);
|
||||
if is_bot {
|
||||
// For values of type _|_, we generate an
|
||||
// "undef" value, as such a value should never
|
||||
// be inspected. It's important for the value
|
||||
// to have type lldestty (the callee's expected type).
|
||||
val = llvm::LLVMGetUndef(lldestty);
|
||||
} else if arg.mode == ast::by_ref || arg.mode == ast::by_val {
|
||||
} else if arg_mode == ast::by_ref || arg_mode == ast::by_val {
|
||||
let copied = false, imm = ty::type_is_immediate(ccx.tcx, e_ty);
|
||||
if arg.mode == ast::by_ref && lv.kind != owned && imm {
|
||||
if arg_mode == ast::by_ref && lv.kind != owned && imm {
|
||||
val = do_spill_noroot(bcx, val);
|
||||
copied = true;
|
||||
}
|
||||
@ -3002,10 +3005,10 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
|
||||
} else { bcx = take_ty(bcx, val, e_ty); }
|
||||
add_clean(bcx, val, e_ty);
|
||||
}
|
||||
if arg.mode == ast::by_val && (lv.kind == owned || !imm) {
|
||||
if arg_mode == ast::by_val && (lv.kind == owned || !imm) {
|
||||
val = Load(bcx, val);
|
||||
}
|
||||
} else if arg.mode == ast::by_copy {
|
||||
} else if arg_mode == ast::by_copy {
|
||||
let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
|
||||
let last_use = ccx.last_uses.contains_key(e.id);
|
||||
bcx = cx;
|
||||
@ -3031,7 +3034,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
|
||||
}
|
||||
|
||||
// Collect arg for later if it happens to be one we've moving out.
|
||||
if arg.mode == ast::by_move {
|
||||
if arg_mode == ast::by_move {
|
||||
if lv.kind == owned {
|
||||
// Use actual ty, not declared ty -- anything else doesn't make
|
||||
// sense if declared ty is a ty param
|
||||
@ -4414,9 +4417,10 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
|
||||
|
||||
fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
|
||||
arg_tys: [ty::arg]) -> @block_ctxt {
|
||||
let tcx = bcx_tcx(bcx);
|
||||
let arg_n: uint = 0u, bcx = bcx;
|
||||
fn epic_fail_(bcx: @block_ctxt) -> ! {
|
||||
bcx_tcx(bcx).sess.bug("Someone forgot\
|
||||
let epic_fail = fn@() -> ! {
|
||||
tcx.sess.bug("Someone forgot\
|
||||
to document an invariant in copy_args_to_allocas!");
|
||||
}
|
||||
let epic_fail = bind epic_fail_(bcx);
|
||||
@ -4424,7 +4428,7 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
|
||||
let id = args[arg_n].id;
|
||||
let argval = alt fcx.llargs.get(id) { local_mem(v) { v }
|
||||
_ { epic_fail() } };
|
||||
alt arg.mode {
|
||||
alt ty::resolved_mode(tcx, arg.mode) {
|
||||
ast::by_mut_ref { }
|
||||
ast::by_move | ast::by_copy { add_clean(bcx, argval, arg.ty); }
|
||||
ast::by_val {
|
||||
@ -4438,7 +4442,6 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
|
||||
}
|
||||
}
|
||||
ast::by_ref {}
|
||||
_ { epic_fail(); }
|
||||
}
|
||||
if fcx_ccx(fcx).sess.opts.extra_debuginfo {
|
||||
debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
|
||||
@ -4585,7 +4588,7 @@ fn trans_enum_variant(ccx: @crate_ctxt,
|
||||
// Translate variant arguments to function arguments.
|
||||
let fn_args = [], i = 0u;
|
||||
for varg in variant.node.args {
|
||||
fn_args += [{mode: ast::by_copy,
|
||||
fn_args += [{mode: ast::expl(ast::by_copy),
|
||||
ty: varg.ty,
|
||||
ident: "arg" + uint::to_str(i, 10u),
|
||||
id: varg.id}];
|
||||
@ -5039,7 +5042,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
|
||||
takes_argv: bool) -> ValueRef {
|
||||
let unit_ty = ty::mk_str(ccx.tcx);
|
||||
let vecarg_ty: ty::arg =
|
||||
{mode: ast::by_val,
|
||||
{mode: ast::expl(ast::by_val),
|
||||
ty: ty::mk_vec(ccx.tcx, {ty: unit_ty, mut: ast::imm})};
|
||||
// FIXME: mk_nil should have a postcondition
|
||||
let nt = ty::mk_nil(ccx.tcx);
|
||||
|
@ -895,13 +895,20 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
|
||||
[0, abi::closure_body_bindings, b]);
|
||||
bcx = bound_arg.bcx;
|
||||
let val = bound_arg.val;
|
||||
if out_arg.mode == ast::by_val { val = Load(bcx, val); }
|
||||
if out_arg.mode == ast::by_copy {
|
||||
|
||||
alt ty::resolved_mode(tcx, out_arg.mode) {
|
||||
ast::by_val {
|
||||
val = Load(bcx, val);
|
||||
}
|
||||
ast::by_copy {
|
||||
let {bcx: cx, val: alloc} = alloc_ty(bcx, out_arg.ty);
|
||||
bcx = memmove_ty(cx, alloc, val, out_arg.ty);
|
||||
bcx = take_ty(bcx, alloc, out_arg.ty);
|
||||
val = alloc;
|
||||
}
|
||||
ast::by_ref | ast::by_mut_ref | ast::by_move { }
|
||||
}
|
||||
|
||||
// If the type is parameterized, then we need to cast the
|
||||
// type we actually have to the parameterized out type.
|
||||
if ty::type_contains_params(ccx.tcx, out_arg.ty) {
|
||||
|
@ -300,7 +300,8 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
|
||||
let nil_res = ty::mk_nil(ccx.tcx);
|
||||
// FIXME: Silly check -- mk_nil should have a postcondition
|
||||
check non_ty_var(ccx, nil_res);
|
||||
let f_t = type_of_fn(ccx, [{mode: ast::by_ref, ty: inner_t}],
|
||||
let fn_mode = ast::expl(ast::by_ref);
|
||||
let f_t = type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
|
||||
nil_res, *param_bounds);
|
||||
ret base::get_extern_const(ccx.externs, ccx.llmod,
|
||||
csearch::get_symbol(ccx.sess.cstore,
|
||||
|
@ -63,7 +63,8 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
|
||||
fn trans_self_arg(bcx: @block_ctxt, base: @ast::expr) -> result {
|
||||
let tz = [], tr = [];
|
||||
let basety = expr_ty(bcx, base);
|
||||
let {bcx, val} = trans_arg_expr(bcx, {mode: ast::by_ref, ty: basety},
|
||||
let m_by_ref = ast::expl(ast::by_ref);
|
||||
let {bcx, val} = trans_arg_expr(bcx, {mode: m_by_ref, ty: basety},
|
||||
T_ptr(type_of_or_i8(bcx, basety)), tz,
|
||||
tr, base);
|
||||
rslt(bcx, PointerCast(bcx, val, T_opaque_cbox_ptr(bcx_ccx(bcx))))
|
||||
|
@ -1089,10 +1089,12 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [mode] {
|
||||
}
|
||||
|
||||
fn callee_arg_init_ops(fcx: fn_ctxt, callee: node_id) -> [init_op] {
|
||||
fn mode_to_op(m: mode) -> init_op {
|
||||
alt m { by_move { init_move } _ { init_assign } }
|
||||
vec::map(callee_modes(fcx, callee)) {|m|
|
||||
alt ty::resolved_mode(fcx.ccx.tcx, m) {
|
||||
by_move { init_move }
|
||||
by_copy | by_ref | by_val | by_mut_ref { init_assign }
|
||||
}
|
||||
}
|
||||
vec::map(callee_modes(fcx, callee), mode_to_op)
|
||||
}
|
||||
|
||||
fn anon_bindings(ops: [init_op], es: [@expr]) -> [binding] {
|
||||
|
@ -276,12 +276,11 @@ fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) {
|
||||
|
||||
fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [mode],
|
||||
operands: [@expr]) {
|
||||
let i = 0u;
|
||||
for mode: mode in modes {
|
||||
if mode == by_move {
|
||||
forget_in_postcond(fcx, parent.id, operands[i].id);
|
||||
vec::iteri(modes) {|i,mode|
|
||||
alt ty::resolved_mode(fcx.ccx.tcx, mode) {
|
||||
by_move { forget_in_postcond(fcx, parent.id, operands[i].id); }
|
||||
by_ref | by_val | by_mut_ref | by_copy { }
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ import util::common::*;
|
||||
import syntax::util::interner;
|
||||
import util::ppaux::ty_to_str;
|
||||
import util::ppaux::ty_constr_to_str;
|
||||
import util::ppaux::mode_str;
|
||||
import syntax::print::pprust::*;
|
||||
|
||||
export node_id_to_type;
|
||||
@ -168,6 +167,10 @@ export type_structurally_contains;
|
||||
export type_structurally_contains_uniques;
|
||||
export type_autoderef;
|
||||
export type_param;
|
||||
export resolved_mode;
|
||||
export arg_mode;
|
||||
export unify_mode;
|
||||
export set_default_mode;
|
||||
export unify;
|
||||
export variant_info;
|
||||
export walk_ty;
|
||||
@ -178,12 +181,12 @@ export ck_box;
|
||||
export ck_uniq;
|
||||
export param_bound, param_bounds, bound_copy, bound_send, bound_iface;
|
||||
export param_bounds_to_kind;
|
||||
export default_arg_mode_for_ty;
|
||||
|
||||
// Data types
|
||||
|
||||
// TODO: really should be a separate type, or a refinement,
|
||||
// so that we don't have to handle the mode_infer case after
|
||||
// typeck. but that's too hard right now.
|
||||
// Note: after typeck, you should use resolved_mode() to convert this mode
|
||||
// into an rmode, which will take into account the results of mode inference.
|
||||
type arg = {mode: ast::mode, ty: t};
|
||||
|
||||
type field = {ident: ast::ident, mt: mt};
|
||||
@ -217,7 +220,8 @@ type ctxt =
|
||||
ast_ty_to_ty_cache: hashmap<@ast::ty, option<t>>,
|
||||
enum_var_cache: hashmap<def_id, @[variant_info]>,
|
||||
iface_method_cache: hashmap<def_id, @[method]>,
|
||||
ty_param_bounds: hashmap<ast::node_id, param_bounds>};
|
||||
ty_param_bounds: hashmap<ast::node_id, param_bounds>,
|
||||
inferred_modes: hashmap<ast::node_id, ast::mode>};
|
||||
|
||||
type ty_ctxt = ctxt;
|
||||
|
||||
@ -424,7 +428,8 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
|
||||
map::mk_hashmap(ast_util::hash_ty, ast_util::eq_ty),
|
||||
enum_var_cache: new_def_hash(),
|
||||
iface_method_cache: new_def_hash(),
|
||||
ty_param_bounds: map::new_int_hash()};
|
||||
ty_param_bounds: map::new_int_hash(),
|
||||
inferred_modes: map::new_int_hash()};
|
||||
populate_type_store(cx);
|
||||
ret cx;
|
||||
}
|
||||
@ -646,6 +651,12 @@ pure fn ty_name(cx: ctxt, typ: t) -> option<@str> {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_arg_mode_for_ty(tcx: ty::ctxt, ty: ty::t) -> ast::rmode {
|
||||
assert !ty::type_contains_vars(tcx, ty);
|
||||
if ty::type_is_immediate(tcx, ty) { ast::by_val }
|
||||
else { ast::by_ref }
|
||||
}
|
||||
|
||||
fn walk_ty(cx: ctxt, ty: t, f: fn(t)) {
|
||||
alt struct(cx, ty) {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
@ -684,13 +695,14 @@ enum fold_mode {
|
||||
|
||||
fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
|
||||
let ty = ty_0;
|
||||
// Fast paths.
|
||||
|
||||
// Fast paths.
|
||||
alt fld {
|
||||
fm_var(_) { if !type_contains_vars(cx, ty) { ret ty; } }
|
||||
fm_param(_) { if !type_contains_params(cx, ty) { ret ty; } }
|
||||
fm_general(_) {/* no fast path */ }
|
||||
}
|
||||
|
||||
alt interner::get(*cx.ts, ty).struct {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_str | ty_type | ty_send_type | ty_opaque_closure_ptr(_) {}
|
||||
@ -1619,6 +1631,77 @@ fn occurs_check_fails(tcx: ctxt, sp: option<span>, vid: int, rt: t) ->
|
||||
} else { ret false; }
|
||||
}
|
||||
|
||||
// Maintains a little union-set tree for inferred modes. `canon()` returns
|
||||
// the current head value for `m0`.
|
||||
fn canon<T:copy>(tbl: hashmap<ast::node_id, ast::inferable<T>>,
|
||||
m0: ast::inferable<T>) -> ast::inferable<T> {
|
||||
alt m0 {
|
||||
ast::infer(id) {
|
||||
alt tbl.find(id) {
|
||||
none { m0 }
|
||||
some(m1) {
|
||||
let cm1 = canon(tbl, m1);
|
||||
// path compression:
|
||||
if cm1 != m1 { tbl.insert(id, cm1); }
|
||||
cm1
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { m0 }
|
||||
}
|
||||
}
|
||||
|
||||
// Maintains a little union-set tree for inferred modes. `resolve_mode()`
|
||||
// returns the current head value for `m0`.
|
||||
fn canon_mode(cx: ctxt, m0: ast::mode) -> ast::mode {
|
||||
canon(cx.inferred_modes, m0)
|
||||
}
|
||||
|
||||
// Returns the head value for mode, failing if `m` was a infer(_) that
|
||||
// was never inferred. This should be safe for use after typeck.
|
||||
fn resolved_mode(cx: ctxt, m: ast::mode) -> ast::rmode {
|
||||
alt canon_mode(cx, m) {
|
||||
ast::infer(_) {
|
||||
cx.sess.bug(#fmt["mode %? was never resolved", m]);
|
||||
}
|
||||
ast::expl(m0) { m0 }
|
||||
}
|
||||
}
|
||||
|
||||
fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { ty::resolved_mode(cx, a.mode) }
|
||||
|
||||
// Unifies `m1` and `m2`. Returns unified value or failure code.
|
||||
fn unify_mode(cx: ctxt, m1: ast::mode, m2: ast::mode)
|
||||
-> result::t<ast::mode, type_err> {
|
||||
alt (canon_mode(cx, m1), canon_mode(cx, m2)) {
|
||||
(m1, m2) if (m1 == m2) {
|
||||
result::ok(m1)
|
||||
}
|
||||
(ast::infer(id1), ast::infer(id2)) {
|
||||
cx.inferred_modes.insert(id2, m1);
|
||||
result::ok(m1)
|
||||
}
|
||||
(ast::infer(id), m) | (m, ast::infer(id)) {
|
||||
cx.inferred_modes.insert(id, m);
|
||||
result::ok(m1)
|
||||
}
|
||||
(m1, m2) {
|
||||
result::err(terr_mode_mismatch(m1, m2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If `m` was never unified, unifies it with `m_def`. Returns the final value
|
||||
// for `m`.
|
||||
fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
|
||||
alt canon_mode(cx, m) {
|
||||
ast::infer(id) {
|
||||
cx.inferred_modes.insert(id, ast::expl(m_def));
|
||||
}
|
||||
ast::expl(_) { }
|
||||
}
|
||||
}
|
||||
|
||||
// Type unification via Robinson's algorithm (Robinson 1965). Implemented as
|
||||
// described in Hoder and Voronkov:
|
||||
//
|
||||
@ -1869,15 +1952,14 @@ mod unify {
|
||||
for expected_input in e_args {
|
||||
let actual_input = a_args[i];
|
||||
i += 1u;
|
||||
|
||||
// Unify the result modes.
|
||||
let result_mode = if expected_input.mode == ast::mode_infer {
|
||||
actual_input.mode
|
||||
} else if actual_input.mode == ast::mode_infer {
|
||||
expected_input.mode
|
||||
} else if expected_input.mode != actual_input.mode {
|
||||
ret either::left(ures_err(terr_mode_mismatch(
|
||||
expected_input.mode, actual_input.mode)));
|
||||
} else { expected_input.mode };
|
||||
let result_mode =
|
||||
alt unify_mode(cx.tcx, expected_input.mode,
|
||||
actual_input.mode) {
|
||||
result::err(err) { ret either::left(ures_err(err)); }
|
||||
result::ok(m) { m }
|
||||
};
|
||||
|
||||
alt unify_step(cx, expected_input.ty, actual_input.ty,
|
||||
variance) {
|
||||
@ -2446,8 +2528,8 @@ fn type_err_to_str(err: ty::type_err) -> str {
|
||||
}
|
||||
terr_arg_count { ret "incorrect number of function parameters"; }
|
||||
terr_mode_mismatch(e_mode, a_mode) {
|
||||
ret "expected argument mode " + mode_str(e_mode) + " but found " +
|
||||
mode_str(a_mode);
|
||||
ret "expected argument mode " + mode_to_str(e_mode) + " but found " +
|
||||
mode_to_str(a_mode);
|
||||
}
|
||||
terr_constr_len(e_len, a_len) {
|
||||
ret "Expected a type with " + uint::str(e_len) +
|
||||
|
@ -64,7 +64,6 @@ type fn_ctxt =
|
||||
var_bindings: @ty::unify::var_bindings,
|
||||
locals: hashmap<ast::node_id, int>,
|
||||
next_var_id: @mutable int,
|
||||
mutable fixups: [ast::node_id],
|
||||
ccx: @crate_ctxt};
|
||||
|
||||
|
||||
@ -215,27 +214,11 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
|
||||
ret ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
|
||||
}
|
||||
|
||||
// Parses the programmer's textual representation of a type into our internal
|
||||
// notion of a type. `getter` is a function that returns the type
|
||||
// corresponding to a definition ID:
|
||||
fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode,
|
||||
ty: ty::t) -> ast::mode {
|
||||
alt m {
|
||||
ast::mode_infer {
|
||||
alt ty::struct(tcx, ty) {
|
||||
ty::ty_var(_) { ast::mode_infer }
|
||||
_ {
|
||||
if ty::type_is_immediate(tcx, ty) { ast::by_val }
|
||||
else { ast::by_ref }
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { m }
|
||||
}
|
||||
}
|
||||
|
||||
enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), }
|
||||
|
||||
// Parses the programmer's textual representation of a type into our
|
||||
// internal notion of a type. `getter` is a function that returns the type
|
||||
// corresponding to a definition ID:
|
||||
fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
||||
fn getter(tcx: ty::ctxt, mode: mode, id: ast::def_id)
|
||||
-> ty::ty_param_bounds_and_ty {
|
||||
@ -443,13 +426,38 @@ fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
|
||||
}
|
||||
}
|
||||
fn ty_of_arg(tcx: ty::ctxt, mode: mode, a: ast::arg) -> ty::arg {
|
||||
fn arg_mode(tcx: ty::ctxt, m: ast::mode, ty: ty::t) -> ast::mode {
|
||||
alt m {
|
||||
ast::infer(_) {
|
||||
alt ty::struct(tcx, ty) {
|
||||
// If the type is not specified, then this must be a fn expr.
|
||||
// Leave the mode as infer(_), it will get inferred based
|
||||
// on constraints elsewhere.
|
||||
ty::ty_var(_) { m }
|
||||
|
||||
// If the type is known, then use the default for that type.
|
||||
// Here we unify m and the default. This should update the
|
||||
// tables in tcx but should never fail, because nothing else
|
||||
// will have been unified with m yet:
|
||||
_ {
|
||||
let m1 = ast::expl(ty::default_arg_mode_for_ty(tcx, ty));
|
||||
result::get(ty::unify_mode(tcx, m, m1))
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expl(_) { m }
|
||||
}
|
||||
}
|
||||
|
||||
let ty = ast_ty_to_ty(tcx, mode, a.ty);
|
||||
{mode: default_arg_mode_for_ty(tcx, a.mode, ty), ty: ty}
|
||||
let mode = arg_mode(tcx, a.mode, ty);
|
||||
{mode: mode, ty: ty}
|
||||
}
|
||||
fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode,
|
||||
proto: ast::proto, decl: ast::fn_decl) -> ty::fn_ty {
|
||||
let input_tys = [];
|
||||
for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
|
||||
fn ty_of_fn_decl(tcx: ty::ctxt,
|
||||
mode: mode,
|
||||
proto: ast::proto,
|
||||
decl: ast::fn_decl) -> ty::fn_ty {
|
||||
let input_tys = vec::map(decl.inputs) {|a| ty_of_arg(tcx, mode, a) };
|
||||
let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
|
||||
|
||||
let out_constrs = [];
|
||||
@ -472,7 +480,9 @@ fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
|
||||
ty_params: [ast::ty_param], def_id: ast::def_id)
|
||||
-> ty::ty_param_bounds_and_ty {
|
||||
let input_tys = [], bounds = ty_param_bounds(tcx, mode, ty_params);
|
||||
for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; }
|
||||
for a: ast::arg in decl.inputs {
|
||||
input_tys += [ty_of_arg(tcx, mode, a)];
|
||||
}
|
||||
let output_ty = ast_ty_to_ty(tcx, mode, decl.output);
|
||||
|
||||
let t_fn = ty::mk_fn(tcx, {proto: ast::proto_bare,
|
||||
@ -585,7 +595,9 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
|
||||
} else {
|
||||
let auto_modes = vec::map2(impl_m.fty.inputs, if_m.fty.inputs, {|i, f|
|
||||
alt ty::struct(tcx, f.ty) {
|
||||
ty::ty_param(0u, _) { {mode: ast::by_ref with i} }
|
||||
ty::ty_param(0u, _) {
|
||||
{mode: ast::expl(ast::by_ref) with i}
|
||||
}
|
||||
_ { i }
|
||||
}
|
||||
});
|
||||
@ -641,7 +653,7 @@ mod collect {
|
||||
let args: [arg] = [];
|
||||
for va: ast::variant_arg in variant.node.args {
|
||||
let arg_ty = ast_ty_to_ty(cx.tcx, m_collect, va.ty);
|
||||
args += [{mode: ast::by_copy, ty: arg_ty}];
|
||||
args += [{mode: ast::expl(ast::by_copy), ty: arg_ty}];
|
||||
}
|
||||
// FIXME: this will be different for constrained types
|
||||
ty::mk_fn(cx.tcx,
|
||||
@ -716,7 +728,7 @@ mod collect {
|
||||
params);
|
||||
let t_ctor = ty::mk_fn(cx.tcx, {
|
||||
proto: ast::proto_box,
|
||||
inputs: [{mode: ast::by_copy with t_arg}],
|
||||
inputs: [{mode: ast::expl(ast::by_copy) with t_arg}],
|
||||
output: t_res,
|
||||
ret_style: ast::return_val, constraints: []
|
||||
});
|
||||
@ -925,9 +937,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
|
||||
// Type resolution: the phase that finds all the types in the AST with
|
||||
// unresolved type variables and replaces "ty_var" types with their
|
||||
// substitutions.
|
||||
//
|
||||
// TODO: inefficient since not all types have vars in them. It would be better
|
||||
// to maintain a list of fixups.
|
||||
mod writeback {
|
||||
|
||||
export resolve_type_vars_in_block;
|
||||
@ -946,24 +955,32 @@ mod writeback {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id) {
|
||||
fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id)
|
||||
-> option<ty::t> {
|
||||
let fcx = wbcx.fcx, tcx = fcx.ccx.tcx;
|
||||
alt resolve_type_vars_in_type(fcx, sp, ty::node_id_to_type(tcx, id)) {
|
||||
some(t) { write_ty(tcx, id, t); }
|
||||
none { wbcx.success = false; ret }
|
||||
}
|
||||
alt tcx.node_type_substs.find(id) {
|
||||
some(substs) {
|
||||
let new_substs = [];
|
||||
for subst: ty::t in substs {
|
||||
alt resolve_type_vars_in_type(fcx, sp, subst) {
|
||||
some(t) { new_substs += [t]; }
|
||||
none { wbcx.success = false; ret; }
|
||||
}
|
||||
}
|
||||
write_substs(tcx, id, new_substs);
|
||||
none {
|
||||
wbcx.success = false;
|
||||
ret none;
|
||||
}
|
||||
|
||||
some(t) {
|
||||
write_ty(tcx, id, t);
|
||||
alt tcx.node_type_substs.find(id) {
|
||||
some(substs) {
|
||||
let new_substs = [];
|
||||
for subst: ty::t in substs {
|
||||
alt resolve_type_vars_in_type(fcx, sp, subst) {
|
||||
some(t) { new_substs += [t]; }
|
||||
none { wbcx.success = false; ret none; }
|
||||
}
|
||||
}
|
||||
write_substs(tcx, id, new_substs);
|
||||
}
|
||||
none {}
|
||||
}
|
||||
ret some(t);
|
||||
}
|
||||
none {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -984,8 +1001,19 @@ mod writeback {
|
||||
alt e.node {
|
||||
ast::expr_fn(_, decl, _, _) |
|
||||
ast::expr_fn_block(decl, _) {
|
||||
for input in decl.inputs {
|
||||
resolve_type_vars_for_node(wbcx, e.span, input.id);
|
||||
vec::iter(decl.inputs) {|input|
|
||||
let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id);
|
||||
|
||||
// Just in case we never constrained the mode to anything,
|
||||
// constrain it to the default for the type in question.
|
||||
alt (r_ty, input.mode) {
|
||||
(some(t), ast::infer(_)) {
|
||||
let tcx = wbcx.fcx.ccx.tcx;
|
||||
let m_def = ty::default_arg_mode_for_ty(tcx, t);
|
||||
ty::set_default_mode(tcx, input.mode, m_def);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { }
|
||||
@ -1541,8 +1569,8 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
|
||||
unify: unifier,
|
||||
expected: ty::t) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx),
|
||||
proto, decl));
|
||||
let fty = ty::mk_fn(tcx,
|
||||
ty_of_fn_decl(tcx, m_check_tyvar(fcx), proto, decl));
|
||||
|
||||
#debug("check_expr_fn_with_unifier %s fty=%s",
|
||||
expr_to_str(expr),
|
||||
@ -1600,7 +1628,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}]);
|
||||
// HACK: build an arguments list with dummy arguments to
|
||||
// check against
|
||||
let dummy = {mode: ast::by_ref, ty: ty::mk_bot(fcx.ccx.tcx)};
|
||||
let dummy = {mode: ast::expl(ast::by_ref),
|
||||
ty: ty::mk_bot(fcx.ccx.tcx)};
|
||||
arg_tys = vec::init_elt(supplied_arg_count, dummy);
|
||||
}
|
||||
|
||||
@ -2027,7 +2056,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
ty_to_str(tcx, expected));
|
||||
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
|
||||
unify, expected);
|
||||
write_ty(tcx, id, expected);
|
||||
}
|
||||
ast::expr_block(b) {
|
||||
// If this is an unchecked block, turn off purity-checking
|
||||
@ -2428,7 +2456,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
|
||||
// FIXME: this is kinda a kludge; we manufacture a fake function context
|
||||
// and statement context for checking the initializer expression.
|
||||
let rty = node_id_to_type(ccx.tcx, id);
|
||||
let fixups: [ast::node_id] = [];
|
||||
let fcx: @fn_ctxt =
|
||||
@{ret_ty: rty,
|
||||
purity: ast::pure_fn,
|
||||
@ -2436,7 +2463,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
|
||||
var_bindings: ty::unify::mk_var_bindings(),
|
||||
locals: new_int_hash::<int>(),
|
||||
next_var_id: @mutable 0,
|
||||
mutable fixups: fixups,
|
||||
ccx: ccx};
|
||||
check_expr(fcx, e);
|
||||
let cty = expr_ty(fcx.ccx.tcx, e);
|
||||
@ -2449,7 +2475,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
|
||||
// FIXME: this is kinda a kludge; we manufacture a fake function context
|
||||
// and statement context for checking the initializer expression.
|
||||
let rty = node_id_to_type(ccx.tcx, id);
|
||||
let fixups: [ast::node_id] = [];
|
||||
let fcx: @fn_ctxt =
|
||||
@{ret_ty: rty,
|
||||
purity: ast::pure_fn,
|
||||
@ -2457,7 +2482,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
|
||||
var_bindings: ty::unify::mk_var_bindings(),
|
||||
locals: new_int_hash::<int>(),
|
||||
next_var_id: @mutable 0,
|
||||
mutable fixups: fixups,
|
||||
ccx: ccx};
|
||||
let disr_vals: [int] = [];
|
||||
let disr_val = 0;
|
||||
@ -2630,7 +2654,6 @@ fn check_fn(ccx: @crate_ctxt,
|
||||
};
|
||||
|
||||
let gather_result = gather_locals(ccx, decl, body, id, old_fcx);
|
||||
let fixups: [ast::node_id] = [];
|
||||
let fcx: @fn_ctxt =
|
||||
@{ret_ty: ty::ty_fn_ret(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)),
|
||||
purity: purity,
|
||||
@ -2638,7 +2661,6 @@ fn check_fn(ccx: @crate_ctxt,
|
||||
var_bindings: gather_result.var_bindings,
|
||||
locals: gather_result.locals,
|
||||
next_var_id: gather_result.next_var_id,
|
||||
mutable fixups: fixups,
|
||||
ccx: ccx};
|
||||
|
||||
check_constraints(fcx, decl.constraints, decl.inputs);
|
||||
|
@ -160,7 +160,17 @@ enum unop {
|
||||
deref, not, neg,
|
||||
}
|
||||
|
||||
enum mode { by_ref, by_val, by_mut_ref, by_move, by_copy, mode_infer, }
|
||||
// Generally, after typeck you can get the inferred value
|
||||
// using ty::resolved_T(...).
|
||||
enum inferable<T> {
|
||||
expl(T), infer(node_id)
|
||||
}
|
||||
|
||||
// "resolved" mode: the real modes.
|
||||
enum rmode { by_ref, by_val, by_mut_ref, by_move, by_copy }
|
||||
|
||||
// inferable mode.
|
||||
type mode = inferable<rmode>;
|
||||
|
||||
type stmt = spanned<stmt_>;
|
||||
|
||||
|
@ -521,14 +521,19 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
|
||||
}
|
||||
|
||||
fn parse_arg_mode(p: parser) -> ast::mode {
|
||||
if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
|
||||
else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
|
||||
else if eat(p, token::ANDAND) { ast::by_ref }
|
||||
else if eat(p, token::BINOP(token::PLUS)) {
|
||||
if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
|
||||
else { ast::by_copy }
|
||||
}
|
||||
else { ast::mode_infer }
|
||||
if eat(p, token::BINOP(token::AND)) {
|
||||
ast::expl(ast::by_mut_ref)
|
||||
} else if eat(p, token::BINOP(token::MINUS)) {
|
||||
ast::expl(ast::by_move)
|
||||
} else if eat(p, token::ANDAND) {
|
||||
ast::expl(ast::by_ref)
|
||||
} else if eat(p, token::BINOP(token::PLUS)) {
|
||||
if eat(p, token::BINOP(token::PLUS)) {
|
||||
ast::expl(ast::by_val)
|
||||
} else {
|
||||
ast::expl(ast::by_copy)
|
||||
}
|
||||
} else { ast::infer(p.get_id()) }
|
||||
}
|
||||
|
||||
fn parse_arg(p: parser) -> ast::arg {
|
||||
@ -1984,8 +1989,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||
let dtor = parse_block_no_value(p);
|
||||
let decl =
|
||||
{inputs:
|
||||
[{mode: ast::by_ref, ty: t, ident: arg_ident,
|
||||
id: p.get_id()}],
|
||||
[{mode: ast::expl(ast::by_ref), ty: t,
|
||||
ident: arg_ident, id: p.get_id()}],
|
||||
output: @spanned(lo, lo, ast::ty_nil),
|
||||
purity: ast::impure_fn,
|
||||
cf: ast::return_val,
|
||||
|
@ -136,7 +136,7 @@ fn res_to_str(decl: ast::fn_decl, name: ast::ident,
|
||||
fn test_res_to_str() {
|
||||
let decl: ast::fn_decl = {
|
||||
inputs: [{
|
||||
mode: ast::by_val,
|
||||
mode: ast::expl(ast::by_val),
|
||||
ty: @ast_util::respan(ast_util::dummy_sp(), ast::ty_bool),
|
||||
ident: "b",
|
||||
id: 0
|
||||
@ -1280,17 +1280,22 @@ fn print_fn_block_args(s: ps, decl: ast::fn_decl) {
|
||||
maybe_print_comment(s, decl.output.span.lo);
|
||||
}
|
||||
|
||||
fn print_arg_mode(s: ps, m: ast::mode) {
|
||||
fn mode_to_str(m: ast::mode) -> str {
|
||||
alt m {
|
||||
ast::by_mut_ref { word(s.s, "&"); }
|
||||
ast::by_move { word(s.s, "-"); }
|
||||
ast::by_ref { word(s.s, "&&"); }
|
||||
ast::by_val { word(s.s, "++"); }
|
||||
ast::by_copy { word(s.s, "+"); }
|
||||
ast::mode_infer {}
|
||||
ast::expl(ast::by_mut_ref) { "&" }
|
||||
ast::expl(ast::by_move) { "-" }
|
||||
ast::expl(ast::by_ref) { "&&" }
|
||||
ast::expl(ast::by_val) { "++" }
|
||||
ast::expl(ast::by_copy) { "+" }
|
||||
ast::infer(_) { "" }
|
||||
}
|
||||
}
|
||||
|
||||
fn print_arg_mode(s: ps, m: ast::mode) {
|
||||
let ms = mode_to_str(m);
|
||||
if ms != "" { word(s.s, ms); }
|
||||
}
|
||||
|
||||
fn print_bounds(s: ps, bounds: @[ast::ty_param_bound]) {
|
||||
if vec::len(*bounds) > 0u {
|
||||
word(s.s, ":");
|
||||
|
@ -4,32 +4,18 @@ import middle::ty;
|
||||
import middle::ty::*;
|
||||
import metadata::encoder;
|
||||
import syntax::print::pprust;
|
||||
import syntax::print::pprust::{path_to_str, constr_args_to_str, proto_to_str};
|
||||
import syntax::print::pprust::{path_to_str, constr_args_to_str, proto_to_str,
|
||||
mode_to_str};
|
||||
import syntax::{ast, ast_util};
|
||||
import middle::ast_map;
|
||||
|
||||
fn mode_str(m: ast::mode) -> str {
|
||||
alt m {
|
||||
ast::by_ref { "&&" }
|
||||
ast::by_val { "++" }
|
||||
ast::by_mut_ref { "&" }
|
||||
ast::by_move { "-" }
|
||||
ast::by_copy { "+" }
|
||||
_ { "" }
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_to_str(cx: ctxt, typ: t) -> str {
|
||||
fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
|
||||
str {
|
||||
let modestr = alt input.mode {
|
||||
ast::by_ref {
|
||||
if ty::type_is_immediate(cx, input.ty) { "&&" } else { "" }
|
||||
}
|
||||
ast::by_val {
|
||||
if ty::type_is_immediate(cx, input.ty) { "" } else { "++" }
|
||||
}
|
||||
_ { mode_str(input.mode) }
|
||||
let arg_mode = ty::arg_mode(cx, input);
|
||||
let modestr = {
|
||||
if arg_mode == ty::default_arg_mode_for_ty(cx, input.ty) { "" }
|
||||
else { mode_to_str(input.mode) }
|
||||
};
|
||||
modestr + ty_to_str(cx, input.ty)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user