Skip to content

Commit 2bc8069

Browse files
committed
Make extern blocks without unsafe warn in edition < 2024 and fail afterwards
1 parent 7fd3368 commit 2bc8069

File tree

11 files changed

+57
-4
lines changed

11 files changed

+57
-4
lines changed

.gitmodules

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
shallow = true
2121
[submodule "library/stdarch"]
2222
path = library/stdarch
23-
url = https://github.com/rust-lang/stdarch.git
23+
url = https://github.com/spastorino/stdarch.git
2424
shallow = true
2525
[submodule "src/doc/rustc-dev-guide"]
2626
path = src/doc/rustc-dev-guide

compiler/rustc_ast_passes/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii ide
7676
7777
ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
7878
79+
ast_passes_extern_missing_unsafe = extern blocks should be unsafe
80+
7981
ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
8082
.suggestion = remove the {$remove_descr}
8183
.label = `extern` block begins here

compiler/rustc_ast_passes/src/ast_validation.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use rustc_data_structures::fx::FxIndexMap;
1515
use rustc_feature::Features;
1616
use rustc_parse::validate_attr;
1717
use rustc_session::lint::builtin::{
18-
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
18+
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
19+
PATTERNS_IN_FNS_WITHOUT_BODY,
1920
};
2021
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
2122
use rustc_session::Session;
@@ -1021,12 +1022,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10211022
walk_list!(self, visit_attribute, &item.attrs);
10221023
return; // Avoid visiting again.
10231024
}
1024-
ItemKind::ForeignMod(ForeignMod { abi, .. }) => {
1025+
ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => {
10251026
let old_item = mem::replace(&mut self.extern_mod, Some(item));
10261027
self.visibility_not_permitted(
10271028
&item.vis,
10281029
errors::VisibilityNotPermittedNote::IndividualForeignItems,
10291030
);
1031+
1032+
if &Unsafe::No == unsafety {
1033+
self.lint_buffer.buffer_lint_with_diagnostic(
1034+
MISSING_UNSAFE_ON_EXTERN,
1035+
item.id,
1036+
item.span,
1037+
fluent::ast_passes_extern_missing_unsafe,
1038+
BuiltinLintDiag::Normal,
1039+
);
1040+
}
1041+
10301042
if abi.is_none() {
10311043
self.maybe_lint_missing_abi(item.span, item.id);
10321044
}

compiler/rustc_lint_defs/src/builtin.rs

+29
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ declare_lint_pass! {
6767
META_VARIABLE_MISUSE,
6868
MISSING_ABI,
6969
MISSING_FRAGMENT_SPECIFIER,
70+
MISSING_UNSAFE_ON_EXTERN,
7071
MUST_NOT_SUSPEND,
7172
NAMED_ARGUMENTS_USED_POSITIONALLY,
7273
NON_CONTIGUOUS_RANGE_ENDPOINTS,
@@ -4741,3 +4742,31 @@ declare_lint! {
47414742
};
47424743
crate_level_only
47434744
}
4745+
4746+
declare_lint! {
4747+
/// The `missing_unsafe_on_extern` lint detects missing unsafe keyword on extern declarations.
4748+
///
4749+
/// ### Example
4750+
///
4751+
/// ```rust
4752+
/// extern "C" {
4753+
/// fn foo(_: i32);
4754+
/// }
4755+
/// ```
4756+
///
4757+
/// {{produces}}
4758+
///
4759+
/// ### Explanation
4760+
///
4761+
/// Declaring extern items, even without ever using them, can cause Undefined Behavior. We
4762+
/// should consider all sources of Undefined Behavior to be unsafe.
4763+
///
4764+
/// This is a [future-incompatible] lint to transition this to a
4765+
/// hard error in the future.
4766+
///
4767+
/// [future-incompatible]: ../index.md#future-incompatible-lints
4768+
pub MISSING_UNSAFE_ON_EXTERN,
4769+
Warn,
4770+
"detects missing unsafe keyword on extern declarations",
4771+
@edition Edition2024 => Deny;
4772+
}

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
//
9191
// Library features:
9292
// tidy-alphabetical-start
93+
#![cfg_attr(not(bootstrap), allow(missing_unsafe_on_extern))]
9394
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
9495
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
9596
#![cfg_attr(test, feature(is_sorted))]

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
#![allow(incomplete_features)]
104104
#![warn(multiple_supertrait_upcastable)]
105105
#![allow(internal_features)]
106+
#![cfg_attr(not(bootstrap), allow(missing_unsafe_on_extern))]
106107
#![deny(ffi_unwind_calls)]
107108
// Do not check link redundancy on bootstraping phase
108109
#![allow(rustdoc::redundant_explicit_links)]

library/panic_unwind/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
// `real_imp` is unused with Miri, so silence warnings.
2929
#![cfg_attr(miri, allow(dead_code))]
3030
#![allow(internal_features)]
31+
#![allow(unknown_lints)]
32+
#![allow(missing_unsafe_on_extern)]
3133

3234
use alloc::boxed::Box;
3335
use core::any::Any;

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@
247247
#![warn(deprecated_in_future)]
248248
#![warn(missing_docs)]
249249
#![warn(missing_debug_implementations)]
250+
#![cfg_attr(not(bootstrap), allow(missing_unsafe_on_extern))]
250251
#![allow(explicit_outlives_requirements)]
251252
#![allow(unused_lifetimes)]
252253
#![allow(internal_features)]

library/unwind/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
feature(link_llvm_intrinsics)
1212
)]
1313
#![allow(internal_features)]
14+
#![allow(unknown_lints)]
15+
#![allow(missing_unsafe_on_extern)]
1416

1517
// Force libc to be included even if unused. This is required by many platforms.
1618
#[cfg(not(all(windows, target_env = "msvc")))]

src/tools/compiletest/src/runtest.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2625,6 +2625,9 @@ impl<'test> TestCx<'test> {
26252625
rustc.args(&["-A", "unused"]);
26262626
}
26272627

2628+
// FIXME: add unsafe to all extern blocks in tests
2629+
rustc.args(&["-A", "missing_unsafe_on_extern"]);
2630+
26282631
// Allow tests to use internal features.
26292632
rustc.args(&["-A", "internal_features"]);
26302633

0 commit comments

Comments
 (0)