Skip to content

Commit ea3ab73

Browse files
committed
Track kind of closure in upvar categorization
Keep track of the kind of closure responsible for an upvar
1 parent 20f4c45 commit ea3ab73

File tree

6 files changed

+61
-33
lines changed

6 files changed

+61
-33
lines changed

src/librustc/middle/borrowck/gather_loans/gather_moves.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,15 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
133133
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
134134
mc::cat_deref(_, _, mc::Implicit(..)) |
135135
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
136-
mc::cat_upvar(..) | mc::cat_static_item |
137-
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
136+
mc::cat_upvar(..) | mc::cat_static_item => {
138137
Some(cmt.clone())
139138
}
140139

141-
// Can move out of captured upvars only if the destination closure
142-
// type is 'once'. 1-shot stack closures emit the copied_upvar form
143-
// (see mem_categorization.rs).
144-
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, .. }) => {
145-
None
140+
mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. }) => {
141+
match kind.onceness() {
142+
ast::Once => None,
143+
ast::Many => Some(cmt.clone())
144+
}
146145
}
147146

148147
mc::cat_rvalue(..) |

src/librustc/middle/borrowck/gather_loans/move_error.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,15 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
115115
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
116116
mc::cat_deref(_, _, mc::Implicit(..)) |
117117
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
118-
mc::cat_upvar(..) | mc::cat_static_item |
119-
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
118+
mc::cat_upvar(..) | mc::cat_static_item => {
119+
bccx.span_err(
120+
move_from.span,
121+
format!("cannot move out of {}",
122+
bccx.cmt_to_string(&*move_from)).as_slice());
123+
}
124+
125+
mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. })
126+
if kind.onceness() == ast::Many => {
120127
bccx.span_err(
121128
move_from.span,
122129
format!("cannot move out of {}",

src/librustc/middle/borrowck/gather_loans/restrictions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
7272
SafeIf(lp.clone(), vec![lp])
7373
}
7474

75-
mc::cat_upvar(upvar_id, _) => {
75+
mc::cat_upvar(upvar_id, _, _) => {
7676
// R-Variable, captured into closure
7777
let lp = Rc::new(LpUpvar(upvar_id));
7878
SafeIf(lp.clone(), vec![lp])

src/librustc/middle/borrowck/mod.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -354,18 +354,22 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
354354
355355
match cmt.cat {
356356
mc::cat_rvalue(..) |
357-
mc::cat_static_item |
358-
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
357+
mc::cat_static_item => {
358+
None
359+
}
360+
361+
mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. })
362+
if kind.onceness() == ast::Many => {
359363
None
360364
}
361365

362366
mc::cat_local(id) => {
363367
Some(Rc::new(LpVar(id)))
364368
}
365369

366-
mc::cat_upvar(ty::UpvarId {var_id: id, closure_expr_id: proc_id}, _) |
370+
mc::cat_upvar(ty::UpvarId {var_id: id, closure_expr_id: proc_id}, _, _) |
367371
mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id,
368-
onceness: _,
372+
kind: _,
369373
capturing_proc: proc_id }) => {
370374
let upvar_id = ty::UpvarId{ var_id: id, closure_expr_id: proc_id };
371375
Some(Rc::new(LpUpvar(upvar_id)))

src/librustc/middle/mem_categorization.rs

+34-16
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub enum categorization {
8383
cat_rvalue(ty::Region), // temporary val, argument is its scope
8484
cat_static_item,
8585
cat_copied_upvar(CopiedUpvar), // upvar copied into proc env
86-
cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure
86+
cat_upvar(ty::UpvarId, ty::UpvarBorrow, Option<ty::UnboxedClosureKind>), // by ref upvar from stack or unboxed closure
8787
cat_local(ast::NodeId), // local variable
8888
cat_deref(cmt, uint, PointerKind), // deref of a ptr
8989
cat_interior(cmt, InteriorKind), // something interior: field, tuple, etc
@@ -93,10 +93,27 @@ pub enum categorization {
9393
// (*1) downcast is only required if the enum has more than one variant
9494
}
9595

96+
#[deriving(Clone, PartialEq)]
97+
pub enum CopiedUpvarKind {
98+
Boxed(ast::Onceness),
99+
Unboxed(ty::UnboxedClosureKind)
100+
}
101+
102+
impl CopiedUpvarKind {
103+
pub fn onceness(&self) -> ast::Onceness {
104+
match *self {
105+
Boxed(onceness) => onceness,
106+
Unboxed(ty::FnUnboxedClosureKind) |
107+
Unboxed(ty::FnMutUnboxedClosureKind) => ast::Many,
108+
Unboxed(ty::FnOnceUnboxedClosureKind) => ast::Once
109+
}
110+
}
111+
}
112+
96113
#[deriving(Clone, PartialEq)]
97114
pub struct CopiedUpvar {
98115
pub upvar_id: ast::NodeId,
99-
pub onceness: ast::Onceness,
116+
pub kind: CopiedUpvarKind,
100117
pub capturing_proc: ast::NodeId,
101118
}
102119

@@ -571,14 +588,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
571588

572589
};
573590
if var_is_refd {
574-
self.cat_upvar(id, span, var_id, fn_node_id)
591+
self.cat_upvar(id, span, var_id, fn_node_id, None)
575592
} else {
576593
Ok(Rc::new(cmt_ {
577594
id:id,
578595
span:span,
579596
cat:cat_copied_upvar(CopiedUpvar {
580597
upvar_id: var_id,
581-
onceness: closure_ty.onceness,
598+
kind: Boxed(closure_ty.onceness),
582599
capturing_proc: fn_node_id,
583600
}),
584601
mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
@@ -591,20 +608,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
591608
.unboxed_closures()
592609
.borrow();
593610
let kind = unboxed_closures.get(&closure_id).kind;
594-
let onceness = match kind {
595-
ty::FnUnboxedClosureKind |
596-
ty::FnMutUnboxedClosureKind => ast::Many,
597-
ty::FnOnceUnboxedClosureKind => ast::Once,
598-
};
599611
if self.typer.capture_mode(fn_node_id) == ast::CaptureByRef {
600-
self.cat_upvar(id, span, var_id, fn_node_id)
612+
self.cat_upvar(id, span, var_id, fn_node_id, Some(kind))
601613
} else {
602614
Ok(Rc::new(cmt_ {
603615
id: id,
604616
span: span,
605617
cat: cat_copied_upvar(CopiedUpvar {
606618
upvar_id: var_id,
607-
onceness: onceness,
619+
kind: Unboxed(kind),
608620
capturing_proc: fn_node_id,
609621
}),
610622
mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
@@ -638,7 +650,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
638650
id: ast::NodeId,
639651
span: Span,
640652
var_id: ast::NodeId,
641-
fn_node_id: ast::NodeId)
653+
fn_node_id: ast::NodeId,
654+
kind: Option<ty::UnboxedClosureKind>)
642655
-> McResult<cmt> {
643656
/*!
644657
* Upvars through a closure are in fact indirect
@@ -666,7 +679,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
666679
let base_cmt = Rc::new(cmt_ {
667680
id:id,
668681
span:span,
669-
cat:cat_upvar(upvar_id, upvar_borrow),
682+
cat:cat_upvar(upvar_id, upvar_borrow, kind),
670683
mutbl:McImmutable,
671684
ty:upvar_ty,
672685
});
@@ -1287,16 +1300,21 @@ impl cmt_ {
12871300
b.freely_aliasable(ctxt)
12881301
}
12891302

1290-
cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
12911303
cat_rvalue(..) |
12921304
cat_local(..) |
12931305
cat_upvar(..) |
12941306
cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
12951307
None
12961308
}
12971309

1298-
cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
1299-
Some(AliasableOther)
1310+
cat_copied_upvar(CopiedUpvar {kind: kind, capturing_proc: id, ..}) => {
1311+
match kind {
1312+
Boxed(ast::Once) |
1313+
Unboxed(ty::FnOnceUnboxedClosureKind) |
1314+
Unboxed(ty::FnMutUnboxedClosureKind) => None,
1315+
Boxed(_) => Some(AliasableOther),
1316+
Unboxed(_) => Some(AliasableClosure(id))
1317+
}
13001318
}
13011319

13021320
cat_static_item(..) => {

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -1552,7 +1552,7 @@ fn link_reborrowed_region(rcx: &Rcx,
15521552

15531553
// Detect references to an upvar `x`:
15541554
let cause = match ref_cmt.cat {
1555-
mc::cat_upvar(ref upvar_id, _) => {
1555+
mc::cat_upvar(ref upvar_id, _, _) => {
15561556
let mut upvar_borrow_map =
15571557
rcx.fcx.inh.upvar_borrow_map.borrow_mut();
15581558
match upvar_borrow_map.find_mut(upvar_id) {
@@ -1686,7 +1686,7 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
16861686
mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
16871687
mc::cat_deref(base, _, mc::Implicit(..)) => {
16881688
match base.cat {
1689-
mc::cat_upvar(ref upvar_id, _) => {
1689+
mc::cat_upvar(ref upvar_id, _, _) => {
16901690
// if this is an implicit deref of an
16911691
// upvar, then we need to modify the
16921692
// borrow_kind of the upvar to make sure it
@@ -1739,7 +1739,7 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
17391739
mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
17401740
mc::cat_deref(base, _, mc::Implicit(..)) => {
17411741
match base.cat {
1742-
mc::cat_upvar(ref upvar_id, _) => {
1742+
mc::cat_upvar(ref upvar_id, _, _) => {
17431743
// if this is an implicit deref of an
17441744
// upvar, then we need to modify the
17451745
// borrow_kind of the upvar to make sure it

0 commit comments

Comments
 (0)