(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).
#[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
Categorization::Deref(ref base_cmt, _) => {
base_cmt.immutability_blame()
}
+ Categorization::ThreadLocal(..) |
Categorization::StaticItem => {
// Do we want to do something here?
None
}
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
match self.cat {
Categorization::Rvalue(..) |
Categorization::StaticItem |
+ Categorization::ThreadLocal(..) |
Categorization::Local(..) |
Categorization::Deref(_, UnsafePtr(..)) |
Categorization::Deref(_, BorrowedPtr(..)) |
}
Categorization::Rvalue(..) |
+ Categorization::ThreadLocal(..) |
Categorization::Local(..) |
Categorization::Upvar(..) |
Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but...
Categorization::StaticItem => {
"static item".into()
}
+ Categorization::ThreadLocal(..) => {
+ "thread-local static item".into()
+ }
Categorization::Rvalue(..) => {
"non-place".into()
}
// 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 {
match cmt.cat {
Categorization::Deref(_, mc::BorrowedPtr(..)) |
Categorization::Deref(_, mc::UnsafePtr(..)) |
+ Categorization::ThreadLocal(..) |
Categorization::StaticItem => {
Some(cmt.clone())
}
match cmt.cat {
Categorization::Rvalue(..) |
+ Categorization::ThreadLocal(..) |
Categorization::Local(..) | // L-Local
Categorization::Upvar(..) |
Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
//! rooting etc, and presuming `cmt` is not mutated.
match cmt.cat {
+ Categorization::ThreadLocal(temp_scope) |
Categorization::Rvalue(temp_scope) => {
temp_scope
}
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)
}
}
}
- _ => {
+
+ Categorization::Rvalue(..) |
+ Categorization::Local(..) |
+ Categorization::Upvar(..) => {
span_bug!(move_from.span, "this path should not cause illegal move");
}
}
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));
match cmt.cat {
Categorization::Rvalue(..) |
+ Categorization::ThreadLocal(..) |
Categorization::StaticItem => {
(None, false)
}
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.
| Categorization::StaticItem
| Categorization::Upvar(..)
| Categorization::Local(..)
+ | Categorization::ThreadLocal(..)
| Categorization::Rvalue(..) => {
// These are all "base cases" with independent lifetimes
// that are not subject to inference
Categorization::Deref(_, mc::UnsafePtr(..)) |
Categorization::StaticItem |
+ Categorization::ThreadLocal(..) |
Categorization::Rvalue(..) |
Categorization::Local(_) |
Categorization::Upvar(..) => {
Categorization::Deref(_, mc::UnsafePtr(..)) |
Categorization::StaticItem |
+ Categorization::ThreadLocal(..) |
Categorization::Rvalue(..) |
Categorization::Local(_) |
Categorization::Upvar(..) => {}