about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2018-10-17 16:31:22 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2018-10-17 16:31:22 +0200
commita75f7810a7118e3bb103058091c1d6414b515786 (patch)
tree0dfdbb075ec1810a6fee15fda466aceada5fa447
parent5ea8eb55cd9f4547b332f43c9f723de30187c223 (diff)
downloadrust-a75f7810a7118e3bb103058091c1d6414b515786.tar.gz
rust-a75f7810a7118e3bb103058091c1d6414b515786.zip
AST-borrowck: add separate mem category for thread-locals, as they are not quite rvalues
(and of course they are not quite statics either).

Namely, they *do* have a restricted region (like rvalues), but they
also cannot be moved out of (like statics).
-rw-r--r--src/librustc/middle/mem_categorization.rs29
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/lifetime.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs7
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs6
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs1
-rw-r--r--src/librustc_passes/rvalue_promotion.rs1
-rw-r--r--src/librustc_typeck/check/regionck.rs1
-rw-r--r--src/librustc_typeck/check/upvar.rs2
10 files changed, 42 insertions, 9 deletions
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 13e6f7a4c74..9d3f37bc36a 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -93,6 +93,7 @@ use util::nodemap::ItemLocalSet;
 #[derive(Clone, Debug, PartialEq)]
 pub enum Categorization<'tcx> {
     Rvalue(ty::Region<'tcx>),            // temporary val, argument is its scope
+    ThreadLocal(ty::Region<'tcx>),       // value that cannot move, but still restricted in scope
     StaticItem,
     Upvar(Upvar),                        // upvar referenced by closure env
     Local(ast::NodeId),                  // local variable
@@ -268,6 +269,7 @@ impl<'tcx> cmt_<'tcx> {
             Categorization::Deref(ref base_cmt, _) => {
                 base_cmt.immutability_blame()
             }
+            Categorization::ThreadLocal(..) |
             Categorization::StaticItem => {
                 // Do we want to do something here?
                 None
@@ -715,17 +717,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
 
             Def::Static(def_id, mutbl) => {
-                // `#[thread_local]` statics may not outlive the current function.
-                for attr in &self.tcx.get_attrs(def_id)[..] {
-                    if attr.check_name("thread_local") {
-                        return Ok(self.cat_rvalue_node(hir_id, span, expr_ty));
-                    }
-                }
+                // `#[thread_local]` statics may not outlive the current function, but
+                // they also cannot be moved out of.
+                let is_thread_local = self.tcx.get_attrs(def_id)[..]
+                    .iter()
+                    .any(|attr| attr.check_name("thread_local"));
+
+                let cat = if is_thread_local {
+                    let re = self.temporary_scope(hir_id.local_id);
+                    Categorization::ThreadLocal(re)
+                } else {
+                    Categorization::StaticItem
+                };
 
                 Ok(cmt_ {
                     hir_id,
-                    span:span,
-                    cat:Categorization::StaticItem,
+                    span,
+                    cat,
                     mutbl: if mutbl { McDeclared } else { McImmutable},
                     ty:expr_ty,
                     note: NoteNone
@@ -1408,6 +1416,7 @@ impl<'tcx> cmt_<'tcx> {
         match self.cat {
             Categorization::Rvalue(..) |
             Categorization::StaticItem |
+            Categorization::ThreadLocal(..) |
             Categorization::Local(..) |
             Categorization::Deref(_, UnsafePtr(..)) |
             Categorization::Deref(_, BorrowedPtr(..)) |
@@ -1439,6 +1448,7 @@ impl<'tcx> cmt_<'tcx> {
             }
 
             Categorization::Rvalue(..) |
+            Categorization::ThreadLocal(..) |
             Categorization::Local(..) |
             Categorization::Upvar(..) |
             Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but...
@@ -1485,6 +1495,9 @@ impl<'tcx> cmt_<'tcx> {
             Categorization::StaticItem => {
                 "static item".into()
             }
+            Categorization::ThreadLocal(..) => {
+                "thread-local static item".into()
+            }
             Categorization::Rvalue(..) => {
                 "non-place".into()
             }
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 34ee03b895f..033ed8008ed 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -377,6 +377,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 // by-move upvars, which is local data for generators
                 Categorization::Upvar(..) => true,
 
+                Categorization::ThreadLocal(region) |
                 Categorization::Rvalue(region) => {
                     // Rvalues promoted to 'static are no longer local
                     if let RegionKind::ReStatic = *region {
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index ffc4fbfb4c9..7bb5f411752 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -177,6 +177,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     match cmt.cat {
         Categorization::Deref(_, mc::BorrowedPtr(..)) |
         Categorization::Deref(_, mc::UnsafePtr(..)) |
+        Categorization::ThreadLocal(..) |
         Categorization::StaticItem => {
             Some(cmt.clone())
         }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
index c9dcc0d9fa2..6ef5d65d10d 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
@@ -70,6 +70,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
 
         match cmt.cat {
             Categorization::Rvalue(..) |
+            Categorization::ThreadLocal(..) |
             Categorization::Local(..) |                     // L-Local
             Categorization::Upvar(..) |
             Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
@@ -105,6 +106,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
         //! rooting etc, and presuming `cmt` is not mutated.
 
         match cmt.cat {
+            Categorization::ThreadLocal(temp_scope) |
             Categorization::Rvalue(temp_scope) => {
                 temp_scope
             }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index b29ab55f9ba..e1a4473539c 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -145,6 +145,8 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
     match move_from.cat {
         Categorization::Deref(_, mc::BorrowedPtr(..)) |
         Categorization::Deref(_, mc::UnsafePtr(..)) |
+        Categorization::Deref(_, mc::Unique) |
+        Categorization::ThreadLocal(..) |
         Categorization::StaticItem => {
             bccx.cannot_move_out_of(
                 move_from.span, &move_from.descriptive_string(bccx.tcx), Origin::Ast)
@@ -166,7 +168,10 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
                 }
             }
         }
-        _ => {
+
+        Categorization::Rvalue(..) |
+        Categorization::Local(..) |
+        Categorization::Upvar(..) => {
             span_bug!(move_from.span, "this path should not cause illegal move");
         }
     }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index d9784cc2177..52c7ebb4beb 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -70,6 +70,12 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 RestrictionResult::Safe
             }
 
+            Categorization::ThreadLocal(..) => {
+                // Thread-locals are statics that have a scope, with
+                // no underlying structure to provide restrictions.
+                RestrictionResult::Safe
+            }
+
             Categorization::Local(local_id) => {
                 // R-Variable, locally declared
                 let lp = new_lp(LpVar(local_id));
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 0ef0d284770..d56eb188ccd 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -520,6 +520,7 @@ pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt_<'tcx>) -> (Option<Rc<LoanPath
 
     match cmt.cat {
         Categorization::Rvalue(..) |
+        Categorization::ThreadLocal(..) |
         Categorization::StaticItem => {
             (None, false)
         }
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 5e9169e86a9..ca58239df8e 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -663,6 +663,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
         let mut cur = cmt;
         loop {
             match cur.cat {
+                Categorization::ThreadLocal(..) |
                 Categorization::Rvalue(..) => {
                     if loan_cause == euv::MatchDiscriminant {
                         // Ignore the dummy immutable borrow created by EUV.
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 80b4ba6240d..212ee2698e0 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -1243,6 +1243,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                 | Categorization::StaticItem
                 | Categorization::Upvar(..)
                 | Categorization::Local(..)
+                | Categorization::ThreadLocal(..)
                 | Categorization::Rvalue(..) => {
                     // These are all "base cases" with independent lifetimes
                     // that are not subject to inference
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 99effce4ee0..df994ad9e55 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -401,6 +401,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
 
             Categorization::Deref(_, mc::UnsafePtr(..)) |
             Categorization::StaticItem |
+            Categorization::ThreadLocal(..) |
             Categorization::Rvalue(..) |
             Categorization::Local(_) |
             Categorization::Upvar(..) => {
@@ -431,6 +432,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
 
             Categorization::Deref(_, mc::UnsafePtr(..)) |
             Categorization::StaticItem |
+            Categorization::ThreadLocal(..) |
             Categorization::Rvalue(..) |
             Categorization::Local(_) |
             Categorization::Upvar(..) => {}