Skip to content

Commit 7d9ed2a

Browse files
authored
Rollup merge of #127921 - spastorino:stabilize-unsafe-extern-blocks, r=compiler-errors
Stabilize unsafe extern blocks (RFC 3484) # Stabilization report ## Summary This is a tracking issue for the RFC 3484: Unsafe Extern Blocks We are stabilizing `#![feature(unsafe_extern_blocks)]`, as described in [Unsafe Extern Blocks RFC 3484](rust-lang/rfcs#3484). This feature makes explicit that declaring an extern block is unsafe. Starting in Rust 2024, all extern blocks must be marked as unsafe. In all editions, items within unsafe extern blocks may be marked as safe to use. RFC: rust-lang/rfcs#3484 Tracking issue: #123743 ## What is stabilized ### Summary of stabilization We now need extern blocks to be marked as unsafe and items inside can also have safety modifiers (unsafe or safe), by default items with no modifiers are unsafe to offer easy migration without surprising results. ```rust unsafe extern { // sqrt (from libm) may be called with any `f64` pub safe fn sqrt(x: f64) -> f64; // strlen (from libc) requires a valid pointer, // so we mark it as being an unsafe fn pub unsafe fn strlen(p: *const c_char) -> usize; // this function doesn't say safe or unsafe, so it defaults to unsafe pub fn free(p: *mut core::ffi::c_void); pub safe static IMPORTANT_BYTES: [u8; 256]; pub safe static LINES: SyncUnsafeCell<i32>; } ``` ## Tests The relevant tests are in `tests/ui/rust-2024/unsafe-extern-blocks`. ## History - #124482 - #124455 - #125077 - #125522 - #126738 - #126749 - #126755 - #126757 - #126758 - #126756 - #126973 - #127535 - rust-lang/rustfmt#6204 ## Unresolved questions I am not aware of any unresolved questions.
2 parents edc4dc3 + 8366c7f commit 7d9ed2a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+85
-163
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+12-30
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,6 @@ impl<'a> AstValidator<'a> {
453453
item_span: span,
454454
block: Some(self.current_extern_span().shrink_to_lo()),
455455
});
456-
} else if !self.features.unsafe_extern_blocks {
457-
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
458-
item_span: span,
459-
block: None,
460-
});
461456
}
462457
}
463458
}
@@ -1054,32 +1049,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10541049
errors::VisibilityNotPermittedNote::IndividualForeignItems,
10551050
);
10561051

