Skip to content

Commit bac72cf

Browse files
committed
Add safe/unsafe to static inside extern blocks
1 parent b4cbdb7 commit bac72cf

File tree

27 files changed

+152
-57
lines changed

27 files changed

+152
-57
lines changed

Diff for: compiler/rustc_ast/src/ast.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -3164,6 +3164,7 @@ pub struct DelegationMac {
31643164
#[derive(Clone, Encodable, Decodable, Debug)]
31653165
pub struct StaticItem {
31663166
pub ty: P<Ty>,
3167+
pub safety: Safety,
31673168
pub mutability: Mutability,
31683169
pub expr: Option<P<Expr>>,
31693170
}
@@ -3182,7 +3183,7 @@ impl From<StaticItem> for StaticForeignItem {
31823183
fn from(static_item: StaticItem) -> StaticForeignItem {
31833184
StaticForeignItem {
31843185
ty: static_item.ty,
3185-
safety: Safety::Default,
3186+
safety: static_item.safety,
31863187
mutability: static_item.mutability,
31873188
expr: static_item.expr,
31883189
}
@@ -3193,6 +3194,7 @@ impl From<StaticForeignItem> for StaticItem {
31933194
fn from(static_item: StaticForeignItem) -> StaticItem {
31943195
StaticItem {
31953196
ty: static_item.ty,
3197+
safety: static_item.safety,
31963198
mutability: static_item.mutability,
31973199
expr: static_item.expr,
31983200
}

Diff for: compiler/rustc_ast/src/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ impl NoopVisitItemKind for ItemKind {
10801080
match self {
10811081
ItemKind::ExternCrate(_orig_name) => {}
10821082
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
1083-
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
1083+
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
10841084
vis.visit_ty(ty);
10851085
visit_opt(expr, |expr| vis.visit_expr(expr));
10861086
}

Diff for: compiler/rustc_ast/src/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ impl WalkItemKind for ItemKind {
334334
match self {
335335
ItemKind::ExternCrate(_) => {}
336336
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
337-
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
337+
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
338338
try_visit!(visitor.visit_ty(ty));
339339
visit_opt!(visitor, visit_expr, expr);
340340
}

Diff for: compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
181181

182182
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
183183
}
184-
ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
184+
ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
185185
let (ty, body_id) =
186186
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
187187
hir::ItemKind::Static(ty, *m, body_id)

Diff for: compiler/rustc_ast_pretty/src/pprust/state/item.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ impl<'a> State<'a> {
171171
self.print_use_tree(tree);
172172
self.word(";");
173173
}
174-
ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
174+
ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => {
175+
self.print_safety(*safety);
175176
self.print_item_const(
176177
item.ident,
177178
Some(*mutbl),

Diff for: compiler/rustc_const_eval/src/interpret/intern.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn intern_as_new_static<'tcx>(
102102
let feed = tcx.create_def(
103103
static_id,
104104
sym::nested,
105-
DefKind::Static { mutability: alloc.0.mutability, nested: true },
105+
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
106106
);
107107
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
108108

Diff for: compiler/rustc_const_eval/src/interpret/validity.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,9 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId)
711711
// We're not using `try_global_alloc` since dangling pointers have already been handled.
712712
match ecx.tcx.global_alloc(alloc_id) {
713713
GlobalAlloc::Static(did) => {
714-
let DefKind::Static { mutability, nested } = ecx.tcx.def_kind(did) else { bug!() };
714+
let DefKind::Static { safety: _, mutability, nested } = ecx.tcx.def_kind(did) else {
715+
bug!()
716+
};
715717
if nested {
716718
assert!(
717719
ecx.memory.alloc_map.get(alloc_id).is_none(),

Diff for: compiler/rustc_expand/src/build.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,10 @@ impl<'a> ExtCtxt<'a> {
631631
span,
632632
name,
633633
AttrVec::new(),
634-
ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()),
634+
ast::ItemKind::Static(
635+
ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) }
636+
.into(),
637+
),
635638
)
636639
}
637640

Diff for: compiler/rustc_hir/src/def.rs

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub enum DefKind {
7676
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
7777
ConstParam,
7878
Static {
79+
/// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`.
80+
safety: hir::Safety,
7981
/// Whether it's a `static mut` or just a `static`.
8082
mutability: ast::Mutability,
8183
/// Whether it's an anonymous static generated for nested allocations.

Diff for: compiler/rustc_hir_analysis/src/check/errs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
4141
if let hir::ExprKind::Path(qpath) = expr.kind
4242
&& let hir::QPath::Resolved(_, path) = qpath
4343
&& let hir::def::Res::Def(def_kind, _) = path.res
44-
&& let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
44+
&& let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
45+
def_kind
4546
{
4647
return Some(qpath_to_string(&tcx, &qpath));
4748
}

Diff for: compiler/rustc_metadata/src/rmeta/table.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,14 @@ fixed_size_enum! {
156156
( Impl { of_trait: false } )
157157
( Impl { of_trait: true } )
158158
( Closure )
159-
( Static { mutability: ast::Mutability::Not, nested: false } )
160-
( Static { mutability: ast::Mutability::Mut, nested: false } )
161-
( Static { mutability: ast::Mutability::Not, nested: true } )
162-
( Static { mutability: ast::Mutability::Mut, nested: true } )
159+
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } )
160+
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } )
161+
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: false } )
162+
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: false } )
163+
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: true } )
164+
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: true } )
165+
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: true } )
166+
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: true } )
163167
( Ctor(CtorOf::Struct, CtorKind::Fn) )
164168
( Ctor(CtorOf::Struct, CtorKind::Const) )
165169
( Ctor(CtorOf::Variant, CtorKind::Fn) )

