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).
This commit is contained in:
Felix S. Klock II 2018-10-17 16:31:22 +02:00
parent 5ea8eb55cd
commit a75f7810a7
10 changed files with 42 additions and 9 deletions

View file

@ -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()
}

View file

@ -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 {

View 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())
}

View file

@ -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
}

View 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");
}
}

View file

@ -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));

View 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)
}

View file

@ -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.

View file

@ -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

View file

@ -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(..) => {}