Make pointers to statics internal
This commit is contained in:
parent
e0bbe7915e
commit
f30a8186f7
@ -233,28 +233,30 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||
if let (local, []) = (&place.local, proj_base) {
|
||||
let decl = &self.body.local_decls[*local];
|
||||
if decl.internal {
|
||||
// Internal locals are used in the `move_val_init` desugaring.
|
||||
// We want to check unsafety against the source info of the
|
||||
// desugaring, rather than the source info of the RHS.
|
||||
self.source_info = self.body.local_decls[*local].source_info;
|
||||
} else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
|
||||
if self.tcx.is_mutable_static(def_id) {
|
||||
self.require_unsafe(
|
||||
"use of mutable static",
|
||||
"mutable statics can be mutated by multiple threads: aliasing \
|
||||
violations or data races will cause undefined behavior",
|
||||
UnsafetyViolationKind::General,
|
||||
);
|
||||
return;
|
||||
} else if self.tcx.is_foreign_item(def_id) {
|
||||
self.require_unsafe(
|
||||
"use of extern static",
|
||||
"extern statics are not controlled by the Rust type system: \
|
||||
invalid data, aliasing violations or data races will cause \
|
||||
undefined behavior",
|
||||
UnsafetyViolationKind::General,
|
||||
);
|
||||
return;
|
||||
if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
|
||||
if self.tcx.is_mutable_static(def_id) {
|
||||
self.require_unsafe(
|
||||
"use of mutable static",
|
||||
"mutable statics can be mutated by multiple threads: aliasing \
|
||||
violations or data races will cause undefined behavior",
|
||||
UnsafetyViolationKind::General,
|
||||
);
|
||||
return;
|
||||
} else if self.tcx.is_foreign_item(def_id) {
|
||||
self.require_unsafe(
|
||||
"use of extern static",
|
||||
"extern statics are not controlled by the Rust type system: \
|
||||
invalid data, aliasing violations or data races will cause \
|
||||
undefined behavior",
|
||||
UnsafetyViolationKind::General,
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Internal locals are used in the `move_val_init` desugaring.
|
||||
// We want to check unsafety against the source info of the
|
||||
// desugaring, rather than the source info of the RHS.
|
||||
self.source_info = self.body.local_decls[*local].source_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
if let ExprKind::StaticRef { def_id, .. } = expr.kind {
|
||||
let is_thread_local = this.hir.tcx().has_attr(def_id, sym::thread_local);
|
||||
local_decl.internal = true;
|
||||
local_decl.local_info = LocalInfo::StaticRef { def_id, is_thread_local };
|
||||
}
|
||||
this.local_decls.push(local_decl)
|
||||
|
@ -222,8 +222,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
|
||||
|
||||
match &expr.kind {
|
||||
ExprKind::Call(callee, args) => match &callee.kind {
|
||||
ExprKind::Path(qpath) => {
|
||||
@ -249,20 +247,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||
}
|
||||
_ => intravisit::walk_expr(self, expr),
|
||||
},
|
||||
ExprKind::Path(qpath) => {
|
||||
let res = self.fcx.tables.borrow().qpath_res(qpath, expr.hir_id);
|
||||
if let Res::Def(DefKind::Static, def_id) = res {
|
||||
// Statics are lowered to temporary references or
|
||||
// pointers in MIR, so record that type.
|
||||
let ptr_ty = self.fcx.tcx.static_ptr_ty(def_id);
|
||||
self.record(ptr_ty, scope, Some(expr), expr.span);
|
||||
}
|
||||
}
|
||||
_ => intravisit::walk_expr(self, expr),
|
||||
}
|
||||
|
||||
self.expr_count += 1;
|
||||
|
||||
let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
|
||||
|
||||
// If there are adjustments, then record the final type --
|
||||
// this is the actual value that is being produced.
|
||||
if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) {
|
||||
|
@ -0,0 +1,33 @@
|
||||
// build-pass
|
||||
// edition:2018
|
||||
|
||||
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
|
||||
|
||||
fn is_send_sync<T: Send + Sync>(_: T) {}
|
||||
|
||||
async fn fun() {
|
||||
let u = unsafe { A[async { 1 }.await] };
|
||||
unsafe {
|
||||
match A {
|
||||
i if async { true }.await => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let index_block = async {
|
||||
let u = unsafe { A[async { 1 }.await] };
|
||||
};
|
||||
let match_block = async {
|
||||
unsafe {
|
||||
match A {
|
||||
i if async { true }.await => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
};
|
||||
is_send_sync(index_block);
|
||||
is_send_sync(match_block);
|
||||
is_send_sync(fun());
|
||||
}
|
29
src/test/ui/generator/static-mut-reference-across-yield.rs
Normal file
29
src/test/ui/generator/static-mut-reference-across-yield.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// build-pass
|
||||
#![feature(generators)]
|
||||
|
||||
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
|
||||
|
||||
fn is_send_sync<T: Send + Sync>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let gen_index = static || {
|
||||
let u = A[{
|
||||
yield;
|
||||
1
|
||||
}];
|
||||
};
|
||||
let gen_match = static || match A {
|
||||
i if {
|
||||
yield;
|
||||
true
|
||||
} =>
|
||||
{
|
||||
()
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
is_send_sync(gen_index);
|
||||
is_send_sync(gen_match);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user