Skip to content

Commit d35eb6e

Browse files
committed
auto merge of #6302 : nikomatsakis/rust/issue-6141-leaking-owned-fn, r=brson
When autoborrowing a fn in trans, adjust the type of the datum to be `&fn`. Fixes #6141. r? @brson
2 parents 847552f + 11f7cb2 commit d35eb6e

File tree

6 files changed

+71
-54
lines changed

6 files changed

+71
-54
lines changed

src/librustc/middle/trans/datum.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,9 @@ pub impl Datum {
548548
}
549549

550550
fn to_rptr(&self, bcx: block) -> Datum {
551-
//!
552-
//
553-
// Returns a new datum of region-pointer type containing the
554-
// the same ptr as this datum (after converting to by-ref
555-
// using `to_ref_llval()`).
551+
//! Returns a new datum of region-pointer type containing the
552+
//! the same ptr as this datum (after converting to by-ref
553+
//! using `to_ref_llval()`).
556554
557555
// Convert to ref, yielding lltype *T. Then create a Rust
558556
// type &'static T (which translates to *T). Construct new

src/librustc/middle/trans/expr.rs

+34-31
Original file line numberDiff line numberDiff line change
@@ -183,30 +183,25 @@ fn drop_and_cancel_clean(bcx: block, dat: Datum) -> block {
183183

184184
pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
185185
debug!("trans_to_datum(expr=%s)", bcx.expr_to_str(expr));
186-
return match bcx.tcx().adjustments.find(&expr.id) {
187-
None => {
188-
trans_to_datum_unadjusted(bcx, expr)
189-
}
190-
Some(&@AutoAddEnv(*)) => {
191-
let mut bcx = bcx;
192-
let datum = unpack_datum!(bcx, {
193-
trans_to_datum_unadjusted(bcx, expr)
194-
});
195-
add_env(bcx, expr, datum)
196-
}
197-
Some(&@AutoDerefRef(ref adj)) => {
198-
let mut bcx = bcx;
199-
let mut datum = unpack_datum!(bcx, {
200-
trans_to_datum_unadjusted(bcx, expr)
201-
});
202-
203-
debug!("unadjusted datum: %s", datum.to_str(bcx.ccx()));
204186

187+
let mut bcx = bcx;
188+
let mut datum = unpack_datum!(bcx, trans_to_datum_unadjusted(bcx, expr));
189+
let adjustment = match bcx.tcx().adjustments.find_copy(&expr.id) {
190+
None => { return DatumBlock {bcx: bcx, datum: datum}; }
191+
Some(adj) => { adj }
192+
};
193+
debug!("unadjusted datum: %s", datum.to_str(bcx.ccx()));
194+
match *adjustment {
195+
AutoAddEnv(*) => {
196+
datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
197+
}
198+
AutoDerefRef(ref adj) => {
205199
if adj.autoderefs > 0 {
206-
let DatumBlock { bcx: new_bcx, datum: new_datum } =
207-
datum.autoderef(bcx, expr.span, expr.id, adj.autoderefs);
208-
datum = new_datum;
209-
bcx = new_bcx;
200+
datum =
201+
unpack_datum!(
202+
bcx,
203+
datum.autoderef(bcx, expr.span,
204+
expr.id, adj.autoderefs));
210205
}
211206

212207
datum = match adj.autoref {
@@ -224,23 +219,31 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
224219
unpack_datum!(bcx, auto_slice_and_ref(bcx, expr, datum))
225220
}
226221
Some(AutoBorrowFn(*)) => {
227-
// currently, all closure types are
228-
// represented precisely the same, so no
229-
// runtime adjustment is required:
230-
datum
222+
let adjusted_ty = ty::adjust_ty(bcx.tcx(), expr.span,
223+
datum.ty, Some(adjustment));
224+
unpack_datum!(bcx, auto_borrow_fn(bcx, adjusted_ty, datum))
231225
}
232226
};
233-
234-
debug!("after adjustments, datum=%s", datum.to_str(bcx.ccx()));
235-
236-
return DatumBlock {bcx: bcx, datum: datum};
237227
}
238-
};
228+
}
229+
debug!("after adjustments, datum=%s", datum.to_str(bcx.ccx()));
230+
return DatumBlock {bcx: bcx, datum: datum};
239231

240232
fn auto_ref(bcx: block, datum: Datum) -> DatumBlock {
241233
DatumBlock {bcx: bcx, datum: datum.to_rptr(bcx)}
242234
}
243235

236+
fn auto_borrow_fn(bcx: block,
237+
adjusted_ty: ty::t,
238+
datum: Datum) -> DatumBlock {
239+
// Currently, all closure types are represented precisely the
240+
// same, so no runtime adjustment is required, but we still
241+
// must patchup the type.
242+
DatumBlock {bcx: bcx,
243+
datum: Datum {val: datum.val, ty: adjusted_ty,
244+
mode: datum.mode, source: datum.source}}
245+
}
246+
244247
fn auto_slice(bcx: block, expr: @ast::expr, datum: Datum) -> DatumBlock {
245248
// This is not the most efficient thing possible; since slices
246249
// are two words it'd be better if this were compiled in

src/librustc/middle/ty.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2893,20 +2893,20 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
28932893
*/
28942894

28952895
let unadjusted_ty = expr_ty(cx, expr);
2896-
adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find(&expr.id))
2896+
adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find_copy(&expr.id))
28972897
}
28982898

