Track kind of closure in upvar categorization
Keep track of the kind of closure responsible for an upvar
This commit is contained in:
parent
20f4c45bad
commit
ea3ab731a3
@ -133,16 +133,15 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
|
||||
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
|
||||
mc::cat_deref(_, _, mc::Implicit(..)) |
|
||||
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
|
||||
mc::cat_upvar(..) | mc::cat_static_item |
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
|
||||
mc::cat_upvar(..) | mc::cat_static_item => {
|
||||
Some(cmt.clone())
|
||||
}
|
||||
|
||||
// Can move out of captured upvars only if the destination closure
|
||||
// type is 'once'. 1-shot stack closures emit the copied_upvar form
|
||||
// (see mem_categorization.rs).
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, .. }) => {
|
||||
None
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. }) => {
|
||||
match kind.onceness() {
|
||||
ast::Once => None,
|
||||
ast::Many => Some(cmt.clone())
|
||||
}
|
||||
}
|
||||
|
||||
mc::cat_rvalue(..) |
|
||||
|
@ -115,8 +115,15 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
|
||||
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
|
||||
mc::cat_deref(_, _, mc::Implicit(..)) |
|
||||
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
|
||||
mc::cat_upvar(..) | mc::cat_static_item |
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
|
||||
mc::cat_upvar(..) | mc::cat_static_item => {
|
||||
bccx.span_err(
|
||||
move_from.span,
|
||||
format!("cannot move out of {}",
|
||||
bccx.cmt_to_string(&*move_from)).as_slice());
|
||||
}
|
||||
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. })
|
||||
if kind.onceness() == ast::Many => {
|
||||
bccx.span_err(
|
||||
move_from.span,
|
||||
format!("cannot move out of {}",
|
||||
|
@ -72,7 +72,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
|
||||
SafeIf(lp.clone(), vec![lp])
|
||||
}
|
||||
|
||||
mc::cat_upvar(upvar_id, _) => {
|
||||
mc::cat_upvar(upvar_id, _, _) => {
|
||||
// R-Variable, captured into closure
|
||||
let lp = Rc::new(LpUpvar(upvar_id));
|
||||
SafeIf(lp.clone(), vec![lp])
|
||||
|
@ -354,8 +354,12 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
|
||||
|
||||
match cmt.cat {
|
||||
mc::cat_rvalue(..) |
|
||||
mc::cat_static_item |
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
|
||||
mc::cat_static_item => {
|
||||
None
|
||||
}
|
||||
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. })
|
||||
if kind.onceness() == ast::Many => {
|
||||
None
|
||||
}
|
||||
|
||||
@ -363,9 +367,9 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
|
||||
Some(Rc::new(LpVar(id)))
|
||||
}
|
||||
|
||||
mc::cat_upvar(ty::UpvarId {var_id: id, closure_expr_id: proc_id}, _) |
|
||||
mc::cat_upvar(ty::UpvarId {var_id: id, closure_expr_id: proc_id}, _, _) |
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id,
|
||||
onceness: _,
|
||||
kind: _,
|
||||
capturing_proc: proc_id }) => {
|
||||
let upvar_id = ty::UpvarId{ var_id: id, closure_expr_id: proc_id };
|
||||
Some(Rc::new(LpUpvar(upvar_id)))
|
||||
|
@ -83,7 +83,7 @@ pub enum categorization {
|
||||
cat_rvalue(ty::Region), // temporary val, argument is its scope
|
||||
cat_static_item,
|
||||
cat_copied_upvar(CopiedUpvar), // upvar copied into proc env
|
||||
cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure
|
||||
cat_upvar(ty::UpvarId, ty::UpvarBorrow, Option<ty::UnboxedClosureKind>), // by ref upvar from stack or unboxed closure
|
||||
cat_local(ast::NodeId), // local variable
|
||||
cat_deref(cmt, uint, PointerKind), // deref of a ptr
|
||||
cat_interior(cmt, InteriorKind), // something interior: field, tuple, etc
|
||||
@ -93,10 +93,27 @@ pub enum categorization {
|
||||
// (*1) downcast is only required if the enum has more than one variant
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub enum CopiedUpvarKind {
|
||||
Boxed(ast::Onceness),
|
||||
Unboxed(ty::UnboxedClosureKind)
|
||||
}
|
||||
|
||||
impl CopiedUpvarKind {
|
||||
pub fn onceness(&self) -> ast::Onceness {
|
||||
match *self {
|
||||
Boxed(onceness) => onceness,
|
||||
Unboxed(ty::FnUnboxedClosureKind) |
|
||||
Unboxed(ty::FnMutUnboxedClosureKind) => ast::Many,
|
||||
Unboxed(ty::FnOnceUnboxedClosureKind) => ast::Once
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub struct CopiedUpvar {
|
||||
pub upvar_id: ast::NodeId,
|
||||
pub onceness: ast::Onceness,
|
||||
pub kind: CopiedUpvarKind,
|
||||
pub capturing_proc: ast::NodeId,
|
||||
}
|
||||
|
||||
@ -571,14 +588,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
|
||||
};
|
||||
if var_is_refd {
|
||||
self.cat_upvar(id, span, var_id, fn_node_id)
|
||||
self.cat_upvar(id, span, var_id, fn_node_id, None)
|
||||
} else {
|
||||
Ok(Rc::new(cmt_ {
|
||||
id:id,
|
||||
span:span,
|
||||
cat:cat_copied_upvar(CopiedUpvar {
|
||||
upvar_id: var_id,
|
||||
onceness: closure_ty.onceness,
|
||||
kind: Boxed(closure_ty.onceness),
|
||||
capturing_proc: fn_node_id,
|
||||
}),
|
||||
mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
|
||||
@ -591,20 +608,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
.unboxed_closures()
|
||||
.borrow();
|
||||
let kind = unboxed_closures.get(&closure_id).kind;
|
||||
let onceness = match kind {
|
||||
ty::FnUnboxedClosureKind |
|
||||
ty::FnMutUnboxedClosureKind => ast::Many,
|
||||
ty::FnOnceUnboxedClosureKind => ast::Once,
|
||||
};
|
||||
if self.typer.capture_mode(fn_node_id) == ast::CaptureByRef {
|
||||
self.cat_upvar(id, span, var_id, fn_node_id)
|
||||
self.cat_upvar(id, span, var_id, fn_node_id, Some(kind))
|
||||
} else {
|
||||
Ok(Rc::new(cmt_ {
|
||||
id: id,
|
||||
span: span,
|
||||
cat: cat_copied_upvar(CopiedUpvar {
|
||||
upvar_id: var_id,
|
||||
onceness: onceness,
|
||||
kind: Unboxed(kind),
|
||||
capturing_proc: fn_node_id,
|
||||
}),
|
||||
mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
|
||||
@ -638,7 +650,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
id: ast::NodeId,
|
||||
span: Span,
|
||||
var_id: ast::NodeId,
|
||||
fn_node_id: ast::NodeId)
|
||||
fn_node_id: ast::NodeId,
|
||||
kind: Option<ty::UnboxedClosureKind>)
|
||||
-> McResult<cmt> {
|
||||
/*!
|
||||
* Upvars through a closure are in fact indirect
|
||||
@ -666,7 +679,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
let base_cmt = Rc::new(cmt_ {
|
||||
id:id,
|
||||
span:span,
|
||||
cat:cat_upvar(upvar_id, upvar_borrow),
|
||||
cat:cat_upvar(upvar_id, upvar_borrow, kind),
|
||||
mutbl:McImmutable,
|
||||
ty:upvar_ty,
|
||||
});
|
||||
@ -1287,7 +1300,6 @@ impl cmt_ {
|
||||
b.freely_aliasable(ctxt)
|
||||
}
|
||||
|
||||
cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
|
||||
cat_rvalue(..) |
|
||||
cat_local(..) |
|
||||
cat_upvar(..) |
|
||||
@ -1295,8 +1307,14 @@ impl cmt_ {
|
||||
None
|
||||
}
|
||||
|
||||
cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
|
||||
Some(AliasableOther)
|
||||
cat_copied_upvar(CopiedUpvar {kind: kind, capturing_proc: id, ..}) => {
|
||||
match kind {
|
||||
Boxed(ast::Once) |
|
||||
Unboxed(ty::FnOnceUnboxedClosureKind) |
|
||||
Unboxed(ty::FnMutUnboxedClosureKind) => None,
|
||||
Boxed(_) => Some(AliasableOther),
|
||||
Unboxed(_) => Some(AliasableClosure(id))
|
||||
}
|
||||
}
|
||||
|
||||
cat_static_item(..) => {
|
||||
|
@ -1552,7 +1552,7 @@ fn link_reborrowed_region(rcx: &Rcx,
|
||||
|
||||
// Detect references to an upvar `x`:
|
||||
let cause = match ref_cmt.cat {
|
||||
mc::cat_upvar(ref upvar_id, _) => {
|
||||
mc::cat_upvar(ref upvar_id, _, _) => {
|
||||
let mut upvar_borrow_map =
|
||||
rcx.fcx.inh.upvar_borrow_map.borrow_mut();
|
||||
match upvar_borrow_map.find_mut(upvar_id) {
|
||||
@ -1686,7 +1686,7 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
|
||||
mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
|
||||
mc::cat_deref(base, _, mc::Implicit(..)) => {
|
||||
match base.cat {
|
||||
mc::cat_upvar(ref upvar_id, _) => {
|
||||
mc::cat_upvar(ref upvar_id, _, _) => {
|
||||
// if this is an implicit deref of an
|
||||
// upvar, then we need to modify the
|
||||
// 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) {
|
||||
mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
|
||||
mc::cat_deref(base, _, mc::Implicit(..)) => {
|
||||
match base.cat {
|
||||
mc::cat_upvar(ref upvar_id, _) => {
|
||||
mc::cat_upvar(ref upvar_id, _, _) => {
|
||||
// if this is an implicit deref of an
|
||||
// upvar, then we need to modify the
|
||||
// borrow_kind of the upvar to make sure it
|
||||
|
Loading…
x
Reference in New Issue
Block a user