]> git.lizzy.rs Git - rust.git/commitdiff
AST-borrowck: add separate mem category for thread-locals, as they are not quite...
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Wed, 17 Oct 2018 14:31:22 +0000 (16:31 +0200)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Wed, 17 Oct 2018 14:31:22 +0000 (16:31 +0200)
(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).

src/librustc/middle/mem_categorization.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs

index 13e6f7a4c745a18c4e884d1c4579202f1540ed41..9d3f37bc36a9d5873796ba3bd66a3f8582ba8947 100644 (file)
@@ -93,6 +93,7 @@
 #[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 @@ pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'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 @@ pub fn cat_def(&self,
             }
 
             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 @@ pub fn guarantor(&self) -> cmt_<'tcx> {
         match self.cat {
             Categorization::Rvalue(..) |
             Categorization::StaticItem |
+            Categorization::ThreadLocal(..) |
             Categorization::Local(..) |
             Categorization::Deref(_, UnsafePtr(..)) |
             Categorization::Deref(_, BorrowedPtr(..)) |
@@ -1439,6 +1448,7 @@ pub fn freely_aliasable(&self) -> Aliasability {
             }
 
             Categorization::Rvalue(..) |
+            Categorization::ThreadLocal(..) |
             Categorization::Local(..) |
             Categorization::Upvar(..) |
             Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but...
@@ -1485,6 +1495,9 @@ pub fn descriptive_string(&self, tcx: TyCtxt<'_, '_, '_>) -> Cow<'static, str> {
             Categorization::StaticItem => {
                 "static item".into()
             }
+            Categorization::ThreadLocal(..) => {
+                "thread-local static item".into()
+            }
             Categorization::Rvalue(..) => {
                 "non-place".into()
             }
index 34ee03b895f9f6615522f5a4cf5e54f558950dd6..033ed8008edc216c8e7da4020b83a4f2b655038c 100644 (file)
@@ -377,6 +377,7 @@ pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
                 // 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 {
index ffc4fbfb4c9cb12839824eef37f04373f1dda358..7bb5f411752fe45630d92aacbbe6af082e2b7711 100644 (file)
@@ -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())
         }
index c9dcc0d9fa266beb190653e31c7526d7309f267a..6ef5d65d10dca6ade262c1fce3706ff0e13fc70a 100644 (file)
@@ -70,6 +70,7 @@ fn check(&self, cmt: &mc::cmt_<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
 
         match cmt.cat {
             Categorization::Rvalue(..) |
+            Categorization::ThreadLocal(..) |
             Categorization::Local(..) |                     // L-Local
             Categorization::Upvar(..) |
             Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
@@ -105,6 +106,7 @@ fn scope(&self, cmt: &mc::cmt_<'tcx>) -> ty::Region<'tcx> {
         //! rooting etc, and presuming `cmt` is not mutated.
 
         match cmt.cat {
+            Categorization::ThreadLocal(temp_scope) |
             Categorization::Rvalue(temp_scope) => {
                 temp_scope
             }
index b29ab55f9ba78a950197cb2c208ef7b8be43187c..e1a4473539c8c567c531caabb8b167aebddcb805 100644 (file)
@@ -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");
         }
     }
index d9784cc2177fde18003c252b9760e512d341b224..52c7ebb4beb0234906183c5f3fcedcbaafb8d358 100644 (file)
@@ -70,6 +70,12 @@ fn restrict(&self,
                 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));
index 0ef0d284770f555f4577a758e68c5a590a4c3e93..d56eb188ccd2d1694f32bd6ead3b3980c4863de4 100644 (file)
@@ -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)
         }
index 5e9169e86a98d7626d2f80889e8b874dd7dd7f9d..ca58239df8eac3b77fa42c23574df7663483dc19 100644 (file)
@@ -663,6 +663,7 @@ fn borrow(&mut self,
         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.
index 80b4ba6240d335099618e82340053d38e2395479..212ee2698e012063d3b63e0e52b284a658438836 100644 (file)
@@ -1243,6 +1243,7 @@ fn link_region(
                 | Categorization::StaticItem
                 | Categorization::Upvar(..)
                 | Categorization::Local(..)
+                | Categorization::ThreadLocal(..)
                 | Categorization::Rvalue(..) => {
                     // These are all "base cases" with independent lifetimes
                     // that are not subject to inference
index 99effce4ee08df4edfa44c5c68910206de179e24..df994ad9e55c4d3dc78f1cad670b59292c19e6ff 100644 (file)
@@ -401,6 +401,7 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) {
 
             Categorization::Deref(_, mc::UnsafePtr(..)) |
             Categorization::StaticItem |
+            Categorization::ThreadLocal(..) |
             Categorization::Rvalue(..) |
             Categorization::Local(_) |
             Categorization::Upvar(..) => {
@@ -431,6 +432,7 @@ fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) {
 
             Categorization::Deref(_, mc::UnsafePtr(..)) |
             Categorization::StaticItem |
+            Categorization::ThreadLocal(..) |
             Categorization::Rvalue(..) |
             Categorization::Local(_) |
             Categorization::Upvar(..) => {}