Categorize upvars in Fn unboxed closures as freely aliasable

This causes borrowck to correctly reject mutation or mutable borrows
of upvars in `Fn` unboxed closures since the closure environment is
aliasable.

This also tracks the responsible closure in the aliasability
information returned and uses it to give a helpful diagnostic.

Closes issue #17780
This commit is contained in:
Brian Koropoff 2014-10-04 14:06:08 -07:00
parent ea3ab731a3
commit f74b1c4ee2
3 changed files with 23 additions and 2 deletions

View file

@ -854,6 +854,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
check_for_aliasability_violation(this, span, b.clone());
}
mc::cat_copied_upvar(mc::CopiedUpvar {
kind: mc::Unboxed(ty::FnUnboxedClosureKind), ..}) => {
// Prohibit writes to capture-by-move upvars in non-once closures
check_for_aliasability_violation(this, span, guarantor.clone());
}
_ => {}
}

View file

@ -728,6 +728,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
format!("{} in an aliasable location",
prefix).as_slice());
}
mc::AliasableClosure(id) => {
self.tcx.sess.span_err(span,
format!("{} in a free variable from an \
immutable unboxed closure", prefix).as_slice());
span_note!(self.tcx.sess, self.tcx.map.span(id),
"consider changing this closure to take self by mutable reference");
}
mc::AliasableStatic(..) |
mc::AliasableStaticMut(..) => {
self.tcx.sess.span_err(

View file

@ -83,7 +83,8 @@ 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, Option<ty::UnboxedClosureKind>), // by ref upvar from stack or unboxed 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
@ -1246,6 +1247,7 @@ pub enum InteriorSafety {
pub enum AliasableReason {
AliasableBorrowed,
AliasableClosure(ast::NodeId), // Aliasable due to capture by unboxed closure expr
AliasableOther,
AliasableStatic(InteriorSafety),
AliasableStaticMut(InteriorSafety),
@ -1302,7 +1304,6 @@ impl cmt_ {
cat_rvalue(..) |
cat_local(..) |
cat_upvar(..) |
cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
None
}
@ -1317,6 +1318,13 @@ impl cmt_ {
}
}
cat_upvar(ty::UpvarId { closure_expr_id: id, .. }, _,
Some(ty::FnUnboxedClosureKind)) => {
Some(AliasableClosure(id))
}
cat_upvar(..) => None,
cat_static_item(..) => {
let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
InteriorUnsafe