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 } ;
1010use rustc_data_structures:: fx:: FxHashSet ;
1111use rustc_hir as hir;
1212use rustc_hir:: def_id:: DefId ;
@@ -17,9 +17,12 @@ use rustc_middle::middle::region::*;
1717use rustc_middle:: ty:: TyCtxt ;
1818use rustc_span:: source_map;
1919use rustc_span:: Span ;
20+ use rustc_type_ir:: Mutability ;
2021
2122use std:: mem;
2223
24+ use crate :: errors;
25+
2326#[ derive( Debug , Copy , Clone ) ]
2427pub 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+ }
0 commit comments