Diff for: compiler/rustc_middle/src/hir/map/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,9 @@ impl<'hir> Map<'hir> {
305305
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
306306
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
307307
DefKind::Closure => BodyOwnerKind::Closure,
308-
DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability),
308+
DefKind::Static { safety: _, mutability, nested: false } => {
309+
BodyOwnerKind::Static(mutability)
310+
}
309311
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
310312
}
311313
}

Diff for: compiler/rustc_middle/src/mir/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -559,10 +559,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
559559
match (kind, body.source.promoted) {
560560
(_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
561561
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
562-
(DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => {
562+
(DefKind::Static { safety: _, mutability: hir::Mutability::Not, nested: false }, _) => {
563563
write!(w, "static ")?
564564
}
565-
(DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => {
565+
(DefKind::Static { safety: _, mutability: hir::Mutability::Mut, nested: false }, _) => {
566566
write!(w, "static mut ")?
567567
}
568568
(_, _) if is_function => write!(w, "fn ")?,

Diff for: compiler/rustc_mir_build/src/check_unsafety.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::build::ExprCategory;
22
use crate::errors::*;
33

44
use rustc_errors::DiagArgValue;
5+
use rustc_hir::def::DefKind;
56
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
67
use rustc_middle::mir::BorrowKind;
78
use rustc_middle::span_bug;
@@ -456,7 +457,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
456457
if self.tcx.is_mutable_static(def_id) {
457458
self.requires_unsafe(expr.span, UseOfMutableStatic);
458459
} else if self.tcx.is_foreign_item(def_id) {
459-
self.requires_unsafe(expr.span, UseOfExternStatic);
460+
match self.tcx.def_kind(def_id) {
461+
DefKind::Static { safety: hir::Safety::Safe, .. } => {}
462+
_ => self.requires_unsafe(expr.span, UseOfExternStatic),
463+
}
460464
}
461465
} else if self.thir[arg].ty.is_unsafe_ptr() {
462466
self.requires_unsafe(expr.span, DerefOfRawPointer);

Diff for: compiler/rustc_parse/src/parser/item.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,11 @@ impl<'a> Parser<'a> {
226226
self.expect_keyword(kw::Extern)?;
227227
self.parse_item_foreign_mod(attrs, safety)?
228228
} else if self.is_static_global() {
229+
let safety = self.parse_safety(Case::Sensitive);
229230
// STATIC ITEM
230231
self.bump(); // `static`
231232
let mutability = self.parse_mutability();
232-
let (ident, item) = self.parse_static_item(mutability)?;
233+
let (ident, item) = self.parse_static_item(safety, mutability)?;
233234
(ident, ItemKind::Static(Box::new(item)))
234235
} else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
235236
// CONST ITEM
@@ -952,7 +953,7 @@ impl<'a> Parser<'a> {
952953
let kind = match AssocItemKind::try_from(kind) {
953954
Ok(kind) => kind,
954955
Err(kind) => match kind {
955-
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
956+
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
956957
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
957958
AssocItemKind::Const(Box::new(ConstItem {
958959
defaultness: Defaultness::Final,
@@ -1259,7 +1260,10 @@ impl<'a> Parser<'a> {
12591260
matches!(token.kind, token::BinOp(token::Or) | token::OrOr)
12601261
})
12611262
} else {
1262-
false
1263+
let quals: &[Symbol] = &[kw::Unsafe, kw::Safe];
1264+
// `$qual static`
1265+
quals.iter().any(|&kw| self.check_keyword(kw))
1266+
&& self.look_ahead(1, |t| t.is_keyword(kw::Static))
12631267
}
12641268
}
12651269

@@ -1320,7 +1324,11 @@ impl<'a> Parser<'a> {
13201324
/// ```ebnf
13211325
/// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
13221326
/// ```
1323-
fn parse_static_item(&mut self, mutability: Mutability) -> PResult<'a, (Ident, StaticItem)> {
1327+
fn parse_static_item(
1328+
&mut self,
1329+
safety: Safety,
1330+
mutability: Mutability,
1331+
) -> PResult<'a, (Ident, StaticItem)> {
13241332
let ident = self.parse_ident()?;
13251333

13261334
if self.token.kind == TokenKind::Lt && self.may_recover() {
@@ -1341,7 +1349,7 @@ impl<'a> Parser<'a> {
13411349

13421350
self.expect_semi()?;
13431351

1344-
Ok((ident, StaticItem { ty, mutability, expr }))
1352+
Ok((ident, StaticItem { ty, safety, mutability, expr }))
13451353
}
13461354

13471355
/// Parse a constant item with the prefix `"const"` already parsed.

Diff for: compiler/rustc_resolve/src/def_collector.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::{ImplTraitContext, Resolver};
22
use rustc_ast::visit::FnKind;
33
use rustc_ast::*;
44
use rustc_expand::expand::AstFragment;
5+
use rustc_hir as hir;
56
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
67
use rustc_hir::def_id::LocalDefId;
78
use rustc_span::hygiene::LocalExpnId;
@@ -128,7 +129,11 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
128129
ItemKind::Union(..) => DefKind::Union,
129130
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
130131
ItemKind::TyAlias(..) => DefKind::TyAlias,
131-
ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false },
132+
ItemKind::Static(s) => DefKind::Static {
133+
safety: hir::Safety::Safe,
134+
mutability: s.mutability,
135+
nested: false,
136+
},
132137
ItemKind::Const(..) => DefKind::Const,
133138
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
134139
ItemKind::MacroDef(..) => {
@@ -215,8 +220,15 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
215220
ty: _,
216221
mutability,
217222
expr: _,
218-
safety: _,
219-
}) => DefKind::Static { mutability, nested: false },
223+
safety,
224+
}) => {
225+
let safety = match safety {
226+
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
227+
ast::Safety::Safe(_) => hir::Safety::Safe,
228+
};
229+
230+
DefKind::Static { safety, mutability, nested: false }
231+
}
220232
ForeignItemKind::Fn(_) => DefKind::Fn,
221233
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
222234
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),

Diff for: src/librustdoc/passes/collect_intra_doc_links.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_errors::{Applicability, Diag, DiagMessage};
1212
use rustc_hir::def::Namespace::*;
1313
use rustc_hir::def::{DefKind, Namespace, PerNS};
1414
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
15-
use rustc_hir::Mutability;
15+
use rustc_hir::{Mutability, Safety};
1616
use rustc_middle::ty::{Ty, TyCtxt};
1717
use rustc_middle::{bug, span_bug, ty};
1818
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
@@ -1517,7 +1517,11 @@ impl Disambiguator {
15171517
"union" => Kind(DefKind::Union),
15181518
"module" | "mod" => Kind(DefKind::Mod),
15191519
"const" | "constant" => Kind(DefKind::Const),
1520-
"static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }),
1520+
"static" => Kind(DefKind::Static {
1521+
mutability: Mutability::Not,
1522+
nested: false,
1523+
safety: Safety::Safe,
1524+
}),
15211525
"function" | "fn" | "method" => Kind(DefKind::Fn),
15221526
"derive" => Kind(DefKind::Macro(MacroKind::Derive)),
15231527
"type" => NS(Namespace::TypeNS),

Diff for: src/tools/clippy/clippy_utils/src/ast_utils.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -308,13 +308,15 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
308308
ty: lt,
309309
mutability: lm,
310310
expr: le,
311+
safety: ls,
311312
}),
312313
Static(box StaticItem {
313314
ty: rt,
314315
mutability: rm,
315316
expr: re,
317+
safety: rs,
316318
}),
317-
) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
319+
) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le, re),
318320
(
319321
Const(box ConstItem {
320322
defaultness: ld,
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
2-
--> $DIR/extern-items-unsafe.rs:11:5
2+
--> $DIR/extern-items-unsafe.rs:12:5
33
|
4-
LL | test1(i);
5-
| ^^^^^^^^ call to unsafe function
4+
LL | test1(TEST1);
5+
| ^^^^^^^^^^^^ call to unsafe function
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

9-
error: aborting due to 1 previous error
9+
error[E0133]: use of extern static is unsafe and requires unsafe function or block
10+
--> $DIR/extern-items-unsafe.rs:12:11
11+
|
12+
LL | test1(TEST1);
13+
| ^^^^^ use of extern static
14+
|
15+
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
16+
17+
error: aborting due to 2 previous errors
1018

1119
For more information about this error, try `rustc --explain E0133`.
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
2-
--> $DIR/extern-items-unsafe.rs:11:5
2+
--> $DIR/extern-items-unsafe.rs:12:5
33
|
4-
LL | test1(i);
5-
| ^^^^^^^^ call to unsafe function
4+
LL | test1(TEST1);
5+
| ^^^^^^^^^^^^ call to unsafe function
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

9-
error: aborting due to 1 previous error
9+
error[E0133]: use of extern static is unsafe and requires unsafe block
10+
--> $DIR/extern-items-unsafe.rs:12:11
11+
|
12+
LL | test1(TEST1);
13+
| ^^^^^ use of extern static
14+
|
15+
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
16+
17+
error: aborting due to 2 previous errors
1018

1119
For more information about this error, try `rustc --explain E0133`.

Diff for: tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44
//@[edition2024] compile-flags: -Zunstable-options
55

66
unsafe extern "C" {
7+
static TEST1: i32;
78
fn test1(i: i32);
89
}
910

10-
fn test2(i: i32) {
11-
test1(i);
11+
fn test2() {
12+
test1(TEST1);
1213
//~^ ERROR: call to unsafe function `test1` is unsafe
14+
//~| ERROR: use of extern static is unsafe
1315
}
1416

15-
fn test3(i: i32) {
17+
fn test3() {
1618
unsafe {
17-
test1(i);
19+
test1(TEST1);
1820
}
1921
}
2022

Diff for: tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
//@ check-pass
66

77
unsafe extern "C" {
8+
safe static TEST1: i32;
89
safe fn test1(i: i32);
910
}
1011

11-
fn test2(i: i32) {
12-
test1(i);
12+
fn test2() {
13+
test1(TEST1);
1314
}
1415

1516
fn main() {}

0 commit comments

Comments
 (0)