28992899
pub fn adjust_ty(cx: ctxt,
29002900
span: span,
29012901
unadjusted_ty: ty::t,
2902-
adjustment: Option<&@AutoAdjustment>) -> ty::t
2902+
adjustment: Option<@AutoAdjustment>) -> ty::t
29032903
{
29042904
/*! See `expr_ty_adjusted` */
29052905

29062906
return match adjustment {
29072907
None => unadjusted_ty,
29082908

2909-
Some(&@AutoAddEnv(r, s)) => {
2909+
Some(@AutoAddEnv(r, s)) => {
29102910
match ty::get(unadjusted_ty).sty {
29112911
ty::ty_bare_fn(ref b) => {
29122912
ty::mk_closure(
@@ -2924,7 +2924,7 @@ pub fn adjust_ty(cx: ctxt,
29242924
}
29252925
}
29262926

2927-
Some(&@AutoDerefRef(ref adj)) => {
2927+
Some(@AutoDerefRef(ref adj)) => {
29282928
let mut adjusted_ty = unadjusted_ty;
29292929

29302930
for uint::range(0, adj.autoderefs) |i| {

src/librustc/middle/typeck/check/regionck.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,37 @@ pub impl Rcx {
118118
}
119119

120120
/// Try to resolve the type for the given node.
121+
#[config(stage0)]
121122
fn resolve_expr_type_adjusted(@mut self, expr: @ast::expr) -> ty::t {
122123
let ty_unadjusted = self.resolve_node_type(expr.id);
123124
if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
124125
ty_unadjusted
125126
} else {
126127
let tcx = self.fcx.tcx();
127128
let adjustments = self.fcx.inh.adjustments;
128-
match adjustments.find(&expr.id) {
129+
match adjustments.find_copy(&expr.id) {
129130
None => ty_unadjusted,
130-
Some(&adjustment) => {
131-
// FIXME(#3850) --- avoid region scoping errors
132-
ty::adjust_ty(tcx, expr.span, ty_unadjusted, Some(&adjustment))
131+
Some(adjustment) => {
132+
ty::adjust_ty(tcx, expr.span, ty_unadjusted,
133+
Some(adjustment))
133134
}
134135
}
135136
}
136137
}
138+
139+
/// Try to resolve the type for the given node.
140+
#[config(not(stage0))]
141+
fn resolve_expr_type_adjusted(@mut self, expr: @ast::expr) -> ty::t {
142+
let ty_unadjusted = self.resolve_node_type(expr.id);
143+
if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
144+
ty_unadjusted
145+
} else {
146+
let tcx = self.fcx.tcx();
147+
let adjustments = self.fcx.inh.adjustments;
148+
ty::adjust_ty(tcx, expr.span, ty_unadjusted,
149+
adjustments.find_copy(&expr.id))
150+
}
151+
}
137152
}
138153

139154
pub fn regionck_expr(fcx: @mut FnCtxt, e: @ast::expr) {
@@ -650,7 +665,7 @@ fn constrain_regions_in_type_of_node(
650665
// is going to fail anyway, so just stop here and let typeck
651666
// report errors later on in the writeback phase.
652667
let ty0 = rcx.resolve_node_type(id);
653-
let adjustment = rcx.fcx.inh.adjustments.find(&id);
668+
let adjustment = rcx.fcx.inh.adjustments.find_copy(&id);
654669
let ty = ty::adjust_ty(tcx, span, ty0, adjustment);
655670
debug!("constrain_regions_in_type_of_node(\
656671
ty=%s, ty0=%s, id=%d, minimum_lifetime=%?, adjustment=%?)",

src/rt/rust_task.cpp

+2-9
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,8 @@ rust_task::delete_this()
7676
assert(ref_count == 0); // ||
7777
// (ref_count == 1 && this == sched->root_task));
7878

79-
if (borrow_list) {
80-
// NOTE should free borrow_list from within rust code!
81-
// If there is a pointer in there, it is a ~[BorrowRecord] pointer,
82-
// which are currently allocated with LIBC malloc/free. But this is
83-
// not really the right way to do this, we should be freeing this
84-
// pointer from Rust code.
85-
free(borrow_list);
86-
borrow_list = NULL;
87-
}
79+
// The borrow list should be freed in the task annihilator
80+
assert(!borrow_list);
8881

8982
sched_loop->release_task(this);
9083
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn run(f: &fn()) {
2+
f()
3+
}
4+
5+
fn main() {
6+
let f: ~fn() = || ();
7+
run(f);
8+
}

0 commit comments

Comments
 (0)