From f30a8186f7469d464e46e3451e2b2e41609225dd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 23 Jan 2020 20:34:11 +0000 Subject: [PATCH] Make pointers to statics internal --- src/librustc_mir/transform/check_unsafety.rs | 46 ++++++++++--------- src/librustc_mir_build/build/expr/as_temp.rs | 1 + .../check/generator_interior.rs | 13 +----- .../issues/issue-67611-static-mut-refs.rs | 33 +++++++++++++ .../static-mut-reference-across-yield.rs | 29 ++++++++++++ 5 files changed, 89 insertions(+), 33 deletions(-) create mode 100644 src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs create mode 100644 src/test/ui/generator/static-mut-reference-across-yield.rs diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 4e943547f07f5..59d370abc71c5 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -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; } } } diff --git a/src/librustc_mir_build/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs index f47987c56174c..34dd10cbc0fc8 100644 --- a/src/librustc_mir_build/build/expr/as_temp.rs +++ b/src/librustc_mir_build/build/expr/as_temp.rs @@ -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) diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index fc02d17a50f37..75cc2c132f8a8 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -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) { diff --git a/src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs b/src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs new file mode 100644 index 0000000000000..dda4a151dd2d6 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs @@ -0,0 +1,33 @@ +// build-pass +// edition:2018 + +static mut A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn is_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()); +} diff --git a/src/test/ui/generator/static-mut-reference-across-yield.rs b/src/test/ui/generator/static-mut-reference-across-yield.rs new file mode 100644 index 0000000000000..2926bba997803 --- /dev/null +++ b/src/test/ui/generator/static-mut-reference-across-yield.rs @@ -0,0 +1,29 @@ +// build-pass +#![feature(generators)] + +static mut A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn is_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); + } +}