Skip to content

Commit

Permalink
Disallow use of static mut inside unsafe block
Browse files Browse the repository at this point in the history
```rust
static mut X: i32 = 23;
unsafe {
  let y = &X;
}
```

This is the idea for the 2024 edition.
Add `E0796` error code.
  • Loading branch information
obeis committed Nov 10, 2023
1 parent 6e2a352 commit d5e84b2
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 1 deletion.
1 change: 1 addition & 0 deletions compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0796.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 30 additions & 1 deletion compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 });
}
}
}
9 changes: 9 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

0 comments on commit d5e84b2

Please sign in to comment.