Skip to content

Commit d1f8400

Browse files
committed
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.
1 parent 056717b commit d1f8400

File tree

5 files changed

+64
-1
lines changed

5 files changed

+64
-1
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ E0792: include_str!("./error_codes/E0792.md"),
515515
E0793: include_str!("./error_codes/E0793.md"),
516516
E0794: include_str!("./error_codes/E0794.md"),
517517
E0795: include_str!("./error_codes/E0795.md"),
518+
E0796: include_str!("./error_codes/E0796.md"),
518519
}
519520

520521
// Undocumented removed error codes. Note that many removed error codes are kept in the list above
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Use of mutable static.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,edition2024,E0796
6+
static mut X: i32 = 23;
7+
unsafe {
8+
let y = &X;
9+
}
10+
11+
unsafe fn foo() {
12+
static mut X: i32 = 1;
13+
let y = &X;
14+
}
15+
```
16+
17+
Mutable statics can be mutated by multiple threads: aliasing violations or
18+
data races will cause undefined behavior.
19+
20+
Use of mutable static is a hard error from 2024 edition.

compiler/rustc_hir_analysis/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ hir_analysis_start_not_target_feature = `#[start]` function is not allowed to ha
333333
hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]`
334334
.label = `#[start]` function is not allowed to be `#[track_caller]`
335335
336+
hir_analysis_static_mut_ref = use of mutable static is discouraged
337+
.label = use of mutable static
338+
.note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
339+
336340
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
337341
338342
hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl

compiler/rustc_hir_analysis/src/check/region.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//!
77
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
88
9-
use rustc_ast::walk_list;
9+
use rustc_ast::{walk_list, BorrowKind};
1010
use rustc_data_structures::fx::FxHashSet;
1111
use rustc_hir as hir;
1212
use rustc_hir::def_id::DefId;
@@ -17,9 +17,12 @@ use rustc_middle::middle::region::*;
1717
use rustc_middle::ty::TyCtxt;
1818
use rustc_span::source_map;
1919
use rustc_span::Span;
20+
use rustc_type_ir::Mutability;
2021

2122
use std::mem;
2223

24+
use crate::errors;
25+
2326
#[derive(Debug, Copy, Clone)]
2427
pub struct Context {
2528
/// 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
9093

9194
let prev_cx = visitor.cx;
9295

96+
if let hir::BlockCheckMode::UnsafeBlock(src) = blk.rules
97+
&& matches!(src, hir::UnsafeSource::UserProvided)
98+
&& blk.span.edition().at_least_rust_2024()
99+
{
100+
static_mut_ref(visitor.tcx, blk.stmts);
101+
}
102+
93103
// We treat the tail expression in the block (if any) somewhat
94104
// differently from the statements. The issue has to do with
95105
// temporary lifetimes. Consider the following:
@@ -887,3 +897,22 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
887897

888898
tcx.arena.alloc(scope_tree)
889899
}
900+
901+
/// Check for use of mutable static
902+
pub fn static_mut_ref(tcx: TyCtxt<'_>, stmts: &[Stmt<'_>]) {
903+
for stmt in stmts {
904+
if let hir::StmtKind::Local(loc) = stmt.kind
905+
&& let Some(init) = loc.init
906+
&& let hir::ExprKind::AddrOf(borrow_kind, _, expr) = init.kind
907+
&& matches!(borrow_kind, BorrowKind::Ref)
908+
&& let hir::ExprKind::Path(qpath) = expr.kind
909+
&& let hir::QPath::Resolved(_, path) = qpath
910+
&& let hir::def::Res::Def(def_kind, _) = path.res
911+
&& let hir::def::DefKind::Static(mt) = def_kind
912+
&& matches!(mt, Mutability::Mut)
913+
{
914+
let span = init.span;
915+
tcx.sess.emit_err(errors::StaticMutRef { span });
916+
}
917+
}
918+
}

compiler/rustc_hir_analysis/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1329,3 +1329,12 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> {
13291329
pub mut_key: &'a str,
13301330
pub ptr_ty: Ty<'a>,
13311331
}
1332+
1333+
#[derive(Diagnostic)]
1334+
#[diag(hir_analysis_static_mut_ref, code = "E0796")]
1335+
#[note]
1336+
pub struct StaticMutRef {
1337+
#[primary_span]
1338+
#[label]
1339+
pub span: Span,
1340+
}

0 commit comments

Comments
 (0)