1057-
if this.features.unsafe_extern_blocks {
1058-
if &Safety::Default == safety {
1059-
if item.span.at_least_rust_2024() {
1060-
this.dcx()
1061-
.emit_err(errors::MissingUnsafeOnExtern { span: item.span });
1062-
} else {
1063-
this.lint_buffer.buffer_lint(
1064-
MISSING_UNSAFE_ON_EXTERN,
1065-
item.id,
1066-
item.span,
1067-
BuiltinLintDiag::MissingUnsafeOnExtern {
1068-
suggestion: item.span.shrink_to_lo(),
1069-
},
1070-
);
1071-
}
1052+
if &Safety::Default == safety {
1053+
if item.span.at_least_rust_2024() {
1054+
this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
1055+
} else {
1056+
this.lint_buffer.buffer_lint(
1057+
MISSING_UNSAFE_ON_EXTERN,
1058+
item.id,
1059+
item.span,
1060+
BuiltinLintDiag::MissingUnsafeOnExtern {
1061+
suggestion: item.span.shrink_to_lo(),
1062+
},
1063+
);
10721064
}
1073-
} else if let &Safety::Unsafe(span) = safety {
1074-
let mut diag = this
1075-
.dcx()
1076-
.create_err(errors::UnsafeItem { span, kind: "extern block" });
1077-
rustc_session::parse::add_feature_diagnostics(
1078-
&mut diag,
1079-
self.session,
1080-
sym::unsafe_extern_blocks,
1081-
);
1082-
diag.emit();
10831065
}
10841066

10851067
if abi.is_none() {

compiler/rustc_ast_passes/src/feature_gate.rs

-4
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
560560
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
561561
gate_all!(global_registration, "global registration is experimental");
562562
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
563-
gate_all!(
564-
unsafe_extern_blocks,
565-
"`unsafe extern {}` blocks and `safe` keyword are experimental"
566-
);
567563
gate_all!(return_type_notation, "return type notation is experimental");
568564

569565
if !visitor.features.never_patterns {

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ declare_features! (
390390
(accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
391391
/// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
392392
(accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
393+
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
394+
(accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
393395
/// Allows importing and reexporting macros with `use`,
394396
/// enables macro modularization in general.
395397
(accepted, use_extern_macros, "1.30.0", Some(35896)),

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,6 @@ declare_features! (
631631
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
632632
/// Allows unsafe attributes.
633633
(unstable, unsafe_attributes, "1.80.0", Some(123757)),
634-
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
635-
(unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
636634
/// Allows const generic parameters to be defined with types that
637635
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
638636
(incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),

compiler/rustc_lint_defs/src/builtin.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4934,7 +4934,6 @@ declare_lint! {
49344934
/// ### Example
49354935
///
49364936
/// ```rust
4937-
/// #![feature(unsafe_extern_blocks)]
49384937
/// #![warn(missing_unsafe_on_extern)]
49394938
/// #![allow(dead_code)]
49404939
///

compiler/rustc_parse/src/parser/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1250,9 +1250,6 @@ impl<'a> Parser<'a> {
12501250
if self.eat_keyword_case(kw::Unsafe, case) {
12511251
Safety::Unsafe(self.prev_token.uninterpolated_span())
12521252
} else if self.eat_keyword_case(kw::Safe, case) {
1253-
self.psess
1254-
.gated_spans
1255-
.gate(sym::unsafe_extern_blocks, self.prev_token.uninterpolated_span());
12561253
Safety::Safe(self.prev_token.uninterpolated_span())
12571254
} else {
12581255
Safety::Default

tests/rustdoc/unsafe-extern-blocks.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Test to ensure the feature is working as expected.
22

3-
#![feature(unsafe_extern_blocks)]
43
#![crate_name = "foo"]
54

65
// @has 'foo/index.html'
@@ -13,7 +12,7 @@
1312
// @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1
1413
// @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠'
1514

16-
unsafe extern {
15+
unsafe extern "C" {
1716
// @has 'foo/static.FOO.html'
1817
// @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32'
1918
pub safe static FOO: i32;

tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs

-13
This file was deleted.

tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr

-23
This file was deleted.

tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(unsafe_extern_blocks)]
21
#![deny(unsafe_code)]
32

43
#[allow(unsafe_code)]

tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: usage of an `unsafe extern` block
2-
--> $DIR/unsafe-extern-blocks.rs:9:1
2+
--> $DIR/unsafe-extern-blocks.rs:8:1
33
|
44
LL | / unsafe extern "C" {
55
LL | |
@@ -8,7 +8,7 @@ LL | | }
88
| |_^
99
|
1010
note: the lint level is defined here
11-
--> $DIR/unsafe-extern-blocks.rs:2:9
11+
--> $DIR/unsafe-extern-blocks.rs:1:9
1212
|
1313
LL | #![deny(unsafe_code)]
1414
| ^^^^^^^^^^^
-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
extern "C" unsafe {
22
//~^ ERROR expected `{`, found keyword `unsafe`
3-
//~| ERROR extern block cannot be declared unsafe
43
unsafe fn foo();
5-
//~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
64
}
75

86
fn main() {}

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

+1-17
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,5 @@ error: expected `{`, found keyword `unsafe`
44
LL | extern "C" unsafe {
55
| ^^^^^^ expected `{`
66

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-
= note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
14-
= help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
15-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
16-
17-
error: items in unadorned `extern` blocks cannot have safety qualifiers
18-
--> $DIR/unsafe-foreign-mod-2.rs:4:5
19-
|
20-
LL | unsafe fn foo();
21-
| ^^^^^^^^^^^^^^^^
22-
23-
error: aborting due to 3 previous errors
7+
error: aborting due to 1 previous error
248

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
unsafe extern "C" {
2-
//~^ ERROR extern block cannot be declared unsafe
3-
}
1+
//@ check-pass
2+
3+
unsafe extern "C" {}
44

55
fn main() {}

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

-12
This file was deleted.

tests/ui/rust-2024/safe-outside-extern.rs

-8
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
1-
//@ revisions: gated ungated
2-
#![cfg_attr(gated, feature(unsafe_extern_blocks))]
3-
41
safe fn foo() {}
52
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
6-
//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
73

84
safe static FOO: i32 = 1;
95
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
10-
//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
116

127
trait Foo {
138
safe fn foo();
149
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
15-
//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
1610
}
1711

1812
impl Foo for () {
1913
safe fn foo() {}
2014
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
21-
//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
2215
}
2316

2417
type FnPtr = safe fn(i32, i32) -> i32;
2518
//~^ ERROR: function pointers cannot be declared with `safe` safety qualifier
26-
//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
2719

2820
unsafe static LOL: u8 = 0;
2921
//~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
2+
--> $DIR/safe-outside-extern.rs:1:1
3+
|
4+
LL | safe fn foo() {}
5+
| ^^^^^^^^^^^^^^^^
6+
7+
error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
8+
--> $DIR/safe-outside-extern.rs:4:1
9+
|
10+
LL | safe static FOO: i32 = 1;
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
14+
--> $DIR/safe-outside-extern.rs:8:5
15+
|
16+
LL | safe fn foo();
17+
| ^^^^^^^^^^^^^^
18+
19+
error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
20+
--> $DIR/safe-outside-extern.rs:13:5
21+
|
22+
LL | safe fn foo() {}
23+
| ^^^^^^^^^^^^^^^^
24+
25+
error: function pointers cannot be declared with `safe` safety qualifier
26+
--> $DIR/safe-outside-extern.rs:17:14
27+
|
28+
LL | type FnPtr = safe fn(i32, i32) -> i32;
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
32+
--> $DIR/safe-outside-extern.rs:20:1
33+
|
34+
LL | unsafe static LOL: u8 = 0;
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
37+
error: aborting due to 6 previous errors
38+

tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
2-
--> $DIR/extern-items-unsafe.rs:14:5
2+
--> $DIR/extern-items-unsafe.rs:12:5
33
|
44
LL | test1(TEST1);
55
| ^^^^^^^^^^^^ call to unsafe function
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

99
error[E0133]: use of extern static is unsafe and requires unsafe function or block
10-
--> $DIR/extern-items-unsafe.rs:14:11
10+
--> $DIR/extern-items-unsafe.rs:12:11
1111
|
1212
LL | test1(TEST1);
1313
| ^^^^^ use of extern static

tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr

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

99
error[E0133]: use of extern static is unsafe and requires unsafe block
10-
--> $DIR/extern-items-unsafe.rs:14:11
10+
--> $DIR/extern-items-unsafe.rs:12:11
1111
|
1212
LL | test1(TEST1);
1313
| ^^^^^ use of extern static

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

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
//@[edition2024] edition:2024
44
//@[edition2024] compile-flags: -Zunstable-options
55

6-
#![feature(unsafe_extern_blocks)]
7-
86
unsafe extern "C" {
97
static TEST1: i32;
108
fn test1(i: i32);

tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: extern blocks must be unsafe
2-
--> $DIR/extern-items.rs:9:1
2+
--> $DIR/extern-items.rs:7:1
33
|
44
LL | / extern "C" {
55
LL | |

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

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
//@[edition2024] edition:2024
55
//@[edition2024] compile-flags: -Zunstable-options
66

7-
#![feature(unsafe_extern_blocks)]
8-
97
extern "C" {
108
//[edition2024]~^ ERROR extern blocks must be unsafe
119
static TEST1: i32;

tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//@ revisions: gated ungated
2-
#![cfg_attr(gated, feature(unsafe_extern_blocks))]
3-
41
trait Bar {}
52
safe impl Bar for () { }
63
//~^ ERROR expected one of `!` or `::`, found keyword `impl`

tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: expected one of `!` or `::`, found keyword `impl`
2-
--> $DIR/safe-impl-trait.rs:5:6
2+
--> $DIR/safe-impl-trait.rs:2:6
33
|
44
LL | safe impl Bar for () { }
55
| ^^^^ expected one of `!` or `::`

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

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
//@[edition2024] compile-flags: -Zunstable-options
55
//@ check-pass
66

7-
#![feature(unsafe_extern_blocks)]
8-
97
unsafe extern "C" {
108
safe static TEST1: i32;
119
safe fn test1(i: i32);

tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//@ revisions: gated ungated
2-
#![cfg_attr(gated, feature(unsafe_extern_blocks))]
3-
41
safe trait Foo {}
52
//~^ ERROR expected one of `!` or `::`, found keyword `trait`
63

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected one of `!` or `::`, found keyword `trait`
2+
--> $DIR/safe-trait.rs:1:6
3+
|
4+
LL | safe trait Foo {}
5+
| ^^^^^ expected one of `!` or `::`
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)