Skip to content

Commit 8d27232

Browse files
committed
librustc: Tie up loose ends in unboxed closures.
This patch primarily does two things: (1) it prevents lifetimes from leaking out of unboxed closures; (2) it allows unboxed closure type notation, call notation, and construction notation to construct closures matching any of the three traits. This breaks code that looked like: let mut f; { let x = &5i; f = |&mut:| *x + 10; } Change this code to avoid having a reference escape. For example: { let x = &5i; let mut f; // <-- move here to avoid dangling reference f = |&mut:| *x + 10; } I believe this is enough to consider unboxed closures essentially implemented. Further issues (for example, higher-rank lifetimes) should be filed as followups. Closes #14449. [breaking-change]
1 parent 9d45d63 commit 8d27232

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+835
-298
lines changed

src/librustc/front/feature_gate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl<'a> Visitor<()> for Context<'a> {
314314

315315
},
316316
ast::TyBox(_) => { self.gate_box(t.span); }
317-
ast::TyUnboxedFn(_) => {
317+
ast::TyUnboxedFn(..) => {
318318
self.gate_feature("unboxed_closure_sugar",
319319
t.span,
320320
"unboxed closure trait sugar is experimental");

src/librustc/metadata/common.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
139139
tag_table_adjustments = 0x51,
140140
tag_table_moves_map = 0x52,
141141
tag_table_capture_map = 0x53,
142-
tag_table_unboxed_closure_type = 0x54,
142+
tag_table_unboxed_closures = 0x54,
143143
tag_table_upvar_borrow_map = 0x55,
144144
tag_table_capture_modes = 0x56,
145145
}
@@ -229,9 +229,11 @@ pub static tag_region_param_def_index: uint = 0x94;
229229
pub static tag_unboxed_closures: uint = 0x95;
230230
pub static tag_unboxed_closure: uint = 0x96;
231231
pub static tag_unboxed_closure_type: uint = 0x97;
232+
pub static tag_unboxed_closure_kind: uint = 0x98;
232233

233-
pub static tag_struct_fields: uint = 0x98;
234-
pub static tag_struct_field: uint = 0x99;
235-
pub static tag_struct_field_id: uint = 0x9a;
234+
pub static tag_struct_fields: uint = 0x99;
235+
pub static tag_struct_field: uint = 0x9a;
236+
pub static tag_struct_field_id: uint = 0x9b;
237+
238+
pub static tag_attribute_is_sugared_doc: uint = 0x9c;
236239

237-
pub static tag_attribute_is_sugared_doc: uint = 0x9b;

src/librustc/metadata/encoder.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,18 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: Visibility) {
630630
rbml_w.end_tag();
631631
}
632632

633+
fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
634+
kind: ty::UnboxedClosureKind) {
635+
rbml_w.start_tag(tag_unboxed_closure_kind);
636+
let ch = match kind {
637+
ty::FnUnboxedClosureKind => 'f',
638+
ty::FnMutUnboxedClosureKind => 'm',
639+
ty::FnOnceUnboxedClosureKind => 'o',
640+
};
641+
rbml_w.wr_str(ch.to_string().as_slice());
642+
rbml_w.end_tag();
643+
}
644+
633645
fn encode_explicit_self(rbml_w: &mut Encoder,
634646
explicit_self: &ty::ExplicitSelfCategory) {
635647
rbml_w.start_tag(tag_item_trait_method_explicit_self);
@@ -1629,17 +1641,20 @@ fn encode_unboxed_closures<'a>(
16291641
ecx: &'a EncodeContext,
16301642
rbml_w: &'a mut Encoder) {
16311643
rbml_w.start_tag(tag_unboxed_closures);
1632-
for (unboxed_closure_id, unboxed_closure_type) in
1633-
ecx.tcx.unboxed_closure_types.borrow().iter() {
1644+
for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1645+
.unboxed_closures
1646+
.borrow()
1647+
.iter() {
16341648
if unboxed_closure_id.krate != LOCAL_CRATE {
16351649
continue
16361650
}
16371651

16381652
rbml_w.start_tag(tag_unboxed_closure);
16391653
encode_def_id(rbml_w, *unboxed_closure_id);
16401654
rbml_w.start_tag(tag_unboxed_closure_type);
1641-
write_closure_type(ecx, rbml_w, unboxed_closure_type);
1655+
write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
16421656
rbml_w.end_tag();
1657+
encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
16431658
rbml_w.end_tag();
16441659
}
16451660
rbml_w.end_tag();

src/librustc/metadata/tydecode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
432432
}
433433
'k' => {
434434
let did = parse_def(st, NominalType, |x,y| conv(x,y));
435-
return ty::mk_unboxed_closure(st.tcx, did);
435+
let region = parse_region(st, conv);
436+
return ty::mk_unboxed_closure(st.tcx, did, region);
436437
}
437438
'e' => {
438439
return ty::mk_err();

src/librustc/metadata/tyencode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,9 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
285285
enc_substs(w, cx, substs);
286286
mywrite!(w, "]");
287287
}
288-
ty::ty_unboxed_closure(def) => {
288+
ty::ty_unboxed_closure(def, region) => {
289289
mywrite!(w, "k{}", (cx.ds)(def));
290+
enc_region(w, cx, region);
290291
}
291292
ty::ty_err => {
292293
mywrite!(w, "e");

src/librustc/middle/astencode.rs

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -689,10 +689,35 @@ pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
689689
}).unwrap()
690690
}
691691

