From d5e84b2c8e8876a13f3e09e72495dc1d66f2047f Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 10 Nov 2023 14:36:10 +0300 Subject: [PATCH] Disallow use of `static mut` inside unsafe block ```rust static mut X: i32 = 23; unsafe { let y = &X; } ``` This is the idea for the 2024 edition. Add `E0796` error code. --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0796.md | 20 ++++++++++++ compiler/rustc_hir_analysis/messages.ftl | 4 +++ .../rustc_hir_analysis/src/check/region.rs | 31 ++++++++++++++++++- compiler/rustc_hir_analysis/src/errors.rs | 9 ++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0796.md diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 6680e8875c3e3..c9348e81532b1 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -515,6 +515,7 @@ E0792: include_str!("./error_codes/E0792.md"), E0793: include_str!("./error_codes/E0793.md"), E0794: include_str!("./error_codes/E0794.md"), E0795: include_str!("./error_codes/E0795.md"), +E0796: include_str!("./error_codes/E0796.md"), } // Undocumented removed error codes. Note that many removed error codes are kept in the list above diff --git a/compiler/rustc_error_codes/src/error_codes/E0796.md b/compiler/rustc_error_codes/src/error_codes/E0796.md new file mode 100644 index 0000000000000..2bb0373f827c5 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0796.md @@ -0,0 +1,20 @@ +Use of mutable static. + +Erroneous code example: + +```compile_fail,E0796 +static mut X: i32 = 23; +unsafe { + let y = &X; +} + +unsafe fn foo() { + static mut X: i32 = 1; + let y = &X; +} +``` + +Mutable statics can be mutated by multiple threads: aliasing violations or +data races will cause undefined behavior. + +Use of mutable static is a hard error from 2024 edition. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 8ab91bebcf672..4e32559f6779d 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -333,6 +333,10 @@ hir_analysis_start_not_target_feature = `#[start]` function is not allowed to ha hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]` .label = `#[start]` function is not allowed to be `#[track_caller]` +hir_analysis_static_mut_ref = use of mutable static is discouraged + .label = use of mutable static + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + hir_analysis_static_specialize = cannot specialize on `'static` lifetime hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 40b33117f7ccc..10d19d2958737 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -6,7 +6,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc_ast::walk_list; +use rustc_ast::{walk_list, BorrowKind}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -17,9 +17,12 @@ use rustc_middle::middle::region::*; use rustc_middle::ty::TyCtxt; use rustc_span::source_map; use rustc_span::Span; +use rustc_type_ir::Mutability; use std::mem; +use crate::errors; + #[derive(Debug, Copy, Clone)] pub struct Context { /// The scope that contains any new variables declared, plus its depth in @@ -90,6 +93,13 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h let prev_cx = visitor.cx; + if let hir::BlockCheckMode::UnsafeBlock(src) = blk.rules + && matches!(src, hir::UnsafeSource::UserProvided) + && blk.span.edition().at_least_rust_2024() + { + static_mut_ref(visitor.tcx, blk.stmts); + } + // We treat the tail expression in the block (if any) somewhat // differently from the statements. The issue has to do with // temporary lifetimes. Consider the following: @@ -887,3 +897,22 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { tcx.arena.alloc(scope_tree) } + +/// Check for use of mutable static +pub fn static_mut_ref(tcx: TyCtxt<'_>, stmts: &[Stmt<'_>]) { + for stmt in stmts { + if let hir::StmtKind::Local(loc) = stmt.kind + && let Some(init) = loc.init + && let hir::ExprKind::AddrOf(borrow_kind, _, expr) = init.kind + && matches!(borrow_kind, BorrowKind::Ref) + && let hir::ExprKind::Path(qpath) = expr.kind + && let hir::QPath::Resolved(_, path) = qpath + && let hir::def::Res::Def(def_kind, _) = path.res + && let hir::def::DefKind::Static(mt) = def_kind + && matches!(mt, Mutability::Mut) + { + let span = init.span; + tcx.sess.emit_err(errors::StaticMutRef { span }); + } + } +} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index dd83b5b6f2c03..7960e53d25e8e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1329,3 +1329,12 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> { pub mut_key: &'a str, pub ptr_ty: Ty<'a>, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_static_mut_ref, code = "E0796")] +#[note] +pub struct StaticMutRef { + #[primary_span] + #[label] + pub span: Span, +}