From efc7f82bc44926c864c52caca8764816ab9150dd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 8 Mar 2013 20:44:37 -0500 Subject: [PATCH 1/2] Revamp foreign code not to consider the Rust modes. This requires adjusting a few foreign functions that were declared with by-ref mode. This also allows us to remove by-val mode in the near future. With copy mode, though, we have to be careful because Rust will implicitly pass somethings by pointer but this may not be the C ABI rules. For example, rust will pass a struct Foo as a Foo*. So I added some code into the adapters to fix this (though the C ABI rules may put the pointer back, oh well). This patch also includes a lint mode for the use of by-ref mode in foreign functions as the semantics of this have changed. --- src/libcore/rt/thread.rs | 4 +- src/libcore/unstable.rs | 4 +- src/librustc/lib/llvm.rs | 2 +- src/librustc/middle/lint.rs | 24 +- src/librustc/middle/trans/build.rs | 2 +- src/librustc/middle/trans/callee.rs | 2 +- src/librustc/middle/trans/foreign.rs | 373 +++++++++++++------ src/librustc/middle/trans/type_of.rs | 22 +- src/libstd/time.rs | 16 +- src/rt/rust_builtin.cpp | 44 ++- src/rt/rustrt.def.in | 7 +- src/rustllvm/RustWrapper.cpp | 4 +- src/test/run-pass/extern-pass-TwoU64s-ref.rs | 31 ++ src/test/run-pass/extern-pass-TwoU64s.rs | 32 ++ src/test/run-pass/extern-pass-char.rs | 22 ++ src/test/run-pass/extern-pass-double.rs | 20 + src/test/run-pass/extern-pass-u32.rs | 22 ++ src/test/run-pass/extern-pass-u64.rs | 22 ++ 18 files changed, 492 insertions(+), 161 deletions(-) create mode 100644 src/test/run-pass/extern-pass-TwoU64s-ref.rs create mode 100644 src/test/run-pass/extern-pass-TwoU64s.rs create mode 100644 src/test/run-pass/extern-pass-char.rs create mode 100644 src/test/run-pass/extern-pass-double.rs create mode 100644 src/test/run-pass/extern-pass-u32.rs create mode 100644 src/test/run-pass/extern-pass-u64.rs diff --git a/src/libcore/rt/thread.rs b/src/libcore/rt/thread.rs index cd46127451281..be1d86c9cf741 100644 --- a/src/libcore/rt/thread.rs +++ b/src/libcore/rt/thread.rs @@ -22,7 +22,7 @@ struct Thread { impl Thread { static fn start(main: ~fn()) -> Thread { fn substart(main: &fn()) -> *raw_thread { - unsafe { rust_raw_thread_start(main) } + unsafe { rust_raw_thread_start(&main) } } let raw = substart(main); Thread { @@ -39,6 +39,6 @@ impl Drop for Thread { } extern { - pub unsafe fn rust_raw_thread_start(f: &fn()) -> *raw_thread; + pub unsafe fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread; pub unsafe fn rust_raw_thread_join_delete(thread: *raw_thread); } diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index 7936b18dbe20c..9b6dcc312347a 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -47,7 +47,7 @@ mod rustrt { pub unsafe fn rust_lock_little_lock(lock: rust_little_lock); pub unsafe fn rust_unlock_little_lock(lock: rust_little_lock); - pub unsafe fn rust_raw_thread_start(f: &fn()) -> *raw_thread; + pub unsafe fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread; pub unsafe fn rust_raw_thread_join_delete(thread: *raw_thread); } } @@ -72,7 +72,7 @@ pub fn run_in_bare_thread(f: ~fn()) { let closure: &fn() = || { f() }; - let thread = rustrt::rust_raw_thread_start(closure); + let thread = rustrt::rust_raw_thread_start(&closure); rustrt::rust_raw_thread_join_delete(thread); chan.send(()); } diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index b0cc18a30a41d..23eb6743b9fa8 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1443,7 +1443,7 @@ pub mod llvm { /** Prepares inline assembly. */ pub unsafe fn LLVMInlineAsm(Ty: TypeRef, AsmString: *c_char, Constraints: *c_char, SideEffects: Bool, - AlignStack: Bool, Dialect: AsmDialect) + AlignStack: Bool, Dialect: c_uint) -> ValueRef; } } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 93f0557028eae..47ec756fe0ee5 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -78,6 +78,7 @@ pub enum lint { deprecated_self, deprecated_mutable_fields, deprecated_drop, + foreign_mode, managed_heap_memory, owned_heap_memory, @@ -182,6 +183,13 @@ pub fn get_lint_dict() -> LintDict { default: warn }), + (@~"foreign_mode", + @LintSpec { + lint: foreign_mode, + desc: "warn about deprecated uses of modes in foreign fns", + default: warn + }), + (@~"deprecated_pattern", @LintSpec { lint: deprecated_pattern, @@ -753,6 +761,20 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) { fn check_foreign_fn(cx: ty::ctxt, fn_id: ast::node_id, decl: &ast::fn_decl) { + // warn about `&&` mode on foreign functions, both because it is + // deprecated and because its semantics have changed recently: + for decl.inputs.eachi |i, arg| { + match ty::resolved_mode(cx, arg.mode) { + ast::by_val | ast::by_copy => {} + ast::by_ref => { + cx.sess.span_lint( + foreign_mode, fn_id, fn_id, arg.ty.span, + fmt!("foreign function uses `&&` mode \ + on argument %u", i)); + } + } + } + let tys = vec::map(decl.inputs, |a| a.ty ); for vec::each(vec::append_one(tys, decl.output)) |ty| { match ty.node { @@ -785,7 +807,7 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) { if attr::foreign_abi(it.attrs) != either::Right(ast::foreign_abi_rust_intrinsic) => { for nmod.items.each |ni| { - match /*bad*/copy ni.node { + match ni.node { ast::foreign_item_fn(ref decl, _, _) => { check_foreign_fn(cx, it.id, decl); } diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index e75cf14ff6945..850ea908e74ee 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -885,7 +885,7 @@ pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char, let llfty = T_fn(~[], T_void()); let v = llvm::LLVMInlineAsm(llfty, asm, cons, volatile, - alignstack, dia); + alignstack, dia as c_uint); Call(cx, v, ~[]) } diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 9e38252dc9a8a..5052ce0767115 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -757,7 +757,7 @@ pub fn trans_arg_expr(bcx: block, if formal_ty.ty != arg_datum.ty { // this could happen due to e.g. subtyping - let llformal_ty = type_of::type_of_explicit_arg(ccx, formal_ty); + let llformal_ty = type_of::type_of_explicit_arg(ccx, &formal_ty); debug!("casting actual type (%s) to match formal (%s)", bcx.val_str(val), bcx.llty_str(llformal_ty)); val = PointerCast(bcx, val, llformal_ty); diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 1e3c4f21bd875..fde1de5b63f21 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -58,59 +58,90 @@ pub fn link_name(ccx: @CrateContext, i: @ast::foreign_item) -> @~str { } } -struct c_stack_tys { - arg_tys: ~[TypeRef], - ret_ty: TypeRef, +struct ShimTypes { + fn_sig: ty::FnSig, + + /// LLVM types that will appear on the foreign function + llsig: LlvmSignature, + + /// True if there is a return value (not bottom, not unit) ret_def: bool, + + /// Type of the struct we will use to shuttle values back and forth. + /// This is always derived from the llsig. bundle_ty: TypeRef, + + /// Type of the shim function itself. shim_fn_ty: TypeRef, + + /// Adapter object for handling native ABI rules (trust me, you + /// don't want to know). fn_ty: cabi::FnType } -fn c_arg_and_ret_lltys(ccx: @CrateContext, - id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) { - match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty { - ty::ty_bare_fn(ref fn_ty) => { - let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs); - let llretty = type_of::type_of(ccx, fn_ty.sig.output); - (llargtys, llretty, fn_ty.sig.output) - } - _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type") - } +struct LlvmSignature { + llarg_tys: ~[TypeRef], + llret_ty: TypeRef, } -fn c_stack_tys(ccx: @CrateContext, - id: ast::node_id) -> @c_stack_tys { - let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, id); - // XXX: Bad copy. - let bundle_ty = T_struct(vec::append_one(copy llargtys, T_ptr(llretty))); - let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); - let fn_ty = abi_info(ccx.sess.targ_cfg.arch). - compute_info(llargtys, llretty, ret_def); - return @c_stack_tys { - arg_tys: llargtys, - ret_ty: llretty, +fn foreign_signature(ccx: @CrateContext, + fn_sig: &ty::FnSig) -> LlvmSignature { + /*! + * The ForeignSignature is the LLVM types of the arguments/return type + * of a function. Note that these LLVM types are not quite the same + * as the LLVM types would be for a native Rust function because foreign + * functions just plain ignore modes. They also don't pass aggregate + * values by pointer like we do. + */ + + let llarg_tys = fn_sig.inputs.map(|arg| type_of(ccx, arg.ty)); + let llret_ty = type_of::type_of(ccx, fn_sig.output); + LlvmSignature {llarg_tys: llarg_tys, llret_ty: llret_ty} +} + +fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { + let fn_sig = match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty { + ty::ty_bare_fn(ref fn_ty) => copy fn_ty.sig, + _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type") + }; + let llsig = foreign_signature(ccx, &fn_sig); + let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys, + T_ptr(llsig.llret_ty))); + let ret_def = + !ty::type_is_bot(fn_sig.output) && + !ty::type_is_nil(fn_sig.output); + let fn_ty = + abi_info(ccx.sess.targ_cfg.arch).compute_info( + llsig.llarg_tys, + llsig.llret_ty, + ret_def); + ShimTypes { + fn_sig: fn_sig, + llsig: llsig, ret_def: ret_def, bundle_ty: bundle_ty, shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_void()), fn_ty: fn_ty - }; + } } -type shim_arg_builder = &self/fn(bcx: block, tys: @c_stack_tys, - llargbundle: ValueRef) -> ~[ValueRef]; +type shim_arg_builder<'self> = + &'self fn(bcx: block, tys: &ShimTypes, + llargbundle: ValueRef) -> ~[ValueRef]; -type shim_ret_builder = &self/fn(bcx: block, tys: @c_stack_tys, - llargbundle: ValueRef, llretval: ValueRef); +type shim_ret_builder<'self> = + &'self fn(bcx: block, tys: &ShimTypes, + llargbundle: ValueRef, + llretval: ValueRef); fn build_shim_fn_(ccx: @CrateContext, +shim_name: ~str, llbasefn: ValueRef, - tys: @c_stack_tys, + tys: &ShimTypes, cc: lib::llvm::CallConv, arg_builder: shim_arg_builder, - ret_builder: shim_ret_builder) -> ValueRef { - + ret_builder: shim_ret_builder) -> ValueRef +{ let llshimfn = decl_internal_cdecl_fn( ccx.llmod, shim_name, tys.shim_fn_ty); @@ -122,8 +153,7 @@ fn build_shim_fn_(ccx: @CrateContext, let llargvals = arg_builder(bcx, tys, llargbundle); // Create the call itself and store the return value: - let llretval = CallWithConv(bcx, llbasefn, - llargvals, cc); // r + let llretval = CallWithConv(bcx, llbasefn, llargvals, cc); ret_builder(bcx, tys, llargbundle, llretval); @@ -133,21 +163,22 @@ fn build_shim_fn_(ccx: @CrateContext, return llshimfn; } -type wrap_arg_builder = &self/fn(bcx: block, tys: @c_stack_tys, - llwrapfn: ValueRef, - llargbundle: ValueRef); +type wrap_arg_builder<'self> = + &'self fn(bcx: block, tys: &ShimTypes, + llwrapfn: ValueRef, llargbundle: ValueRef); -type wrap_ret_builder = &self/fn(bcx: block, tys: @c_stack_tys, - llargbundle: ValueRef); +type wrap_ret_builder<'self> = + &'self fn(bcx: block, tys: &ShimTypes, + llargbundle: ValueRef); fn build_wrap_fn_(ccx: @CrateContext, - tys: @c_stack_tys, + tys: &ShimTypes, llshimfn: ValueRef, llwrapfn: ValueRef, shim_upcall: ValueRef, arg_builder: wrap_arg_builder, - ret_builder: wrap_ret_builder) { - + ret_builder: wrap_ret_builder) +{ let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_"); let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, None); let bcx = top_scope_block(fcx, None); @@ -199,36 +230,83 @@ fn build_wrap_fn_(ccx: @CrateContext, // F(args->z, args->x, args->y); // } // -// Note: on i386, the layout of the args struct is generally the same as the -// desired layout of the arguments on the C stack. Therefore, we could use -// upcall_alloc_c_stack() to allocate the `args` structure and switch the -// stack pointer appropriately to avoid a round of copies. (In fact, the shim -// function itself is unnecessary). We used to do this, in fact, and will -// perhaps do so in the future. +// Note: on i386, the layout of the args struct is generally the same +// as the desired layout of the arguments on the C stack. Therefore, +// we could use upcall_alloc_c_stack() to allocate the `args` +// structure and switch the stack pointer appropriately to avoid a +// round of copies. (In fact, the shim function itself is +// unnecessary). We used to do this, in fact, and will perhaps do so +// in the future. pub fn trans_foreign_mod(ccx: @CrateContext, foreign_mod: &ast::foreign_mod, - abi: ast::foreign_abi) { - + abi: ast::foreign_abi) +{ let _icx = ccx.insn_ctxt("foreign::trans_foreign_mod"); + let mut cc = match abi { + ast::foreign_abi_rust_intrinsic | + ast::foreign_abi_cdecl => lib::llvm::CCallConv, + ast::foreign_abi_stdcall => lib::llvm::X86StdcallCallConv + }; + + for vec::each(foreign_mod.items) |foreign_item| { + match foreign_item.node { + ast::foreign_item_fn(*) => { + let id = foreign_item.id; + if abi != ast::foreign_abi_rust_intrinsic { + let llwrapfn = get_item_val(ccx, id); + let tys = shim_types(ccx, id); + if attr::attrs_contains_name( + foreign_item.attrs, "rust_stack") + { + build_direct_fn(ccx, llwrapfn, *foreign_item, + &tys, cc); + } else { + let llshimfn = build_shim_fn(ccx, *foreign_item, + &tys, cc); + build_wrap_fn(ccx, &tys, llshimfn, llwrapfn); + } + } else { + // Intrinsics are emitted by monomorphic fn + } + } + ast::foreign_item_const(*) => { + let ident = ccx.sess.parse_sess.interner.get( + foreign_item.ident); + ccx.item_symbols.insert(foreign_item.id, copy *ident); + } + } + } + fn build_shim_fn(ccx: @CrateContext, foreign_item: @ast::foreign_item, - tys: @c_stack_tys, - cc: lib::llvm::CallConv) -> ValueRef { + tys: &ShimTypes, + cc: lib::llvm::CallConv) -> ValueRef + { + /*! + * + * Build S, from comment above: + * + * void S(struct { X x; Y y; Z *z; } *args) { + * F(args->z, args->x, args->y); + * } + */ let _icx = ccx.insn_ctxt("foreign::build_shim_fn"); - fn build_args(bcx: block, tys: @c_stack_tys, + fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::shim::build_args"); - return tys.fn_ty.build_shim_args(bcx, tys.arg_tys, llargbundle); + tys.fn_ty.build_shim_args( + bcx, tys.llsig.llarg_tys, llargbundle) } - fn build_ret(bcx: block, tys: @c_stack_tys, + fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef, llretval: ValueRef) { let _icx = bcx.insn_ctxt("foreign::shim::build_ret"); - tys.fn_ty.build_shim_ret(bcx, tys.arg_tys, tys.ret_def, - llargbundle, llretval); + tys.fn_ty.build_shim_ret( + bcx, tys.llsig.llarg_tys, + tys.ret_def, llargbundle, llretval); } let lname = link_name(ccx, foreign_item); @@ -239,7 +317,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, build_args, build_ret); } - fn base_fn(ccx: @CrateContext, lname: &str, tys: @c_stack_tys, + fn base_fn(ccx: @CrateContext, lname: &str, tys: &ShimTypes, cc: lib::llvm::CallConv) -> ValueRef { // Declare the "prototype" for the base function F: do tys.fn_ty.decl_fn |fnty| { @@ -250,7 +328,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, // FIXME (#2535): this is very shaky and probably gets ABIs wrong all // over the place fn build_direct_fn(ccx: @CrateContext, decl: ValueRef, - item: @ast::foreign_item, tys: @c_stack_tys, + item: @ast::foreign_item, tys: &ShimTypes, cc: lib::llvm::CallConv) { let fcx = new_fn_ctxt(ccx, ~[], decl, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; @@ -269,66 +347,55 @@ pub fn trans_foreign_mod(ccx: @CrateContext, } fn build_wrap_fn(ccx: @CrateContext, - tys: @c_stack_tys, + tys: &ShimTypes, llshimfn: ValueRef, llwrapfn: ValueRef) { + /*! + * + * Build W, from comment above: + * + * void W(Z* dest, void *env, X x, Y y) { + * struct { X x; Y y; Z *z; } args = { x, y, z }; + * call_on_c_stack_shim(S, &args); + * } + * + * One thing we have to be very careful of is to + * account for the Rust modes. + */ let _icx = ccx.insn_ctxt("foreign::build_wrap_fn"); - fn build_args(bcx: block, tys: @c_stack_tys, + build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, + ccx.upcalls.call_shim_on_c_stack, + build_args, build_ret); + + fn build_args(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_args"); - let mut i = 0u; - let n = vec::len(tys.arg_tys); + let ccx = bcx.ccx(); + let n = vec::len(tys.llsig.llarg_tys); let implicit_args = first_real_arg; // return + env - while i < n { - let llargval = get_param(llwrapfn, i + implicit_args); + for uint::range(0, n) |i| { + let mut llargval = get_param(llwrapfn, i + implicit_args); + + // In some cases, Rust will pass a pointer which the + // native C type doesn't have. In that case, just + // load the value from the pointer. + if type_of::arg_is_indirect(ccx, &tys.fn_sig.inputs[i]) { + llargval = Load(bcx, llargval); + } + store_inbounds(bcx, llargval, llargbundle, ~[0u, i]); - i += 1u; } let llretptr = get_param(llwrapfn, 0u); store_inbounds(bcx, llretptr, llargbundle, ~[0u, n]); } - fn build_ret(bcx: block, _tys: @c_stack_tys, + fn build_ret(bcx: block, _tys: &ShimTypes, _llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_ret"); RetVoid(bcx); } - - build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, - ccx.upcalls.call_shim_on_c_stack, - build_args, build_ret); - } - - let mut cc = match abi { - ast::foreign_abi_rust_intrinsic | - ast::foreign_abi_cdecl => lib::llvm::CCallConv, - ast::foreign_abi_stdcall => lib::llvm::X86StdcallCallConv - }; - - for vec::each(foreign_mod.items) |foreign_item| { - match foreign_item.node { - ast::foreign_item_fn(*) => { - let id = foreign_item.id; - if abi != ast::foreign_abi_rust_intrinsic { - let llwrapfn = get_item_val(ccx, id); - let tys = c_stack_tys(ccx, id); - if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") { - build_direct_fn(ccx, llwrapfn, *foreign_item, tys, cc); - } else { - let llshimfn = build_shim_fn(ccx, *foreign_item, tys, cc); - build_wrap_fn(ccx, tys, llshimfn, llwrapfn); - } - } else { - // Intrinsics are emitted by monomorphic fn - } - } - ast::foreign_item_const(*) => { - let ident = ccx.sess.parse_sess.interner.get(foreign_item.ident); - ccx.item_symbols.insert(foreign_item.id, copy *ident); - } - } } } @@ -842,6 +909,32 @@ pub fn trans_intrinsic(ccx: @CrateContext, finish_fn(fcx, lltop); } +/** + * Translates a "crust" fn, meaning a Rust fn that can be called + * from C code. In this case, we have to perform some adaptation + * to (1) switch back to the Rust stack and (2) adapt the C calling + * convention to our own. + * + * Example: Given a crust fn F(x: X, y: Y) -> Z, we generate a + * Rust function R as normal: + * + * void R(Z* dest, void *env, X x, Y y) {...} + * + * and then we generate a wrapper function W that looks like: + * + * Z W(X x, Y y) { + * struct { X x; Y y; Z *z; } args = { x, y, z }; + * call_on_c_stack_shim(S, &args); + * } + * + * Note that the wrapper follows the foreign (typically "C") ABI. + * The wrapper is the actual "value" of the foreign fn. Finally, + * we generate a shim function S that looks like: + * + * void S(struct { X x; Y y; Z *z; } *args) { + * R(args->z, NULL, args->x, args->y); + * } + */ pub fn trans_foreign_fn(ccx: @CrateContext, +path: ast_map::path, decl: &ast::fn_decl, @@ -867,28 +960,51 @@ pub fn trans_foreign_fn(ccx: @CrateContext, } fn build_shim_fn(ccx: @CrateContext, +path: ast_map::path, - llrustfn: ValueRef, tys: @c_stack_tys) -> ValueRef { + llrustfn: ValueRef, tys: &ShimTypes) -> ValueRef { + /*! + * + * Generate the shim S: + * + * void S(struct { X x; Y y; Z *z; } *args) { + * R(args->z, NULL, &args->x, args->y); + * } + * + * One complication is that we must adapt to the Rust + * calling convention, which introduces indirection + * in some cases. To demonstrate this, I wrote one of the + * entries above as `&args->x`, because presumably `X` is + * one of those types that is passed by pointer in Rust. + */ + let _icx = ccx.insn_ctxt("foreign::foreign::build_shim_fn"); - fn build_args(bcx: block, tys: @c_stack_tys, + fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::extern::shim::build_args"); + let ccx = bcx.ccx(); let mut llargvals = ~[]; let mut i = 0u; - let n = vec::len(tys.arg_tys); + let n = tys.fn_sig.inputs.len(); let llretptr = load_inbounds(bcx, llargbundle, ~[0u, n]); llargvals.push(llretptr); let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx())); llargvals.push(llenvptr); while i < n { - let llargval = load_inbounds(bcx, llargbundle, ~[0u, i]); + // Get a pointer to the argument: + let mut llargval = GEPi(bcx, llargbundle, [0u, i]); + + if !type_of::arg_is_indirect(ccx, &tys.fn_sig.inputs[i]) { + // If Rust would pass this by value, load the value. + llargval = Load(bcx, llargval); + } + llargvals.push(llargval); i += 1u; } return llargvals; } - fn build_ret(_bcx: block, _tys: @c_stack_tys, + fn build_ret(_bcx: block, _tys: &ShimTypes, _llargbundle: ValueRef, _llretval: ValueRef) { // Nop. The return pointer in the Rust ABI function // is wired directly into the return slot in the shim struct @@ -904,36 +1020,48 @@ pub fn trans_foreign_fn(ccx: @CrateContext, } fn build_wrap_fn(ccx: @CrateContext, llshimfn: ValueRef, - llwrapfn: ValueRef, tys: @c_stack_tys) { + llwrapfn: ValueRef, tys: &ShimTypes) + { + /*! + * + * Generate the wrapper W: + * + * Z W(X x, Y y) { + * struct { X x; Y y; Z *z; } args = { x, y, z }; + * call_on_c_stack_shim(S, &args); + * } + */ let _icx = ccx.insn_ctxt("foreign::foreign::build_wrap_fn"); - fn build_args(bcx: block, tys: @c_stack_tys, + build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, + ccx.upcalls.call_shim_on_rust_stack, + build_args, build_ret); + + fn build_args(bcx: block, tys: &ShimTypes, llwrapfn: ValueRef, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); - tys.fn_ty.build_wrap_args(bcx, tys.ret_ty, - llwrapfn, llargbundle); + tys.fn_ty.build_wrap_args( + bcx, tys.llsig.llret_ty, + llwrapfn, llargbundle); } - fn build_ret(bcx: block, tys: @c_stack_tys, + fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_ret"); - tys.fn_ty.build_wrap_ret(bcx, tys.arg_tys, llargbundle); + tys.fn_ty.build_wrap_ret( + bcx, tys.llsig.llarg_tys, llargbundle); } - - build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, - ccx.upcalls.call_shim_on_rust_stack, - build_args, build_ret); } - let tys = c_stack_tys(ccx, id); + let tys = shim_types(ccx, id); // The internal Rust ABI function - runs on the Rust stack // XXX: Bad copy. let llrustfn = build_rust_fn(ccx, copy path, decl, body, id); // The internal shim function - runs on the Rust stack - let llshimfn = build_shim_fn(ccx, path, llrustfn, tys); + let llshimfn = build_shim_fn(ccx, path, llrustfn, &tys); // The foreign C function - runs on the C stack - build_wrap_fn(ccx, llshimfn, llwrapfn, tys) + build_wrap_fn(ccx, llshimfn, llwrapfn, &tys) } pub fn register_foreign_fn(ccx: @CrateContext, @@ -944,11 +1072,8 @@ pub fn register_foreign_fn(ccx: @CrateContext, -> ValueRef { let _icx = ccx.insn_ctxt("foreign::register_foreign_fn"); let t = ty::node_id_to_type(ccx.tcx, node_id); - let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, node_id); - let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); - let fn_ty = abi_info(ccx.sess.targ_cfg.arch). - compute_info(llargtys, llretty, ret_def); - do fn_ty.decl_fn |fnty| { + let tys = shim_types(ccx, node_id); + do tys.fn_ty.decl_fn |fnty| { register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs, t, lib::llvm::CCallConv, fnty) } diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 68eb0852445e0..2a390a03fa142 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -21,24 +21,22 @@ use util::ppaux; use core::option::None; use syntax::ast; -pub fn type_of_explicit_arg(ccx: @CrateContext, arg: ty::arg) -> TypeRef { - let llty = type_of(ccx, arg.ty); +pub fn arg_is_indirect(ccx: @CrateContext, arg: &ty::arg) -> bool { match ty::resolved_mode(ccx.tcx, arg.mode) { - ast::by_val => llty, - ast::by_copy => { - if ty::type_is_immediate(arg.ty) { - llty - } else { - T_ptr(llty) - } - } - _ => T_ptr(llty) + ast::by_val => false, + ast::by_copy => !ty::type_is_immediate(arg.ty), + ast::by_ref => true } } +pub fn type_of_explicit_arg(ccx: @CrateContext, arg: &ty::arg) -> TypeRef { + let llty = type_of(ccx, arg.ty); + if arg_is_indirect(ccx, arg) {T_ptr(llty)} else {llty} +} + pub fn type_of_explicit_args(ccx: @CrateContext, inputs: &[ty::arg]) -> ~[TypeRef] { - inputs.map(|arg| type_of_explicit_arg(ccx, *arg)) + inputs.map(|arg| type_of_explicit_arg(ccx, arg)) } pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], diff --git a/src/libstd/time.rs b/src/libstd/time.rs index d6e19515ba655..d768eef9a8c9b 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -30,10 +30,10 @@ pub mod rustrt { pub unsafe fn rust_tzset(); // FIXME: The i64 values can be passed by-val when #2064 is fixed. - pub unsafe fn rust_gmtime(&&sec: i64, &&nsec: i32, &&result: Tm); - pub unsafe fn rust_localtime(&&sec: i64, &&nsec: i32, &&result: Tm); - pub unsafe fn rust_timegm(&&tm: Tm, sec: &mut i64); - pub unsafe fn rust_mktime(&&tm: Tm, sec: &mut i64); + pub unsafe fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm); + pub unsafe fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm); + pub unsafe fn rust_timegm(tm: &Tm, sec: &mut i64); + pub unsafe fn rust_mktime(tm: &Tm, sec: &mut i64); } } @@ -172,7 +172,7 @@ pub fn at_utc(clock: Timespec) -> Tm { unsafe { let mut Timespec { sec, nsec } = clock; let mut tm = empty_tm(); - rustrt::rust_gmtime(sec, nsec, tm); + rustrt::rust_gmtime(sec, nsec, &mut tm); tm } } @@ -187,7 +187,7 @@ pub fn at(clock: Timespec) -> Tm { unsafe { let mut Timespec { sec, nsec } = clock; let mut tm = empty_tm(); - rustrt::rust_localtime(sec, nsec, tm); + rustrt::rust_localtime(sec, nsec, &mut tm); tm } } @@ -217,9 +217,9 @@ pub impl Tm { unsafe { let mut sec = 0i64; if self.tm_gmtoff == 0_i32 { - rustrt::rust_timegm(*self, &mut sec); + rustrt::rust_timegm(self, &mut sec); } else { - rustrt::rust_mktime(*self, &mut sec); + rustrt::rust_mktime(self, &mut sec); } Timespec::new(sec, self.tm_nsec) } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 8d83e2036b9be..5a9de9735ba03 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -434,18 +434,18 @@ rust_tzset() { } extern "C" CDECL void -rust_gmtime(int64_t *sec, int32_t *nsec, rust_tm *timeptr) { +rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { tm tm; - time_t s = *sec; + time_t s = sec; GMTIME(&s, &tm); - tm_to_rust_tm(&tm, timeptr, 0, "UTC", *nsec); + tm_to_rust_tm(&tm, timeptr, 0, "UTC", nsec); } extern "C" CDECL void -rust_localtime(int64_t *sec, int32_t *nsec, rust_tm *timeptr) { +rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { tm tm; - time_t s = *sec; + time_t s = sec; LOCALTIME(&s, &tm); #if defined(__WIN32__) @@ -457,7 +457,7 @@ rust_localtime(int64_t *sec, int32_t *nsec, rust_tm *timeptr) { const char *zone = tm.tm_zone; #endif - tm_to_rust_tm(&tm, timeptr, gmtoff, zone, *nsec); + tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec); } extern "C" CDECL void @@ -844,6 +844,38 @@ rust_readdir() { #endif +// These functions are used in the unit tests for C ABI calls. + +extern "C" CDECL uint32_t +rust_dbg_extern_identity_u32(uint32_t u) { + return u; +} + +extern "C" CDECL uint64_t +rust_dbg_extern_identity_u64(uint64_t u) { + return u; +} + +struct TwoU64s { + uint64_t one; + uint64_t two; +}; + +extern "C" CDECL TwoU64s +rust_dbg_extern_identity_TwoU64s(TwoU64s u) { + return u; +} + +extern "C" CDECL double +rust_dbg_extern_identity_double(double u) { + return u; +} + +extern "C" CDECL char +rust_dbg_extern_identity_u8(char u) { + return u; +} + // // Local Variables: diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 886d945b144e2..7fb6334ca754c 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -195,4 +195,9 @@ rust_get_exchange_count_ptr rust_get_sched_tls_key swap_registers rust_readdir -rust_opendir \ No newline at end of file +rust_opendir +rust_dbg_extern_identity_u32 +rust_dbg_extern_identity_u64 +rust_dbg_extern_identity_TwoU64s +rust_dbg_extern_identity_double +rust_dbg_extern_identity_u8 diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 7686dcd4ff4dc..12b305720cc93 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -546,8 +546,8 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty, char *Constraints, LLVMBool HasSideEffects, LLVMBool IsAlignStack, - InlineAsm::AsmDialect Dialect) { + unsigned Dialect) { return wrap(InlineAsm::get(unwrap(Ty), AsmString, Constraints, HasSideEffects, - IsAlignStack, Dialect)); + IsAlignStack, (InlineAsm::AsmDialect) Dialect)); } diff --git a/src/test/run-pass/extern-pass-TwoU64s-ref.rs b/src/test/run-pass/extern-pass-TwoU64s-ref.rs new file mode 100644 index 0000000000000..00754afa703b2 --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU64s-ref.rs @@ -0,0 +1,31 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we ignore modes when calling extern functions. + +// xfail-test --- broken on 32-bit ABIs! (#5347) + +#[deriving_eq] +struct TwoU64s { + one: u64, two: u64 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU64s(&&u: TwoU64s) -> TwoU64s; +} + +pub fn main() { + unsafe { + let x = TwoU64s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU64s(x); + fail_unless!(x == y); + } +} + diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs new file mode 100644 index 0000000000000..2baf383ce545f --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -0,0 +1,32 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +// xfail-test --- broken on 32-bit ABIs! (#5347) + +#[deriving_eq] +struct TwoU64s { + one: u64, two: u64 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s; +} + +pub fn main() { + unsafe { + let x = TwoU64s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU64s(x); + fail_unless!(x == y); + } +} + diff --git a/src/test/run-pass/extern-pass-char.rs b/src/test/run-pass/extern-pass-char.rs new file mode 100644 index 0000000000000..104ea342cd5e0 --- /dev/null +++ b/src/test/run-pass/extern-pass-char.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a function that takes/returns a u8. + +pub extern { + pub fn rust_dbg_extern_identity_u8(v: u8) -> u8; +} + +pub fn main() { + unsafe { + fail_unless!(22_u8 == rust_dbg_extern_identity_u8(22_u8)); + } +} + diff --git a/src/test/run-pass/extern-pass-double.rs b/src/test/run-pass/extern-pass-double.rs new file mode 100644 index 0000000000000..afdec4d100298 --- /dev/null +++ b/src/test/run-pass/extern-pass-double.rs @@ -0,0 +1,20 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub extern { + pub fn rust_dbg_extern_identity_double(v: f64) -> f64; +} + +pub fn main() { + unsafe { + fail_unless!(22.0_f64 == rust_dbg_extern_identity_double(22.0_f64)); + } +} + diff --git a/src/test/run-pass/extern-pass-u32.rs b/src/test/run-pass/extern-pass-u32.rs new file mode 100644 index 0000000000000..0d6220e7b25cd --- /dev/null +++ b/src/test/run-pass/extern-pass-u32.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a function that takes/returns a u32. + +pub extern { + pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; +} + +pub fn main() { + unsafe { + fail_unless!(22_u32 == rust_dbg_extern_identity_u32(22_u32)); + } +} + diff --git a/src/test/run-pass/extern-pass-u64.rs b/src/test/run-pass/extern-pass-u64.rs new file mode 100644 index 0000000000000..3177703523833 --- /dev/null +++ b/src/test/run-pass/extern-pass-u64.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a call to a function that takes/returns a u64. + +pub extern { + pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; +} + +pub fn main() { + unsafe { + fail_unless!(22_u64 == rust_dbg_extern_identity_u64(22_u64)); + } +} + From 852619d5d7ef7e9b9c5e57102e244c575f0c6a8f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 10 Mar 2013 11:02:16 -0400 Subject: [PATCH 2/2] Remove `++` mode from the compiler (it is parsed as `+` mode) and obsolete `-` mode altogether (it *was* parsed as `+` mode). --- src/libcore/cast.rs | 2 +- src/libcore/unstable/intrinsics.rs | 4 ++-- src/librustc/back/link.rs | 4 ++-- src/librustc/driver/driver.rs | 4 ++-- src/librustc/metadata/creader.rs | 2 +- src/librustc/metadata/decoder.rs | 2 +- src/librustc/metadata/loader.rs | 2 +- src/librustc/metadata/tydecode.rs | 1 - src/librustc/metadata/tyencode.rs | 1 - src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/borrowck/gather_loans.rs | 4 ++-- src/librustc/middle/lint.rs | 2 +- src/librustc/middle/liveness.rs | 4 ++-- src/librustc/middle/mem_categorization.rs | 8 -------- src/librustc/middle/moves.rs | 2 +- src/librustc/middle/resolve.rs | 10 +++++----- src/librustc/middle/trans/_match.rs | 2 +- src/librustc/middle/trans/base.rs | 8 +------- src/librustc/middle/trans/callee.rs | 8 -------- src/librustc/middle/trans/common.rs | 10 +++++----- src/librustc/middle/trans/controlflow.rs | 2 +- src/librustc/middle/trans/meth.rs | 2 +- src/librustc/middle/trans/reflect.rs | 1 - src/librustc/middle/trans/type_of.rs | 1 - src/librustc/middle/trans/type_use.rs | 6 +++--- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 4 ++-- src/librustc/middle/typeck/mod.rs | 20 ------------------- src/libstd/arena.rs | 2 +- src/libstd/priority_queue.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_map.rs | 6 +++--- src/libsyntax/attr.rs | 6 +++--- src/libsyntax/parse/obsolete.rs | 5 +++++ src/libsyntax/parse/parser.rs | 10 +++++++--- src/libsyntax/print/pprust.rs | 1 - src/test/auxiliary/cci_class_6.rs | 2 +- src/test/bench/graph500-bfs.rs | 2 +- .../bench/task-perf-jargon-metal-smoke.rs | 2 +- .../compile-fail/liveness-move-from-args.rs | 4 ---- .../compile-fail/liveness-use-after-send.rs | 2 +- src/test/compile-fail/mutable-arguments.rs | 7 +------ src/test/run-fail/unwind-move.rs | 2 +- src/test/run-pass/argument-passing.rs | 2 +- src/test/run-pass/borrowck-lend-args.rs | 8 -------- src/test/run-pass/class-poly-methods.rs | 2 +- src/test/run-pass/intrinsic-move-val.rs | 4 ++-- src/test/run-pass/issue-2718.rs | 18 ++++++++--------- src/test/run-pass/liveness-move-in-loop.rs | 2 +- src/test/run-pass/move-arg-2-unique.rs | 2 +- src/test/run-pass/move-arg-2.rs | 2 +- src/test/run-pass/move-arg.rs | 2 +- src/test/run-pass/move-nullary-fn.rs | 4 ++-- src/test/run-pass/pipe-bank-proto.rs | 2 +- src/test/run-pass/pipe-pingpong-bounded.rs | 4 ++-- src/test/run-pass/pipe-pingpong-proto.rs | 4 ++-- src/test/run-pass/unique-fn-arg-move.rs | 2 +- 57 files changed, 89 insertions(+), 144 deletions(-) diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs index f17b04da503a9..bc4358db56c7e 100644 --- a/src/libcore/cast.rs +++ b/src/libcore/cast.rs @@ -12,7 +12,7 @@ pub mod rusti { #[abi = "rust-intrinsic"] #[link_name = "rusti"] pub extern { - fn forget(-x: T); + fn forget(+x: T); fn reinterpret_cast(&&e: T) -> U; } } diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs index 8f0067b739335..a27ac2ccb6b3a 100644 --- a/src/libcore/unstable/intrinsics.rs +++ b/src/libcore/unstable/intrinsics.rs @@ -34,8 +34,8 @@ pub extern { pub fn size_of() -> uint; - pub fn move_val(dst: &mut T, -src: T); - pub fn move_val_init(dst: &mut T, -src: T); + pub fn move_val(dst: &mut T, +src: T); + pub fn move_val_init(dst: &mut T, +src: T); pub fn min_align_of() -> uint; pub fn pref_align_of() -> uint; diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3c6b9b6232e2e..84836568029be 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -486,7 +486,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path, // This calculates CMH as defined above fn crate_meta_extras_hash(symbol_hasher: &hash::State, - -cmh_items: ~[@ast::meta_item], + +cmh_items: ~[@ast::meta_item], dep_hashes: ~[~str]) -> @str { fn len_and_str(s: &str) -> ~str { fmt!("%u_%s", s.len(), s) @@ -535,7 +535,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path, name, default)); } - fn crate_meta_name(sess: Session, output: &Path, -opt_name: Option<@str>) + fn crate_meta_name(sess: Session, output: &Path, +opt_name: Option<@str>) -> @str { return match opt_name { Some(v) => v, diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 2b61c9480457d..c26b9691dbe61 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -440,7 +440,7 @@ pub fn pretty_print_input(sess: Session, +cfg: ast::crate_cfg, input: input, } } -pub fn get_os(triple: ~str) -> Option { +pub fn get_os(triple: &str) -> Option { if str::contains(triple, ~"win32") || str::contains(triple, ~"mingw32") { Some(session::os_win32) @@ -455,7 +455,7 @@ pub fn get_os(triple: ~str) -> Option { } else { None } } -pub fn get_arch(triple: ~str) -> Option { +pub fn get_arch(triple: &str) -> Option { if str::contains(triple, ~"i386") || str::contains(triple, ~"i486") || str::contains(triple, ~"i586") || diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 890a58243a1cd..fa4acea662a83 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -222,7 +222,7 @@ fn metas_with_ident(ident: @~str, +metas: ~[@ast::meta_item]) metas_with(ident, @~"name", metas) } -fn existing_match(e: @mut Env, metas: ~[@ast::meta_item], hash: @~str) +fn existing_match(e: @mut Env, metas: &[@ast::meta_item], hash: @~str) -> Option { for e.crate_cache.each |c| { if loader::metadata_matches(*c.metas, metas) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 2643012d30ae2..b87418ce7dc8d 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -560,7 +560,7 @@ pub fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, let item_path = item_path(intr, item_doc); vec::from_slice(item_path.init()) }; - match decode_inlined_item(cdata, tcx, path, item_doc) { + match decode_inlined_item(cdata, tcx, copy path, item_doc) { Some(ref ii) => csearch::found((/*bad*/copy *ii)), None => { match item_parent_item(item_doc) { diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index d45cefdbf081f..e9861e1c9ae12 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -176,7 +176,7 @@ fn crate_matches(crate_data: @~[u8], metadata_matches(linkage_metas, metas) } -pub fn metadata_matches(extern_metas: ~[@ast::meta_item], +pub fn metadata_matches(extern_metas: &[@ast::meta_item], local_metas: &[@ast::meta_item]) -> bool { debug!("matching %u metadata requirements against %u items", diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 63b14cc51be1c..04dd9156660d8 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -427,7 +427,6 @@ fn parse_mode(st: @mut PState) -> ast::mode { let m = ast::expl(match next(st) { '+' => ast::by_copy, '=' => ast::by_ref, - '#' => ast::by_val, _ => fail!(~"bad mode") }); return m; diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index b9cb0b1d4b5a3..d07d8917c6512 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -342,7 +342,6 @@ pub fn enc_mode(w: io::Writer, cx: @ctxt, m: mode) { match ty::resolved_mode(cx.tcx, m) { by_copy => w.write_char('+'), by_ref => w.write_char('='), - by_val => w.write_char('#') } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index c1a8f79b9b131..98ac67f986b36 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -105,7 +105,7 @@ pub fn encode_inlined_item(ecx: @e::EncodeContext, pub fn decode_inlined_item(cdata: @cstore::crate_metadata, tcx: ty::ctxt, maps: Maps, - path: ast_map::path, + +path: ast_map::path, par_doc: ebml::Doc) -> Option { let dcx = @DecodeContext { diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 6e998864def57..f55fae12b4584 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -156,7 +156,7 @@ fn req_loans_in_expr(ex: @ast::expr, let arg_cmt = self.bccx.cat_expr(*arg); self.guarantee_valid(arg_cmt, m_imm, scope_r); } - ast::by_val | ast::by_copy => {} + ast::by_copy => {} } } visit::visit_expr(ex, self, vt); @@ -172,7 +172,7 @@ fn req_loans_in_expr(ex: @ast::expr, let arg_cmt = self.bccx.cat_expr(*arg); self.guarantee_valid(arg_cmt, m_imm, scope_r); } - ast::by_val | ast::by_copy => {} + ast::by_copy => {} } } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 47ec756fe0ee5..505bc35024931 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -765,7 +765,7 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) { // deprecated and because its semantics have changed recently: for decl.inputs.eachi |i, arg| { match ty::resolved_mode(cx, arg.mode) { - ast::by_val | ast::by_copy => {} + ast::by_copy => {} ast::by_ref => { cx.sess.span_lint( foreign_mode, fn_id, fn_id, arg.ty.span, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d300698da59d1..8c206f2707114 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -427,7 +427,7 @@ pub impl IrMaps { v.push(id); } Arg(_, _, by_ref) | - Arg(_, _, by_val) | ImplicitRet => { + ImplicitRet => { debug!("--but it is not owned"); } } @@ -1006,7 +1006,7 @@ pub impl Liveness { // inputs passed by & mode should be considered live on exit: for decl.inputs.each |arg| { match ty::resolved_mode(self.tcx, arg.mode) { - by_val | by_ref => { + by_ref => { // By val and by ref do not own, so register a // read at the end. This will prevent us from // moving out of such variables but also prevent diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 5881f95f29869..c25266b453164 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -486,14 +486,6 @@ pub impl mem_categorization_ctxt { let lp = match ty::resolved_mode(self.tcx, mode) { ast::by_copy => Some(@lp_arg(vid)), ast::by_ref => None, - ast::by_val => { - // by-value is this hybrid mode where we have a - // pointer but we do not own it. This is not - // considered loanable because, for example, a by-ref - // and and by-val argument might both actually contain - // the same unique ptr. - None - } }; @cmt_ { id:id, diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 734f4651f3bed..a7562d190a216 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -782,7 +782,7 @@ pub impl VisitContext { */ match arg_mode { - by_val | by_ref => self.use_expr(arg_expr, Read, visitor), + by_ref => self.use_expr(arg_expr, Read, visitor), by_copy => self.consume_expr(arg_expr, visitor) } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 7ac559161af4f..975f699021e28 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2021,7 +2021,7 @@ pub impl Resolver { } fn import_path_to_str(@mut self, - idents: ~[ident], + idents: &[ident], subclass: ImportDirectiveSubclass) -> @~str { if idents.is_empty() { @@ -2573,7 +2573,7 @@ pub impl Resolver { /// Resolves the given module path from the given root `module_`. fn resolve_module_path_from_root(@mut self, module_: @mut Module, - module_path: ~[ident], + module_path: &[ident], index: uint, span: span, mut name_search_type: NameSearchType) @@ -2658,7 +2658,7 @@ pub impl Resolver { /// rooted at the given module. fn resolve_module_path_for_import(@mut self, module_: @mut Module, - module_path: ~[ident], + module_path: &[ident], use_lexical_scope: UseLexicalScopeFlag, span: span) -> ResolveResult<@mut Module> { @@ -2944,7 +2944,7 @@ pub impl Resolver { */ fn resolve_module_prefix(@mut self, module_: @mut Module, - module_path: ~[ident]) + module_path: &[ident]) -> ResolveResult { let interner = self.session.parse_sess.interner; @@ -3876,7 +3876,7 @@ pub impl Resolver { generics: &Generics, opt_trait_reference: Option<@trait_ref>, self_type: @Ty, - methods: ~[@method], + methods: &[@method], visitor: ResolveVisitor) { // If applicable, create a rib for the type parameters. let outer_type_parameter_count = generics.ty_params.len(); diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index d4a7c104500ba..80631abaa555b 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -599,7 +599,7 @@ pub fn enter_rec_or_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint, - fields: ~[ast::ident], + fields: &[ast::ident], val: ValueRef) -> ~[@Match/&r] { debug!("enter_rec_or_struct(bcx=%s, m=%s, col=%u, val=%?)", diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index ac315a36e4034..b2a25fded14ac 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1682,12 +1682,6 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, add_clean(bcx, llarg, arg_ty.ty); } - ast::by_val => { - // always by value, also not owned, so don't add a cleanup: - let alloc = alloc_ty(bcx, arg_ty.ty); - Store(bcx, raw_llarg, alloc); - llarg = alloc; - } } bcx = _match::bind_irrefutable_pat(bcx, @@ -1812,7 +1806,7 @@ pub fn trans_fn(ccx: @CrateContext, debug!("trans_fn(ty_self=%?)", ty_self); let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; - let the_path_str = path_str(ccx.sess, &path); + let the_path_str = path_str(ccx.sess, path); trans_closure(ccx, path, decl, body, llfndecl, ty_self, param_substs, id, impl_id, |fcx| { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 5052ce0767115..15888a64e1e28 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -720,14 +720,6 @@ pub fn trans_arg_expr(bcx: block, val = arg_datum.to_ref_llval(bcx); } - ast::by_val => { - // NB: avoid running the take glue. - - fail_unless!(!bcx.ccx().maps.moves_map.contains_key( - &arg_expr.id)); - val = arg_datum.to_value_llval(bcx); - } - ast::by_copy => { debug!("by copy arg with type %s, storing to scratch", bcx.ty_to_str(arg_datum.ty)); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index c4b80c504dabc..2e5dee49c343f 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -54,7 +54,7 @@ use core::vec::raw::to_ptr; use core::vec; use std::oldmap::{HashMap, Set}; use syntax::ast::ident; -use syntax::ast_map::path; +use syntax::ast_map::{path, path_elt}; use syntax::codemap::span; use syntax::parse::token::ident_interner; use syntax::{ast, ast_map}; @@ -590,7 +590,7 @@ pub struct block_ { fcx: fn_ctxt } -pub fn block_(llbb: BasicBlockRef, parent: Option, -kind: block_kind, +pub fn block_(llbb: BasicBlockRef, parent: Option, +kind: block_kind, is_lpad: bool, node_info: Option, fcx: fn_ctxt) -> block_ { @@ -608,7 +608,7 @@ pub fn block_(llbb: BasicBlockRef, parent: Option, -kind: block_kind, pub type block = @mut block_; -pub fn mk_block(llbb: BasicBlockRef, parent: Option, -kind: block_kind, +pub fn mk_block(llbb: BasicBlockRef, parent: Option, +kind: block_kind, is_lpad: bool, node_info: Option, fcx: fn_ctxt) -> block { @mut block_(llbb, parent, kind, is_lpad, node_info, fcx) @@ -1320,9 +1320,9 @@ pub fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef { return build::And(cx, bumped, build::Not(cx, mask)); } -pub fn path_str(sess: session::Session, p: &path) -> ~str { +pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str { let mut r = ~"", first = true; - for vec::each(*p) |e| { + for p.each |e| { match *e { ast_map::path_name(s) | ast_map::path_mod(s) => { if first { first = false; } diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index e60223c9effb7..3a0968d750adb 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -192,7 +192,7 @@ pub fn trans_log(log_ex: @ast::expr, bcx.fcx.path.filtered(|e| match *e { path_mod(_) => true, _ => false } )); - let modname = path_str(ccx.sess, &modpath); + let modname = path_str(ccx.sess, modpath); let global = if ccx.module_data.contains_key(&modname) { ccx.module_data.get(&modname) diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 2f4e8d715e0a0..b8c5ff4258ced 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -44,7 +44,7 @@ be generated once they are invoked with specific type parameters, see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ pub fn trans_impl(ccx: @CrateContext, +path: path, name: ast::ident, - methods: ~[@ast::method], generics: &ast::Generics, + methods: &[@ast::method], generics: &ast::Generics, self_ty: Option, id: ast::node_id) { let _icx = ccx.insn_ctxt("impl::trans_impl"); if !generics.ty_params.is_empty() { return; } diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 85c0bc80292b6..60af486b3cf1b 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -313,7 +313,6 @@ pub impl Reflector { ast::infer(_) => 0u, ast::expl(e) => match e { ast::by_ref => 1u, - ast::by_val => 2u, ast::by_copy => 5u } }; diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 2a390a03fa142..6855ec5d5726f 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -23,7 +23,6 @@ use syntax::ast; pub fn arg_is_indirect(ccx: @CrateContext, arg: &ty::arg) -> bool { match ty::resolved_mode(ccx.tcx, arg.mode) { - ast::by_val => false, ast::by_copy => !ty::type_is_immediate(arg.ty), ast::by_ref => true } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 9a0c330d2d106..5279c10d9675a 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -81,7 +81,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => { for vec::each(sig.inputs) |arg| { match ty::resolved_mode(ccx.tcx, arg.mode) { - by_val | by_copy => { + by_copy => { type_needs(cx, use_repr, arg.ty); } by_ref => {} @@ -326,7 +326,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) { ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id)) ) |a| { match a.mode { - expl(by_copy) | expl(by_val) => { + expl(by_copy) => { type_needs(cx, use_repr, a.ty); } _ => () @@ -340,7 +340,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) { for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, e.callee_id)).each |a| { match a.mode { - expl(by_copy) | expl(by_val) => { + expl(by_copy) => { type_needs(cx, use_repr, a.ty); } _ => () diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 6e21439fc3563..108d4e94017a8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1110,7 +1110,7 @@ pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { // forward-compatible with non-legacy, we should use + ast::by_copy } else if ty::type_is_immediate(ty) { - ast::by_val + ast::by_copy } else { ast::by_ref } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 445cab4ba95fd..9baea38bd7c50 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3207,7 +3207,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { let (_, visitor_trait) = tcx.intrinsic_defs.get(&ty_visitor_name); let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty, mutbl: ast::m_imm}); - (0u, ~[arg(ast::by_val, td_ptr), + (0u, ~[arg(ast::by_copy, td_ptr), arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx)) } ~"frame_address" => { @@ -3217,7 +3217,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { onceness: ast::Once, region: ty::re_bound(ty::br_anon(0)), sig: ty::FnSig { - inputs: ~[arg {mode: ast::expl(ast::by_val), + inputs: ~[arg {mode: ast::expl(ast::by_copy), ty: ty::mk_imm_ptr( ccx.tcx, ty::mk_mach_uint(ccx.tcx, ast::ty_u8))}], diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index abaf658a1a43e..297e33aa8e365 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -273,26 +273,6 @@ impl get_and_find_region for isr_alist { } } -fn arg_is_argv_ty(tcx: ty::ctxt, a: ty::arg) -> bool { - match ty::resolved_mode(tcx, a.mode) { - ast::by_val => { /*ok*/ } - _ => { - return false; - } - } - - match ty::get(a.ty).sty { - ty::ty_evec(mt, vstore_uniq) => { - if mt.mutbl != ast::m_imm { return false; } - match ty::get(mt.ty).sty { - ty::ty_estr(vstore_uniq) => return true, - _ => return false - } - } - _ => return false - } -} - fn check_main_fn_ty(ccx: @mut CrateCtxt, main_id: ast::node_id, main_span: span) { diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 695b3d01376c3..6b5f806f7df3d 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -49,7 +49,7 @@ use core::vec; pub mod rusti { #[abi = "rust-intrinsic"] pub extern { - fn move_val_init(dst: &mut T, -src: T); + fn move_val_init(dst: &mut T, +src: T); fn needs_drop() -> bool; } } diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index 31f29ce23f2cd..99d19c4839c40 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -19,7 +19,7 @@ use core::vec; #[abi = "rust-intrinsic"] extern "C" mod rusti { - fn move_val_init(dst: &mut T, -src: T); + fn move_val_init(dst: &mut T, +src: T); fn init() -> T; } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b22018c4c76e1..298cb241bed41 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -456,7 +456,7 @@ impl to_bytes::IterBytes for inferable { #[auto_encode] #[auto_decode] #[deriving_eq] -pub enum rmode { by_ref, by_val, by_copy } +pub enum rmode { by_ref, by_copy } impl to_bytes::IterBytes for rmode { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index a7d5c0ce75fa0..a97007cfb3a9b 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -148,7 +148,7 @@ pub fn map_crate(diag: span_handler, c: crate) -> map { // the item itself. pub fn map_decoded_item(diag: span_handler, map: map, - path: path, + +path: path, ii: inlined_item) { // I believe it is ok for the local IDs of inlined items from other crates // to overlap with the local ids from this crate, so just generate the ids @@ -171,10 +171,10 @@ pub fn map_decoded_item(diag: span_handler, ii_item(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic, - @/*bad*/ copy path)); + @path)); } ii_method(impl_did, m) => { - map_method(impl_did, @/*bad*/ copy path, m, cx); + map_method(impl_did, @path, m, cx); } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index fb7143f7c1438..cd7f9a7cf823e 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -72,7 +72,7 @@ pub fn attr_meta(attr: ast::attribute) -> @ast::meta_item { } // Get the meta_items from inside a vector of attributes -pub fn attr_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] { +pub fn attr_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] { do attrs.map |a| { attr_meta(*a) } } @@ -214,7 +214,7 @@ pub fn attrs_contains_name(attrs: &[ast::attribute], name: &str) -> bool { !find_attrs_by_name(attrs, name).is_empty() } -pub fn first_attr_value_str_by_name(attrs: ~[ast::attribute], name: &str) +pub fn first_attr_value_str_by_name(attrs: &[ast::attribute], name: &str) -> Option<@~str> { let mattrs = find_attrs_by_name(attrs, name); @@ -304,7 +304,7 @@ pub fn find_linkage_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] { } } -pub fn foreign_abi(attrs: ~[ast::attribute]) +pub fn foreign_abi(attrs: &[ast::attribute]) -> Either<~str, ast::foreign_abi> { return match attr::first_attr_value_str_by_name(attrs, ~"abi") { None => { diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index ef858a2d5ebd1..2ade0810deae4 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -55,6 +55,7 @@ pub enum ObsoleteSyntax { ObsoletePostFnTySigil, ObsoleteBareFnType, ObsoleteNewtypeEnum, + ObsoleteMode, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -176,6 +177,10 @@ pub impl Parser { "newtype enum", "instead of `enum Foo = int`, write `struct Foo(int)`" ), + ObsoleteMode => ( + "obsolete argument mode", + "replace `-` or `++` mode with `+`" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0c38b2f5ab53f..77ba27cf423b7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -17,7 +17,7 @@ use ast::{RegionTyParamBound, TraitTyParamBound}; use ast::{provided, public, pure_fn, purity}; use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer}; use ast::{bind_by_copy, bitand, bitor, bitxor, blk}; -use ast::{blk_check_mode, box, by_copy, by_ref, by_val}; +use ast::{blk_check_mode, box, by_copy, by_ref}; use ast::{crate, crate_cfg, decl, decl_item}; use ast::{decl_local, default_blk, deref, div, enum_def, enum_variant_kind}; use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again}; @@ -78,6 +78,7 @@ use parse::obsolete::{ObsoleteMutVector, ObsoleteTraitImplVisibility}; use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern}; use parse::obsolete::{ObsoleteAssertion, ObsoletePostFnTySigil}; use parse::obsolete::{ObsoleteBareFnType, ObsoleteNewtypeEnum}; +use parse::obsolete::{ObsoleteMode}; use parse::prec::{as_prec, token_to_binop}; use parse::token::{can_begin_expr, is_ident, is_ident_or_path}; use parse::token::{is_plain_ident, INTERPOLATED, special_idents}; @@ -716,12 +717,15 @@ pub impl Parser { fn parse_arg_mode(&self) -> mode { if self.eat(&token::BINOP(token::MINUS)) { - expl(by_copy) // NDM outdated syntax + self.obsolete(*self.span, ObsoleteMode); + expl(by_copy) } else if self.eat(&token::ANDAND) { expl(by_ref) } else if self.eat(&token::BINOP(token::PLUS)) { if self.eat(&token::BINOP(token::PLUS)) { - expl(by_val) + // ++ mode is obsolete, but we need a snapshot + // to stop parsing it. + expl(by_copy) } else { expl(by_copy) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9288312378206..846560636463f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1710,7 +1710,6 @@ pub fn mode_to_str(m: ast::mode) -> ~str { match m { ast::expl(ast::by_ref) => ~"&&", ast::expl(ast::by_copy) => ~"+", - ast::expl(ast::by_val) => ~"++", ast::infer(_) => ~"" } } diff --git a/src/test/auxiliary/cci_class_6.rs b/src/test/auxiliary/cci_class_6.rs index ceccea409c44a..80990099cdab5 100644 --- a/src/test/auxiliary/cci_class_6.rs +++ b/src/test/auxiliary/cci_class_6.rs @@ -23,7 +23,7 @@ pub mod kitties { fn meow_count(&mut self) -> uint { self.meows } } - pub fn cat(in_x : uint, in_y : int, -in_info: ~[U]) -> cat { + pub fn cat(in_x : uint, in_y : int, +in_info: ~[U]) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 133dd606b0e71..8da09af2d18b6 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -100,7 +100,7 @@ fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph { } } -fn gen_search_keys(graph: graph, n: uint) -> ~[node_id] { +fn gen_search_keys(graph: &[~[node_id]], n: uint) -> ~[node_id] { let keys = oldmap::HashMap::(); let r = rand::Rng(); diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs index 9bdc5aae3f283..17b7d1d29482d 100644 --- a/src/test/bench/task-perf-jargon-metal-smoke.rs +++ b/src/test/bench/task-perf-jargon-metal-smoke.rs @@ -19,7 +19,7 @@ use core::cell::Cell; -fn child_generation(gens_left: uint, -c: comm::Chan<()>) { +fn child_generation(gens_left: uint, c: comm::Chan<()>) { // This used to be O(n^2) in the number of generations that ever existed. // With this code, only as many generations are alive at a time as tasks // alive at a time, diff --git a/src/test/compile-fail/liveness-move-from-args.rs b/src/test/compile-fail/liveness-move-from-args.rs index d6c0be9f1833c..c60848e5cc6c5 100644 --- a/src/test/compile-fail/liveness-move-from-args.rs +++ b/src/test/compile-fail/liveness-move-from-args.rs @@ -10,10 +10,6 @@ fn take(_x: ~int) { } -fn from_by_value_arg(++x: ~int) { - take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode -} - fn from_by_ref_arg(&&x: ~int) { take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index ab24b63af100a..fdc0392a74c7c 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn send(ch: _chan, -data: T) { +fn send(ch: _chan, +data: T) { debug!(ch); debug!(data); fail!(); diff --git a/src/test/compile-fail/mutable-arguments.rs b/src/test/compile-fail/mutable-arguments.rs index aefe8c02ecd2f..39e47fb1aabdb 100644 --- a/src/test/compile-fail/mutable-arguments.rs +++ b/src/test/compile-fail/mutable-arguments.rs @@ -19,18 +19,13 @@ fn mutate_by_ref(&&x: uint) { x = 0; //~ ERROR assigning to argument } -fn mutate_by_val(++x: uint) { - //~^ WARNING unused variable: `x` - x = 0; //~ ERROR assigning to argument -} - fn mutate_by_copy(+x: uint) { //~^ WARNING unused variable: `x` x = 0; //~ ERROR assigning to argument //~^ WARNING value assigned to `x` is never read } -fn mutate_by_move(-x: uint) { +fn mutate_by_move(+x: uint) { //~^ WARNING unused variable: `x` x = 0; //~ ERROR assigning to argument //~^ WARNING value assigned to `x` is never read diff --git a/src/test/run-fail/unwind-move.rs b/src/test/run-fail/unwind-move.rs index b2d30688ec55d..51e2eaa44fa37 100644 --- a/src/test/run-fail/unwind-move.rs +++ b/src/test/run-fail/unwind-move.rs @@ -9,7 +9,7 @@ // except according to those terms. // error-pattern:fail -fn f(-_a: @int) { +fn f(+_a: @int) { fail!(); } diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs index 186fdb2849443..11f988bc2961b 100644 --- a/src/test/run-pass/argument-passing.rs +++ b/src/test/run-pass/argument-passing.rs @@ -12,7 +12,7 @@ struct X { x: int } -fn f1(a: &mut X, b: &mut int, -c: int) -> int { +fn f1(a: &mut X, b: &mut int, +c: int) -> int { let r = a.x + *b + c; a.x = 0; *b = 10; diff --git a/src/test/run-pass/borrowck-lend-args.rs b/src/test/run-pass/borrowck-lend-args.rs index 44be8f2724a2a..0d51993e226ef 100644 --- a/src/test/run-pass/borrowck-lend-args.rs +++ b/src/test/run-pass/borrowck-lend-args.rs @@ -18,17 +18,9 @@ fn borrow_from_arg_mut_ref(v: &mut ~int) { borrow(*v); } -fn borrow_from_arg_move(-v: ~int) { - borrow(v); -} - fn borrow_from_arg_copy(+v: ~int) { borrow(v); } -fn borrow_from_arg_val(++v: ~int) { - borrow(v); -} - pub fn main() { } diff --git a/src/test/run-pass/class-poly-methods.rs b/src/test/run-pass/class-poly-methods.rs index 88fe2be2bdb6c..95db23f6c5afe 100644 --- a/src/test/run-pass/class-poly-methods.rs +++ b/src/test/run-pass/class-poly-methods.rs @@ -22,7 +22,7 @@ pub impl cat { fn meow_count(&mut self) -> uint { self.meows } } -fn cat(in_x : uint, in_y : int, -in_info: ~[U]) -> cat { +fn cat(in_x : uint, in_y : int, +in_info: ~[U]) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index 7e0a8173f7e6e..7544c89197bab 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -11,8 +11,8 @@ mod rusti { #[abi = "rust-intrinsic"] pub extern { - pub fn move_val_init(dst: &mut T, -src: T); - pub fn move_val(dst: &mut T, -src: T); + pub fn move_val_init(dst: &mut T, +src: T); + pub fn move_val(dst: &mut T, +src: T); } } diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index acd30de9e8786..ae927ff791810 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -70,7 +70,7 @@ pub mod pipes { } } - pub fn send(mut p: send_packet, -payload: T) { + pub fn send(mut p: send_packet, +payload: T) { let mut p = p.unwrap(); let mut p = unsafe { uniquify(p) }; fail_unless!((*p).payload.is_none()); @@ -228,7 +228,7 @@ pub mod pingpong { pub struct ping(::pipes::send_packet); pub struct pong(::pipes::send_packet); - pub fn liberate_ping(-p: ping) -> ::pipes::send_packet { + pub fn liberate_ping(+p: ping) -> ::pipes::send_packet { unsafe { let addr : *::pipes::send_packet = match &p { &ping(ref x) => { cast::transmute(ptr::addr_of(x)) } @@ -239,7 +239,7 @@ pub mod pingpong { } } - pub fn liberate_pong(-p: pong) -> ::pipes::send_packet { + pub fn liberate_pong(+p: pong) -> ::pipes::send_packet { unsafe { let addr : *::pipes::send_packet = match &p { &pong(ref x) => { cast::transmute(ptr::addr_of(x)) } @@ -261,14 +261,14 @@ pub mod pingpong { pub type ping = ::pipes::send_packet; pub type pong = ::pipes::recv_packet; - pub fn do_ping(-c: ping) -> pong { + pub fn do_ping(+c: ping) -> pong { let (sp, rp) = ::pipes::entangle(); ::pipes::send(c, pingpong::ping(sp)); rp } - pub fn do_pong(-c: pong) -> (ping, ()) { + pub fn do_pong(+c: pong) -> (ping, ()) { let packet = ::pipes::recv(c); if packet.is_none() { fail!(~"sender closed the connection") @@ -283,7 +283,7 @@ pub mod pingpong { pub type ping = ::pipes::recv_packet; pub type pong = ::pipes::send_packet; - pub fn do_ping(-c: ping) -> (pong, ()) { + pub fn do_ping(+c: ping) -> (pong, ()) { let packet = ::pipes::recv(c); if packet.is_none() { fail!(~"sender closed the connection") @@ -291,7 +291,7 @@ pub mod pingpong { (pingpong::liberate_ping(option::unwrap(packet)), ()) } - pub fn do_pong(-c: pong) -> ping { + pub fn do_pong(+c: pong) -> ping { let (sp, rp) = ::pipes::entangle(); ::pipes::send(c, pingpong::pong(sp)); rp @@ -299,14 +299,14 @@ pub mod pingpong { } } -fn client(-chan: pingpong::client::ping) { +fn client(+chan: pingpong::client::ping) { let chan = pingpong::client::do_ping(chan); error!(~"Sent ping"); let (_chan, _data) = pingpong::client::do_pong(chan); error!(~"Received pong"); } -fn server(-chan: pingpong::server::ping) { +fn server(+chan: pingpong::server::ping) { let (chan, _data) = pingpong::server::do_ping(chan); error!(~"Received ping"); let _chan = pingpong::server::do_pong(chan); diff --git a/src/test/run-pass/liveness-move-in-loop.rs b/src/test/run-pass/liveness-move-in-loop.rs index 8c4b7d57bc201..658885124c2ef 100644 --- a/src/test/run-pass/liveness-move-in-loop.rs +++ b/src/test/run-pass/liveness-move-in-loop.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn take(-x: int) -> int {x} +fn take(+x: int) -> int {x} fn the_loop() { let mut list = ~[]; diff --git a/src/test/run-pass/move-arg-2-unique.rs b/src/test/run-pass/move-arg-2-unique.rs index 4275513d61e02..c0adcc8c03cc4 100644 --- a/src/test/run-pass/move-arg-2-unique.rs +++ b/src/test/run-pass/move-arg-2-unique.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn test(-foo: ~~[int]) { fail_unless!((foo[0] == 10)); } +fn test(+foo: ~~[int]) { fail_unless!((foo[0] == 10)); } pub fn main() { let x = ~~[10]; diff --git a/src/test/run-pass/move-arg-2.rs b/src/test/run-pass/move-arg-2.rs index 24444f5ebdbea..41a82977175e7 100644 --- a/src/test/run-pass/move-arg-2.rs +++ b/src/test/run-pass/move-arg-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn test(-foo: @~[int]) { fail_unless!((foo[0] == 10)); } +fn test(+foo: @~[int]) { fail_unless!((foo[0] == 10)); } pub fn main() { let x = @~[10]; diff --git a/src/test/run-pass/move-arg.rs b/src/test/run-pass/move-arg.rs index 288abb6fb3950..b763317dfe186 100644 --- a/src/test/run-pass/move-arg.rs +++ b/src/test/run-pass/move-arg.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn test(-foo: int) { fail_unless!((foo == 10)); } +fn test(+foo: int) { fail_unless!((foo == 10)); } pub fn main() { let x = 10; test(x); } diff --git a/src/test/run-pass/move-nullary-fn.rs b/src/test/run-pass/move-nullary-fn.rs index 48f4a75ed4e4c..eb4c5f871af48 100644 --- a/src/test/run-pass/move-nullary-fn.rs +++ b/src/test/run-pass/move-nullary-fn.rs @@ -9,9 +9,9 @@ // except according to those terms. // Issue #922 -fn f2(-thing: @fn()) { } +fn f2(+thing: @fn()) { } -fn f(-thing: @fn()) { +fn f(+thing: @fn()) { f2(thing); } diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs index 20daa894bc128..d6b8acd94de37 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -53,7 +53,7 @@ fn switch(+endp: pipes::RecvPacket, f(pipes::try_recv(endp)) } -fn move_it(-x: T) -> T { x } +fn move_it(+x: T) -> T { x } macro_rules! follow ( { diff --git a/src/test/run-pass/pipe-pingpong-bounded.rs b/src/test/run-pass/pipe-pingpong-bounded.rs index 266f657de96e4..7dea787e1a1ce 100644 --- a/src/test/run-pass/pipe-pingpong-bounded.rs +++ b/src/test/run-pass/pipe-pingpong-bounded.rs @@ -91,7 +91,7 @@ mod test { use core::pipes::recv; use pingpong::{ping, pong}; - pub fn client(-chan: ::pingpong::client::ping) { + pub fn client(+chan: ::pingpong::client::ping) { use pingpong::client; let chan = client::ping(chan); return; @@ -100,7 +100,7 @@ mod test { error!("Received pong"); } - pub fn server(-chan: ::pingpong::server::ping) { + pub fn server(+chan: ::pingpong::server::ping) { use pingpong::server; let ping(chan) = recv(chan); return; diff --git a/src/test/run-pass/pipe-pingpong-proto.rs b/src/test/run-pass/pipe-pingpong-proto.rs index 98af23738b7d7..65a5672941f28 100644 --- a/src/test/run-pass/pipe-pingpong-proto.rs +++ b/src/test/run-pass/pipe-pingpong-proto.rs @@ -29,7 +29,7 @@ mod test { use core::pipes::recv; use pingpong::{ping, pong}; - pub fn client(-chan: ::pingpong::client::ping) { + pub fn client(+chan: ::pingpong::client::ping) { use pingpong::client; let chan = client::ping(chan); @@ -38,7 +38,7 @@ mod test { error!(~"Received pong"); } - pub fn server(-chan: ::pingpong::server::ping) { + pub fn server(+chan: ::pingpong::server::ping) { use pingpong::server; let ping(chan) = recv(chan); diff --git a/src/test/run-pass/unique-fn-arg-move.rs b/src/test/run-pass/unique-fn-arg-move.rs index 850af69b34752..5a318d04e55c1 100644 --- a/src/test/run-pass/unique-fn-arg-move.rs +++ b/src/test/run-pass/unique-fn-arg-move.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(-i: ~int) { +fn f(+i: ~int) { fail_unless!(*i == 100); }