692+
pub fn encode_unboxed_closure_kind(ebml_w: &mut Encoder,
693+
kind: ty::UnboxedClosureKind) {
694+
ebml_w.emit_enum("UnboxedClosureKind", |ebml_w| {
695+
match kind {
696+
ty::FnUnboxedClosureKind => {
697+
ebml_w.emit_enum_variant("FnUnboxedClosureKind", 0, 3, |_| {
698+
Ok(())
699+
})
700+
}
701+
ty::FnMutUnboxedClosureKind => {
702+
ebml_w.emit_enum_variant("FnMutUnboxedClosureKind", 1, 3, |_| {
703+
Ok(())
704+
})
705+
}
706+
ty::FnOnceUnboxedClosureKind => {
707+
ebml_w.emit_enum_variant("FnOnceUnboxedClosureKind",
708+
2,
709+
3,
710+
|_| {
711+
Ok(())
712+
})
713+
}
714+
}
715+
}).unwrap()
716+
}
692717

693718
pub fn encode_vtable_origin(ecx: &e::EncodeContext,
694-
rbml_w: &mut Encoder,
695-
vtable_origin: &typeck::vtable_origin) {
719+
rbml_w: &mut Encoder,
720+
vtable_origin: &typeck::vtable_origin) {
696721
rbml_w.emit_enum("vtable_origin", |rbml_w| {
697722
match *vtable_origin {
698723
typeck::vtable_static(def_id, ref substs, ref vtable_res) => {
@@ -1210,14 +1235,15 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
12101235
})
12111236
}
12121237

1213-
for unboxed_closure_type in tcx.unboxed_closure_types
1214-
.borrow()
1215-
.find(&ast_util::local_def(id))
1216-
.iter() {
1217-
rbml_w.tag(c::tag_table_unboxed_closure_type, |rbml_w| {
1238+
for unboxed_closure in tcx.unboxed_closures
1239+
.borrow()
1240+
.find(&ast_util::local_def(id))
1241+
.iter() {
1242+
rbml_w.tag(c::tag_table_unboxed_closures, |rbml_w| {
12181243
rbml_w.id(id);
12191244
rbml_w.tag(c::tag_table_val, |rbml_w| {
1220-
rbml_w.emit_closure_type(ecx, *unboxed_closure_type)
1245+
rbml_w.emit_closure_type(ecx, &unboxed_closure.closure_type);
1246+
encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind)
12211247
})
12221248
})
12231249
}
@@ -1244,8 +1270,8 @@ trait rbml_decoder_decoder_helpers {
12441270
-> ty::Polytype;
12451271
fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> subst::Substs;
12461272
fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
1247-
fn read_unboxed_closure_type(&mut self, xcx: &ExtendedDecodeContext)
1248-
-> ty::ClosureTy;
1273+
fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
1274+
-> ty::UnboxedClosure;
12491275
fn convert_def_id(&mut self,
12501276
xcx: &ExtendedDecodeContext,
12511277
source: DefIdSource,
@@ -1418,16 +1444,33 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
14181444
}).unwrap()
14191445
}
14201446

1421-
fn read_unboxed_closure_type(&mut self, xcx: &ExtendedDecodeContext)
1422-
-> ty::ClosureTy {
1423-
self.read_opaque(|this, doc| {
1447+
fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
1448+
-> ty::UnboxedClosure {
1449+
let closure_type = self.read_opaque(|this, doc| {
14241450
Ok(tydecode::parse_ty_closure_data(
14251451
doc.data,
14261452
xcx.dcx.cdata.cnum,
14271453
doc.start,
14281454
xcx.dcx.tcx,
14291455
|s, a| this.convert_def_id(xcx, s, a)))
1430-
}).unwrap()
1456+
}).unwrap();
1457+
let variants = [
1458+
"FnUnboxedClosureKind",
1459+
"FnMutUnboxedClosureKind",
1460+
"FnOnceUnboxedClosureKind"
1461+
];
1462+
let kind = self.read_enum_variant(variants, |_, i| {
1463+
Ok(match i {
1464+
0 => ty::FnUnboxedClosureKind,
1465+
1 => ty::FnMutUnboxedClosureKind,
1466+
2 => ty::FnOnceUnboxedClosureKind,
1467+
_ => fail!("bad enum variant for ty::UnboxedClosureKind"),
1468+
})
1469+
}).unwrap();
1470+
ty::UnboxedClosure {
1471+
closure_type: closure_type,
1472+
kind: kind,
1473+
}
14311474
}
14321475

14331476
fn convert_def_id(&mut self,
@@ -1566,14 +1609,14 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
15661609
let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(xcx);
15671610
dcx.tcx.adjustments.borrow_mut().insert(id, adj);
15681611
}
1569-
c::tag_table_unboxed_closure_type => {
1570-
let unboxed_closure_type =
1571-
val_dsr.read_unboxed_closure_type(xcx);
1612+
c::tag_table_unboxed_closures => {
1613+
let unboxed_closure =
1614+
val_dsr.read_unboxed_closure(xcx);
15721615
dcx.tcx
1573-
.unboxed_closure_types
1616+
.unboxed_closures
15741617
.borrow_mut()
15751618
.insert(ast_util::local_def(id),
1576-
unboxed_closure_type);
1619+
unboxed_closure);
15771620
}
15781621
_ => {
15791622
xcx.dcx.tcx.sess.bug(

src/librustc/middle/borrowck/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,9 @@ pub fn closure_to_block(closure_id: ast::NodeId,
290290
tcx: &ty::ctxt) -> ast::NodeId {
291291
match tcx.map.get(closure_id) {
292292
ast_map::NodeExpr(expr) => match expr.node {
293-
ast::ExprProc(_decl, block) |
294-
ast::ExprFnBlock(_, _decl, block) => { block.id }
293+
ast::ExprProc(_, block) |
294+
ast::ExprFnBlock(_, _, block) |
295+
ast::ExprUnboxedFn(_, _, _, block) => { block.id }
295296
_ => fail!("encountered non-closure id: {}", closure_id)
296297
},
297298
_ => fail!("encountered non-expr id: {}", closure_id)

src/librustc/middle/check_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'a> Visitor<Context> for CheckLoopVisitor<'a> {
4848
}
4949
ast::ExprFnBlock(_, _, ref b) |
5050
ast::ExprProc(_, ref b) |
51-
ast::ExprUnboxedFn(_, _, ref b) => {
51+
ast::ExprUnboxedFn(_, _, _, ref b) => {
5252
self.visit_block(&**b, Closure);
5353
}
5454
ast::ExprBreak(_) => self.require_loop("break", cx, e.span),

src/librustc/middle/freevars.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
7474
self.capture_mode_map.insert(expr.id, capture_mode);
7575
visit::walk_expr(self, expr, depth + 1)
7676
}
77-
ast::ExprUnboxedFn(capture_clause, _, _) => {
77+
ast::ExprUnboxedFn(capture_clause, _, _, _) => {
7878
let capture_mode = match capture_clause {
7979
ast::CaptureByValue => CaptureByValue,
8080
ast::CaptureByRef => CaptureByRef,

src/librustc/middle/kind.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ fn with_appropriate_checker(cx: &Context,
225225
b(check_for_bare)
226226
}
227227

228-
ty::ty_unboxed_closure(_) => {}
228+
ty::ty_unboxed_closure(..) => {}
229229

230230
ref s => {
231231
cx.tcx.sess.bug(format!("expect fn type in kind checker, not \

src/librustc/middle/liveness.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ impl<'a> Liveness<'a> {
967967

968968
ExprFnBlock(_, _, ref blk) |
969969
ExprProc(_, ref blk) |
970-
ExprUnboxedFn(_, _, ref blk) => {
970+
ExprUnboxedFn(_, _, _, ref blk) => {
971971
debug!("{} is an ExprFnBlock, ExprProc, or ExprUnboxedFn",
972972
expr_to_string(expr));
973973

src/librustc/middle/mem_categorization.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use middle::def;
6666
use middle::freevars;
6767
use middle::ty;
6868
use middle::typeck;
69-
use util::nodemap::NodeMap;
69+
use util::nodemap::{DefIdMap, NodeMap};
7070
use util::ppaux::{ty_to_string, Repr};
7171

7272
use syntax::ast::{MutImmutable, MutMutable};
@@ -273,6 +273,8 @@ pub trait Typer {
273273
fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
274274
fn capture_mode(&self, closure_expr_id: ast::NodeId)
275275
-> freevars::CaptureMode;
276+
fn unboxed_closures<'a>(&'a self)
277+
-> &'a RefCell<DefIdMap<ty::UnboxedClosure>>;
276278
}
277279

278280
impl MutabilityCategory {
@@ -598,13 +600,22 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
598600
}))
599601
}
600602
}
601-
ty::ty_unboxed_closure(_) => {
603+
ty::ty_unboxed_closure(closure_id, _) => {
604+
let unboxed_closures = self.typer
605+
.unboxed_closures()
606+
.borrow();
607+
let kind = unboxed_closures.get(&closure_id).kind;
608+
let onceness = match kind {
609+
ty::FnUnboxedClosureKind |
610+
ty::FnMutUnboxedClosureKind => ast::Many,
611+
ty::FnOnceUnboxedClosureKind => ast::Once,
612+
};
602613
Ok(Rc::new(cmt_ {
603614
id: id,
604615
span: span,
605616
cat: cat_copied_upvar(CopiedUpvar {
606617
upvar_id: var_id,
607-
onceness: ast::Many,
618+
onceness: onceness,
608619
capturing_proc: fn_node_id,
609620
}),
610621
mutbl: MutabilityCategory::from_def(&def),

src/librustc/middle/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5289,7 +5289,7 @@ impl<'a> Resolver<'a> {
52895289

52905290
ExprFnBlock(_, fn_decl, block) |
52915291
ExprProc(fn_decl, block) |
5292-
ExprUnboxedFn(_, fn_decl, block) => {
5292+
ExprUnboxedFn(_, _, fn_decl, block) => {
52935293
self.resolve_function(FunctionRibKind(expr.id, block.id),
52945294
Some(fn_decl), NoTypeParameters,
52955295
block);

src/librustc/middle/trans/adt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
170170

171171
return Univariant(mk_struct(cx, ftys.as_slice(), packed), dtor)
172172
}
173-
ty::ty_unboxed_closure(def_id) => {
173+
ty::ty_unboxed_closure(def_id, _) => {
174174
let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
175175
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
176176
return Univariant(mk_struct(cx, upvar_types.as_slice(), false),

0 commit comments

Comments
 (0)