Skip to content

Commit 0380321

Browse files
committed
Add unsafe_extern_blocks feature flag
1 parent bac72cf commit 0380321

21 files changed

+93
-37
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -440,16 +440,14 @@ impl<'a> AstValidator<'a> {
440440
}
441441

442442
fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) {
443-
match safety {
444-
Safety::Unsafe(_) | Safety::Safe(_)
445-
if self.extern_mod_safety == Some(Safety::Default) =>
446-
{
447-
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
448-
item_span,
449-
block: self.current_extern_span(),
450-
});
451-
}
452-
_ => {}
443+
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
444+
&& (self.extern_mod_safety == Some(Safety::Default)
445+
|| !self.features.unsafe_extern_blocks)
446+
{
447+
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
448+
item_span,
449+
block: self.current_extern_span(),
450+
});
453451
}
454452
}
455453

@@ -1044,13 +1042,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10441042
errors::VisibilityNotPermittedNote::IndividualForeignItems,
10451043
);
10461044

1047-
if &Safety::Default == safety {
1048-
this.lint_buffer.buffer_lint(
1049-
MISSING_UNSAFE_ON_EXTERN,
1050-
item.id,
1051-
item.span,
1052-
BuiltinLintDiag::MissingUnsafeOnExtern,
1053-
);
1045+
if this.features.unsafe_extern_blocks {
1046+
if &Safety::Default == safety {
1047+
this.lint_buffer.buffer_lint(
1048+
MISSING_UNSAFE_ON_EXTERN,
1049+
item.id,
1050+
item.span,
1051+
BuiltinLintDiag::MissingUnsafeOnExtern,
1052+
);
1053+
}
1054+
} else if let &Safety::Unsafe(span) = safety {
1055+
this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
10541056
}
10551057

10561058
if abi.is_none() {

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,8 @@ declare_features! (
624624
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
625625
/// Allows unnamed fields of struct and union type
626626
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
627+
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
628+
(unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
627629
/// Allows unsized fn parameters.
628630
(unstable, unsized_fn_params, "1.49.0", Some(48055)),
629631
/// Allows unsized rvalues at arguments and parameters.

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4858,7 +4858,10 @@ declare_lint! {
48584858
///
48594859
/// ### Example
48604860
///
4861-
/// ```rust,edition2024
4861+
/// ```rust,edition2024,ignore
4862+
/// #![feature(unsafe_extern_blocks)]
4863+
/// #![allow(dead_code)]
4864+
///
48624865
/// extern "C" {
48634866
/// fn foo(_: i32);
48644867
/// }
@@ -4880,5 +4883,5 @@ declare_lint! {
48804883
pub MISSING_UNSAFE_ON_EXTERN,
48814884
Allow,
48824885
"detects missing unsafe keyword on extern declarations",
4883-
@edition Edition2024 => Warn;
4886+
@edition Edition2024 => Deny;
48844887
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,7 @@ symbols! {
19651965
unsafe_block_in_unsafe_fn,
19661966
unsafe_cell,
19671967
unsafe_cell_raw_get,
1968+
unsafe_extern_blocks,
19681969
unsafe_no_drop_flag,
19691970
unsafe_pin_internals,
19701971
unsize,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
unsafe extern "C" {
2+
//~^ ERROR extern block cannot be declared unsafe
3+
}
4+
5+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: extern block cannot be declared unsafe
2+
--> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1
3+
|
4+
LL | unsafe extern "C" {
5+
| ^^^^^^
6+
7+
error: aborting due to 1 previous error
8+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
extern "C" unsafe {
22
//~^ ERROR expected `{`, found keyword `unsafe`
3+
//~| ERROR extern block cannot be declared unsafe
34
unsafe fn foo();
5+
//~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
46
}
57

68
fn main() {}

tests/ui/parser/unsafe-foreign-mod-2.stderr

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,20 @@ error: expected `{`, found keyword `unsafe`
44
LL | extern "C" unsafe {
55
| ^^^^^^ expected `{`
66

7-
error: aborting due to 1 previous error
7+
error: extern block cannot be declared unsafe
8+
--> $DIR/unsafe-foreign-mod-2.rs:1:12
9+
|
10+
LL | extern "C" unsafe {
11+
| ^^^^^^
12+
13+
error: items in unadorned `extern` blocks cannot have safety qualifiers
14+
--> $DIR/unsafe-foreign-mod-2.rs:4:5
15+
|
16+
LL | extern "C" unsafe {
17+
| ----------------- help: add unsafe to this `extern` block
18+
...
19+
LL | unsafe fn foo();
20+
| ^^^^^^^^^^^^^^^^
21+
22+
error: aborting due to 3 previous errors
823

tests/ui/parser/unsafe-foreign-mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//@ build-pass
2-
3-
unsafe extern "C" {}
1+
unsafe extern "C" {
2+
//~^ ERROR extern block cannot be declared unsafe
3+
}
44

55
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: extern block cannot be declared unsafe
2+
--> $DIR/unsafe-foreign-mod.rs:1:1
3+
|
4+
LL | unsafe extern "C" {
5+
| ^^^^^^
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)