Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: rust-lang/rust
base: master
...
head fork: eholk/rust
Checking mergeability… Don’t worry, you can still create the pull request.
  • 2 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
View
82 src/rustc/middle/trans/base.rs
@@ -50,7 +50,6 @@ import type_of::type_of; // Issue #1873
import syntax::ast_map::{path, path_mod, path_name};
import std::smallintmap;
-import option::is_none;
// Destinations
@@ -1212,8 +1211,7 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
}
}
-// See [Note-arg-mode]
-fn call_tydesc_glue_full(++cx: block, v: ValueRef, tydesc: ValueRef,
+fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
field: uint, static_ti: option<@tydesc_info>) {
let _icx = cx.insn_ctxt("call_tydesc_glue_full");
lazily_emit_tydesc_glue(cx.ccx(), field, static_ti);
@@ -1251,9 +1249,8 @@ fn call_tydesc_glue_full(++cx: block, v: ValueRef, tydesc: ValueRef,
C_null(T_ptr(T_ptr(cx.ccx().tydesc_type))), llrawptr]);
}
-// See [Note-arg-mode]
-fn call_tydesc_glue(++cx: block, v: ValueRef, t: ty::t, field: uint)
- -> block {
+fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint) ->
+ block {
let _icx = cx.insn_ctxt("call_tydesc_glue");
let mut ti = none;
let td = get_tydesc(cx.ccx(), t, ti);
@@ -1439,6 +1436,7 @@ fn copy_val_no_check(bcx: block, action: copy_action, dst: ValueRef,
// doesn't need to be dropped. (Issue #839)
fn move_val(cx: block, action: copy_action, dst: ValueRef,
src: lval_result, t: ty::t) -> block {
+ assert !cx.terminated;
let _icx = cx.insn_ctxt("move_val");
let mut src_val = src.val;
let tcx = cx.tcx();
@@ -1721,7 +1719,11 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
some(origin) {
let callee_id = ast_util::op_expr_callee_id(ex);
let fty = node_id_type(bcx, callee_id);
- ret trans_call_inner(
+
+ let dty = expr_ty(bcx, dst);
+ let target = alloc_ty(bcx, dty);
+
+ let bcx = trans_call_inner(
bcx, ex.info(), fty,
expr_ty(bcx, ex),
{|bcx|
@@ -1729,7 +1731,12 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
// #2528
impl::trans_method_callee(bcx, callee_id, dst, origin)
},
- arg_exprs([src]), save_in(lhs_res.val));
+ arg_exprs([src]), save_in(target));
+
+ ret move_val(bcx, DROP_EXISTING, lhs_res.val,
+ // FIXME: should kind be owned?
+ {bcx: bcx, val: target, kind: owned},
+ dty);
}
_ {}
}
@@ -3127,9 +3134,8 @@ fn body_contains_ret(body: ast::blk) -> bool {
cx.found
}
-// See [Note-arg-mode]
fn trans_call_inner(
- ++in_cx: block,
+ in_cx: block,
call_info: option<node_info>,
fn_expr_ty: ty::t,
ret_ty: ty::t,
@@ -3257,8 +3263,8 @@ fn need_invoke(bcx: block) -> bool {
_ { }
}
cur = alt cur.parent {
- some(next) { next }
- none { ret false; }
+ parent_some(next) { next }
+ parent_none { ret false; }
}
}
}
@@ -3279,7 +3285,7 @@ fn in_lpad_scope_cx(bcx: block, f: fn(scope_info)) {
loop {
alt bcx.kind {
block_scope(inf) {
- if inf.cleanups.len() > 0u || is_none(bcx.parent) {
+ if inf.cleanups.len() > 0u || bcx.parent == parent_none {
f(inf); ret;
}
}
@@ -3488,11 +3494,11 @@ fn add_root_cleanup(bcx: block, scope_id: ast::node_id,
some({id, _}) if id == scope_id { ret bcx_sid; }
_ {
alt bcx_sid.parent {
- none {
+ parent_none {
bcx.tcx().sess.bug(
#fmt["no enclosing scope with id %d", scope_id]);
}
- some(bcx_par) { bcx_par }
+ parent_some(bcx_par) { bcx_par }
}
}
}
@@ -3802,10 +3808,7 @@ fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
// Since this function does *not* root, it is the caller's responsibility to
// ensure that the referent is pointed to by a root.
-// [Note-arg-mode]
-// ++ mode is temporary, due to how borrowck treats enums. With hope,
-// will go away anyway when we get rid of modes.
-fn do_spill_noroot(++cx: block, v: ValueRef) -> ValueRef {
+fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
let llptr = alloca(cx, val_ty(v));
Store(cx, v, llptr);
ret llptr;
@@ -3987,9 +3990,9 @@ fn trans_break_cont(bcx: block, to_end: bool)
_ {}
}
unwind = alt unwind.parent {
- some(cx) { cx }
+ parent_some(cx) { cx }
// This is a return from a loop body block
- none {
+ parent_none {
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr);
cleanup_and_leave(bcx, none, some(bcx.fcx.llreturn));
Unreachable(bcx);
@@ -4107,7 +4110,7 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block {
// You probably don't want to use this one. See the
// next three functions instead.
-fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
+fn new_block(cx: fn_ctxt, parent: block_parent, +kind: block_kind,
name: str, opt_node_info: option<node_info>) -> block {
let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
@@ -4116,10 +4119,19 @@ fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
let llbb: BasicBlockRef = str::as_c_str(s, {|buf|
llvm::LLVMAppendBasicBlock(cx.llfn, buf)
});
- let bcx = mk_block(llbb, parent, kind, opt_node_info, cx);
- option::iter(parent) {|cx|
+ let bcx = @{llbb: llbb,
+ mut terminated: false,
+ mut unreachable: false,
+ parent: parent,
+ kind: kind,
+ node_info: opt_node_info,
+ fcx: cx};
+ alt parent {
+ parent_some(cx) {
if cx.unreachable { Unreachable(bcx); }
- };
+ }
+ _ {}
+ }
ret bcx;
}
@@ -4130,20 +4142,20 @@ fn simple_block_scope() -> block_kind {
// Use this when you're at the top block of a function or the like.
fn top_scope_block(fcx: fn_ctxt, opt_node_info: option<node_info>) -> block {
- ret new_block(fcx, none, simple_block_scope(),
+ ret new_block(fcx, parent_none, simple_block_scope(),
"function top level", opt_node_info);
}
fn scope_block(bcx: block,
opt_node_info: option<node_info>,
n: str) -> block {
- ret new_block(bcx.fcx, some(bcx), simple_block_scope(),
+ ret new_block(bcx.fcx, parent_some(bcx), simple_block_scope(),
n, opt_node_info);
}
fn loop_scope_block(bcx: block, loop_break: block, n: str,
opt_node_info: option<node_info>) -> block {
- ret new_block(bcx.fcx, some(bcx), block_scope({
+ ret new_block(bcx.fcx, parent_some(bcx), block_scope({
loop_break: some(loop_break),
mut cleanups: [],
mut cleanup_paths: [],
@@ -4154,11 +4166,17 @@ fn loop_scope_block(bcx: block, loop_break: block, n: str,
// Use this when you're making a general CFG BB within a scope.
fn sub_block(bcx: block, n: str) -> block {
- new_block(bcx.fcx, some(bcx), block_non_scope, n, none)
+ ret new_block(bcx.fcx, parent_some(bcx), block_non_scope, n, none);
}
fn raw_block(fcx: fn_ctxt, llbb: BasicBlockRef) -> block {
- mk_block(llbb, none, block_non_scope, none, fcx)
+ ret @{llbb: llbb,
+ mut terminated: false,
+ mut unreachable: false,
+ parent: parent_none,
+ kind: block_non_scope,
+ node_info: none,
+ fcx: fcx};
}
@@ -4233,8 +4251,8 @@ fn cleanup_and_leave(bcx: block, upto: option<BasicBlockRef>,
_ {}
}
cur = alt cur.parent {
- some(next) { next }
- none { assert is_none(upto); break; }
+ parent_some(next) { next }
+ parent_none { assert option::is_none(upto); break; }
};
}
alt leave {
View
44 src/rustc/middle/trans/common.rs
@@ -350,44 +350,32 @@ type node_info = {
// code. Each basic block we generate is attached to a function, typically
// with many basic blocks per function. All the basic blocks attached to a
// function are organized as a directed graph.
-class block_ {
+type block = @{
// The BasicBlockRef returned from a call to
// llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
// block to the function pointed to by llfn. We insert
// instructions into that block by way of this block context.
// The block pointing to this one in the function's digraph.
- let llbb: BasicBlockRef;
- let mut terminated: bool;
- let mut unreachable: bool;
- let parent: option<block>;
+ llbb: BasicBlockRef,
+ mut terminated: bool,
+ mut unreachable: bool,
+ parent: block_parent,
// The 'kind' of basic block this is.
- let kind: block_kind;
+ kind: block_kind,
// info about the AST node this block originated from, if any
- let node_info: option<node_info>;
+ node_info: option<node_info>,
// The function context for the function to which this block is
// attached.
- let fcx: fn_ctxt;
- new(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
- node_info: option<node_info>, fcx: fn_ctxt) {
- // sigh
- self.llbb = llbb; self.terminated = false; self.unreachable = false;
- self.parent = parent; self.kind = kind; self.node_info = node_info;
- self.fcx = fcx;
- }
-}
-
-/* This must be enum and not type, or trans goes into an infinite loop (#2572)
- */
-enum block = @block_;
-
-fn mk_block(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
- node_info: option<node_info>, fcx: fn_ctxt) -> block {
- block(@block_(llbb, parent, kind, node_info, fcx))
-}
+ fcx: fn_ctxt
+};
// First two args are retptr, env
const first_real_arg: uint = 2u;
+// FIXME move blocks to a class once those are finished, and simply use
+// option<block> for this. (#2532)
+enum block_parent { parent_none, parent_some(block), }
+
type result = {bcx: block, val: ValueRef};
type result_t = {bcx: block, val: ValueRef, ty: ty::t};
@@ -424,11 +412,7 @@ fn in_scope_cx(cx: block, f: fn(scope_info)) {
}
fn block_parent(cx: block) -> block {
- alt cx.parent {
- some(b) { b }
- none { cx.sess().bug(#fmt("block_parent called on root block %?",
- cx)); }
- }
+ alt check cx.parent { parent_some(b) { b } }
}
// Accessors
View
17 src/rustc/middle/trans/debuginfo.rs
@@ -236,8 +236,8 @@ fn create_block(cx: block) -> @metadata<block_md> {
let mut cx = cx;
while option::is_none(cx.node_info) {
alt cx.parent {
- some(b) { cx = b; }
- none { fail; }
+ parent_some(b) { cx = b; }
+ parent_none { fail; }
}
}
let sp = option::get(cx.node_info).span;
@@ -254,8 +254,8 @@ fn create_block(cx: block) -> @metadata<block_md> {
}*/
let parent = alt cx.parent {
- none { create_function(cx.fcx).node }
- some(bcx) { create_block(bcx).node }
+ parent_none { create_function(cx.fcx).node }
+ parent_some(bcx) { create_block(bcx).node }
};
let file_node = create_file(cx.ccx(), fname);
let unique_id = alt cache.find(LexicalBlockTag) {
@@ -658,8 +658,8 @@ fn create_local_var(bcx: block, local: @ast::local)
let tymd = create_ty(cx, ty, local.node.ty);
let filemd = create_file(cx, loc.file.name);
let context = alt bcx.parent {
- none { create_function(bcx.fcx).node }
- some(_) { create_block(bcx).node }
+ parent_none { create_function(bcx.fcx).node }
+ parent_some(_) { create_block(bcx).node }
};
let mdnode = create_var(tg, context, name, filemd.node,
loc.line as int, tymd.node);
@@ -761,10 +761,9 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
(nm, decl.output, ctor_id)
}
ast_map::class_ctor(ctor,_) {
- // FIXME: output type may be wrong (#2194)
- (nm, ctor.node.dec.output, ctor.node.id)
+ fcx.ccx.sess.span_bug(ctor.span, "create_function: \
+ expected a resource ctor here"); }
}
- }
}
ast_map::node_expr(expr) {
alt expr.node {
View
74 src/test/run-pass/operator-overloading-leaks.rs
@@ -0,0 +1,74 @@
+// The cases commented as "Leaks" need to not leak. Issue #2581
+
+impl methods<T: copy> for [T] {
+ fn -(x: [T]/&) -> [T] {
+ [x[0], x[0], x[0]]
+ }
+
+ fn foo(x: [T]/&) -> [T] {
+ [x[0], x[0], x[0]]
+ }
+}
+
+impl methods<T: copy> for ~T {
+ fn +(rhs: ~T) -> ~T {
+ rhs
+ }
+}
+
+impl methods for ~int {
+ fn -(rhs: ~int) -> ~int {
+ ~(*self - *rhs)
+ }
+}
+
+impl methods for @int {
+ fn +(rhs: @int) -> @int {
+ @(*self + *rhs)
+ }
+}
+
+fn main() {
+ // leaks
+ let mut bar = [1, 2, 3];
+ bar -= [3, 2, 1];
+ bar -= [4, 5, 6];
+
+ io::println(#fmt("%?", bar));
+
+ // okay
+ let mut bar = [1, 2, 3];
+ bar = bar.foo([3, 2, 1]);
+ bar = bar.foo([4, 5, 6]);
+
+ io::println(#fmt("%?", bar));
+
+ // okay
+ let mut bar = [1, 2, 3];
+ bar = bar - [3, 2, 1];
+ bar = bar - [4, 5, 6];
+
+ io::println(#fmt("%?", bar));
+
+ // Leaks
+ let mut bar = ~1;
+ bar += ~2;
+ bar += ~3;
+
+ io:: println(#fmt("%?", bar));
+
+ // Leaks
+ let mut bar = ~1;
+ bar -= ~2;
+ bar -= ~3;
+
+ io:: println(#fmt("%?", bar));
+
+ // Leaks
+ let mut bar = @1;
+ bar += @2;
+ bar += @3;
+
+ io:: println(#fmt("%?", bar));
+
+}

No commit comments for this range

Something went wrong with that request. Please try again.