diff options
| author | Brian Koropoff <bkoropoff@gmail.com> | 2014-10-04 14:06:08 -0700 |
|---|---|---|
| committer | Brian Koropoff <bkoropoff@gmail.com> | 2014-10-05 00:24:10 -0700 |
| commit | f74b1c4ee255ab7cd2706896bced45f14e1ccc1a (patch) | |
| tree | 481c425b441cce2c9760b4d3126f3ba618cbebe7 /src | |
| parent | ea3ab731a3c762829e3f2bec5bfbaa3a3a84689f (diff) | |
| download | rust-f74b1c4ee255ab7cd2706896bced45f14e1ccc1a.tar.gz rust-f74b1c4ee255ab7cd2706896bced45f14e1ccc1a.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/borrowck/check_loans.rs | 6 | ||||
| -rw-r--r-- | src/librustc/middle/borrowck/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/middle/mem_categorization.rs | 12 |
3 files changed, 23 insertions, 2 deletions
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index e114eb88705..df18ec30f0e 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -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()); + } + _ => {} } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 710193188ee..a86ae420065 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -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( diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 207722eba00..9a0885ca301 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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 |
