diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 2626631d80047..594ce0c4aa97b 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -67,6 +67,9 @@ ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have quali .label = in this `extern` block .suggestion = remove this qualifier +ast_passes_item_invalid_safety = items cannot be declared with `safe` safety qualifier + .suggestion = remove safe to this item + ast_passes_extern_invalid_safety = items in unadorned `extern` blocks cannot have safety qualifiers .suggestion = add unsafe to this `extern` block diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b274a9b9114ac..a8df1173935b0 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -456,6 +456,12 @@ impl<'a> AstValidator<'a> { } } + fn check_item_safety(&self, span: Span, safety: Safety) { + if matches!(safety, Safety::Safe(_)) { + self.dcx().emit_err(errors::InvalidSafetyOnItem { span }); + } + } + fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) { if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) && (self.extern_mod_safety == Some(Safety::Default) @@ -1015,6 +1021,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { self.check_defaultness(item.span, *defaultness); + self.check_item_safety(item.span, sig.header.safety); if body.is_none() { self.dcx().emit_err(errors::FnWithoutBody { @@ -1174,11 +1181,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } } - ItemKind::Static(box StaticItem { expr: None, .. }) => { - self.dcx().emit_err(errors::StaticWithoutBody { - span: item.span, - replace_span: self.ending_semi_or_hi(item.span), - }); + ItemKind::Static(box StaticItem { expr, safety, .. }) => { + self.check_item_safety(item.span, *safety); + + if expr.is_none() { + self.dcx().emit_err(errors::StaticWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } ItemKind::TyAlias( ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. }, diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 601910ded208e..59d85d4840ceb 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -225,6 +225,13 @@ pub struct InvalidSafetyOnExtern { pub block: Span, } +#[derive(Diagnostic)] +#[diag(ast_passes_item_invalid_safety)] +pub struct InvalidSafetyOnItem { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(ast_passes_bound_in_context)] pub struct BoundInContext<'a> { diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs new file mode 100644 index 0000000000000..a501ca8407ee0 --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.rs @@ -0,0 +1,7 @@ +safe fn foo() {} +//~^ ERROR: items cannot be declared with `safe` safety qualifier + +safe static FOO: i32 = 1; +//~^ ERROR: items cannot be declared with `safe` safety qualifier + +fn main() {} diff --git a/tests/ui/rust-2024/safe-outside-extern.stderr b/tests/ui/rust-2024/safe-outside-extern.stderr new file mode 100644 index 0000000000000..26d4afe624896 --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.stderr @@ -0,0 +1,14 @@ +error: items cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:1:1 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: items cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:4:1 + | +LL | safe static FOO: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors +