Skip to content

Commit 2eb0858

Browse files
authored
Unrolled build for rust-lang#139718
Rollup merge of rust-lang#139718 - folkertdev:unsafe-attributes-earlier-editions, r=fmease enforce unsafe attributes in pre-2024 editions by default New unsafe attributes should emit an error when used without the `unsafe(...)` in all editions. The `no_mangle`, `link_section` and `export_name` attributes are exceptions, and can still be used without an unsafe in earlier editions. The only attributes for which this change is relevant right now are `#[ffi_const]` and `#[ffi_pure]`. This change is required for making `#[unsafe(naked)]` sound in pre-2024 editions.
2 parents f836ae4 + f472cc8 commit 2eb0858

17 files changed

+102
-52
lines changed

Diff for: compiler/rustc_error_codes/src/error_codes/E0755.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Erroneous code example:
55
```compile_fail,E0755
66
#![feature(ffi_pure)]
77
8-
#[ffi_pure] // error!
8+
#[unsafe(ffi_pure)] // error!
99
pub fn foo() {}
1010
# fn main() {}
1111
```
@@ -17,7 +17,7 @@ side effects or infinite loops:
1717
#![feature(ffi_pure)]
1818
1919
extern "C" {
20-
#[ffi_pure] // ok!
20+
#[unsafe(ffi_pure)] // ok!
2121
pub fn strlen(s: *const i8) -> isize;
2222
}
2323
# fn main() {}

Diff for: compiler/rustc_error_codes/src/error_codes/E0756.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Erroneous code example:
66
```compile_fail,E0756
77
#![feature(ffi_const)]
88
9-
#[ffi_const] // error!
9+
#[unsafe(ffi_const)] // error!
1010
pub fn foo() {}
1111
# fn main() {}
1212
```
@@ -18,7 +18,7 @@ which have no side effects except for their return value:
1818
#![feature(ffi_const)]
1919
2020
extern "C" {
21-
#[ffi_const] // ok!
21+
#[unsafe(ffi_const)] // ok!
2222
pub fn strlen(s: *const i8) -> i32;
2323
}
2424
# fn main() {}

Diff for: compiler/rustc_error_codes/src/error_codes/E0757.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ Erroneous code example:
66
#![feature(ffi_const, ffi_pure)]
77
88
extern "C" {
9-
#[ffi_const]
10-
#[ffi_pure] // error: `#[ffi_const]` function cannot be `#[ffi_pure]`
9+
#[unsafe(ffi_const)]
10+
#[unsafe(ffi_pure)]
11+
//~^ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
1112
pub fn square(num: i32) -> i32;
1213
}
1314
```
@@ -19,7 +20,7 @@ As `ffi_const` provides stronger guarantees than `ffi_pure`, remove the
1920
#![feature(ffi_const)]
2021
2122
extern "C" {
22-
#[ffi_const]
23+
#[unsafe(ffi_const)]
2324
pub fn square(num: i32) -> i32;
2425
}
2526
```

Diff for: compiler/rustc_feature/src/builtin_attrs.rs

+24-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use AttributeDuplicates::*;
66
use AttributeGate::*;
77
use AttributeType::*;
88
use rustc_data_structures::fx::FxHashMap;
9+
use rustc_span::edition::Edition;
910
use rustc_span::{Symbol, sym};
1011

1112
use crate::{Features, Stability};
@@ -65,9 +66,12 @@ pub enum AttributeSafety {
6566
/// Normal attribute that does not need `#[unsafe(...)]`
6667
Normal,
6768

68-
/// Unsafe attribute that requires safety obligations
69-
/// to be discharged
70-
Unsafe,
69+
/// Unsafe attribute that requires safety obligations to be discharged.
70+
///
71+
/// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition
72+
/// is less than the one stored in `unsafe_since`. This handles attributes that were safe in
73+
/// earlier editions, but become unsafe in later ones.
74+
Unsafe { unsafe_since: Option<Edition> },
7175
}
7276

7377
#[derive(Clone, Copy)]
@@ -187,12 +191,23 @@ macro_rules! template {
187191
}
188192

189193
macro_rules! ungated {
194+
(unsafe($edition:ident) $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
195+
BuiltinAttribute {
196+
name: sym::$attr,
197+
encode_cross_crate: $encode_cross_crate,
198+
type_: $typ,
199+
safety: AttributeSafety::Unsafe { unsafe_since: Some(Edition::$edition) },
200+
template: $tpl,
201+
gate: Ungated,
202+
duplicates: $duplicates,
203+
}
204+
};
190205
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
191206
BuiltinAttribute {
192207
name: sym::$attr,
193208
encode_cross_crate: $encode_cross_crate,
194209
type_: $typ,
195-
safety: AttributeSafety::Unsafe,
210+
safety: AttributeSafety::Unsafe { unsafe_since: None },
196211
template: $tpl,
197212
gate: Ungated,
198213
duplicates: $duplicates,
@@ -217,7 +232,7 @@ macro_rules! gated {
217232
name: sym::$attr,
218233
encode_cross_crate: $encode_cross_crate,
219234
type_: $typ,
220-
safety: AttributeSafety::Unsafe,
235+
safety: AttributeSafety::Unsafe { unsafe_since: None },
221236
template: $tpl,
222237
duplicates: $duplicates,
223238
gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate),
@@ -228,7 +243,7 @@ macro_rules! gated {
228243
name: sym::$attr,
229244
encode_cross_crate: $encode_cross_crate,
230245
type_: $typ,
231-
safety: AttributeSafety::Unsafe,
246+
safety: AttributeSafety::Unsafe { unsafe_since: None },
232247
template: $tpl,
233248
duplicates: $duplicates,
234249
gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr),
@@ -423,9 +438,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
423438
),
424439
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
425440
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
426-
ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
427-
ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
428-
ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
441+
ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
442+
ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
443+
ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
429444
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
430445
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
431446

Diff for: compiler/rustc_parse/src/validate_attr.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
157157
pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) {
158158
let attr_item = attr.get_normal_item();
159159

160-
if safety == AttributeSafety::Unsafe {
160+
if let AttributeSafety::Unsafe { unsafe_since } = safety {
161161
if let ast::Safety::Default = attr_item.unsafety {
162162
let path_span = attr_item.path.span;
163163

@@ -167,7 +167,13 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr:
167167
// square bracket respectively.
168168
let diag_span = attr_item.span();
169169

170-
if attr.span.at_least_rust_2024() {
170+
// Attributes can be safe in earlier editions, and become unsafe in later ones.
171+
let emit_error = match unsafe_since {
172+
None => true,
173+
Some(unsafe_since) => attr.span.edition() >= unsafe_since,
174+
};
175+
176+
if emit_error {
171177
psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
172178
span: path_span,
173179
suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {

Diff for: tests/codegen/cffi/ffi-const.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ extern "C" {
1010
// CHECK-LABEL: declare{{.*}}void @foo()
1111
// CHECK-SAME: [[ATTRS:#[0-9]+]]
1212
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(none){{.*}} }
13-
#[ffi_const]
13+
#[unsafe(ffi_const)]
1414
pub fn foo();
1515
}

Diff for: tests/codegen/cffi/ffi-pure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ extern "C" {
1010
// CHECK-LABEL: declare{{.*}}void @foo()
1111
// CHECK-SAME: [[ATTRS:#[0-9]+]]
1212
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(read){{.*}} }
13-
#[ffi_pure]
13+
#[unsafe(ffi_pure)]
1414
pub fn foo();
1515
}

Diff for: tests/ui/feature-gates/feature-gate-ffi_const.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![crate_type = "lib"]
22

33
extern "C" {
4-
#[ffi_const] //~ ERROR the `#[ffi_const]` attribute is an experimental feature
4+
#[unsafe(ffi_const)] //~ ERROR the `#[ffi_const]` attribute is an experimental feature
55
pub fn foo();
66
}

Diff for: tests/ui/feature-gates/feature-gate-ffi_const.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0658]: the `#[ffi_const]` attribute is an experimental feature
22
--> $DIR/feature-gate-ffi_const.rs:4:5
33
|
4-
LL | #[ffi_const]
5-
| ^^^^^^^^^^^^
4+
LL | #[unsafe(ffi_const)]
5+
| ^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: see issue #58328 <https://github.com/rust-lang/rust/issues/58328> for more information
88
= help: add `#![feature(ffi_const)]` to the crate attributes to enable

Diff for: tests/ui/feature-gates/feature-gate-ffi_pure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![crate_type = "lib"]
22

33
extern "C" {
4-
#[ffi_pure] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature
4+
#[unsafe(ffi_pure)] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature
55
pub fn foo();
66
}

Diff for: tests/ui/feature-gates/feature-gate-ffi_pure.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0658]: the `#[ffi_pure]` attribute is an experimental feature
22
--> $DIR/feature-gate-ffi_pure.rs:4:5
33
|
4-
LL | #[ffi_pure]
5-
| ^^^^^^^^^^^
4+
LL | #[unsafe(ffi_pure)]
5+
| ^^^^^^^^^^^^^^^^^^^
66
|
77
= note: see issue #58329 <https://github.com/rust-lang/rust/issues/58329> for more information
88
= help: add `#![feature(ffi_pure)]` to the crate attributes to enable

Diff for: tests/ui/ffi-attrs/ffi_const.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
#![feature(ffi_const)]
22
#![crate_type = "lib"]
33

4-
#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
4+
#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
55
pub fn foo() {}
66

7-
#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
7+
#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
88
macro_rules! bar {
9-
() => ()
9+
() => {};
1010
}
1111

1212
extern "C" {
13-
#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
13+
#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
1414
static INT: i32;
15+
16+
#[ffi_const] //~ ERROR unsafe attribute used without unsafe
17+
fn bar();
1518
}

Diff for: tests/ui/ffi-attrs/ffi_const.stderr

+18-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
1+
error: unsafe attribute used without unsafe
2+
--> $DIR/ffi_const.rs:16:7
3+
|
4+
LL | #[ffi_const]
5+
| ^^^^^^^^^ usage of unsafe attribute
6+
|
7+
help: wrap the attribute in `unsafe(...)`
8+
|
9+
LL | #[unsafe(ffi_const)]
10+
| +++++++ +
11+
112
error[E0756]: `#[ffi_const]` may only be used on foreign functions
213
--> $DIR/ffi_const.rs:4:1
314
|
4-
LL | #[ffi_const]
5-
| ^^^^^^^^^^^^
15+
LL | #[unsafe(ffi_const)]
16+
| ^^^^^^^^^^^^^^^^^^^^
617

718
error[E0756]: `#[ffi_const]` may only be used on foreign functions
819
--> $DIR/ffi_const.rs:7:1
920
|
10-
LL | #[ffi_const]
11-
| ^^^^^^^^^^^^
21+
LL | #[unsafe(ffi_const)]
22+
| ^^^^^^^^^^^^^^^^^^^^
1223

1324
error[E0756]: `#[ffi_const]` may only be used on foreign functions
1425
--> $DIR/ffi_const.rs:13:5
1526
|
16-
LL | #[ffi_const]
17-
| ^^^^^^^^^^^^
27+
LL | #[unsafe(ffi_const)]
28+
| ^^^^^^^^^^^^^^^^^^^^
1829

19-
error: aborting due to 3 previous errors
30+
error: aborting due to 4 previous errors
2031

2132
For more information about this error, try `rustc --explain E0756`.

Diff for: tests/ui/ffi-attrs/ffi_const2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![feature(ffi_const, ffi_pure)]
22

33
extern "C" {
4-
#[ffi_pure] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
5-
#[ffi_const]
4+
#[unsafe(ffi_pure)] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
5+
#[unsafe(ffi_const)]
66
pub fn baz();
77
}
88

Diff for: tests/ui/ffi-attrs/ffi_const2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0757]: `#[ffi_const]` function cannot be `#[ffi_pure]`
22
--> $DIR/ffi_const2.rs:4:5
33
|
4-
LL | #[ffi_pure]
5-
| ^^^^^^^^^^^
4+
LL | #[unsafe(ffi_pure)]
5+
| ^^^^^^^^^^^^^^^^^^^
66

77
error: aborting due to 1 previous error
88

Diff for: tests/ui/ffi-attrs/ffi_pure.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
#![feature(ffi_pure)]
22
#![crate_type = "lib"]
33

4-
#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
4+
#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
55
pub fn foo() {}
66

7-
#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
7+
#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
88
macro_rules! bar {
9-
() => ()
9+
() => {};
1010
}
1111

1212
extern "C" {
13-
#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
13+
#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
1414
static INT: i32;
15+
16+
#[ffi_pure] //~ ERROR unsafe attribute used without unsafe
17+
fn bar();
1518
}

Diff for: tests/ui/ffi-attrs/ffi_pure.stderr

+18-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
1+
error: unsafe attribute used without unsafe
2+
--> $DIR/ffi_pure.rs:16:7
3+
|
4+
LL | #[ffi_pure]
5+
| ^^^^^^^^ usage of unsafe attribute
6+
|
7+
help: wrap the attribute in `unsafe(...)`
8+
|
9+
LL | #[unsafe(ffi_pure)]
10+
| +++++++ +
11+
112
error[E0755]: `#[ffi_pure]` may only be used on foreign functions
213
--> $DIR/ffi_pure.rs:4:1
314
|
4-
LL | #[ffi_pure]
5-
| ^^^^^^^^^^^
15+
LL | #[unsafe(ffi_pure)]
16+
| ^^^^^^^^^^^^^^^^^^^
617

718
error[E0755]: `#[ffi_pure]` may only be used on foreign functions
819
--> $DIR/ffi_pure.rs:7:1
920
|
10-
LL | #[ffi_pure]
11-
| ^^^^^^^^^^^
21+
LL | #[unsafe(ffi_pure)]
22+
| ^^^^^^^^^^^^^^^^^^^
1223

1324
error[E0755]: `#[ffi_pure]` may only be used on foreign functions
1425
--> $DIR/ffi_pure.rs:13:5
1526
|
16-
LL | #[ffi_pure]
17-
| ^^^^^^^^^^^
27+
LL | #[unsafe(ffi_pure)]
28+
| ^^^^^^^^^^^^^^^^^^^
1829

19-
error: aborting due to 3 previous errors
30+
error: aborting due to 4 previous errors
2031

2132
For more information about this error, try `rustc --explain E0755`.

0 commit comments

Comments
 (0)