Skip to content

Commit fedb839

Browse files
committed
Auto merge of rust-lang#116773 - dtolnay:validatestable, r=compiler-errors
Validate `feature` and `since` values inside `#[stable(…)]` Previously the string passed to `#[unstable(feature = "...")]` would be validated as an identifier, but not `#[stable(feature = "...")]`. In the standard library there were `stable` attributes containing the empty string, and kebab-case string, neither of which should be allowed. Pre-existing validation of `unstable`: ```rust // src/lib.rs #![allow(internal_features)] #![feature(staged_api)] #![unstable(feature = "kebab-case", issue = "none")] #[unstable(feature = "kebab-case", issue = "none")] pub struct Struct; ``` ```console error[E0546]: 'feature' is not an identifier --> src/lib.rs:5:1 | 5 | #![unstable(feature = "kebab-case", issue = "none")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` For an `unstable` attribute, the need for an identifier is obvious because the downstream code needs to write a `#![feature(...)]` attribute containing that identifier. `#![feature(kebab-case)]` is not valid syntax and `#![feature(kebab_case)]` would not work if that is not the name of the feature. Having a valid identifier even in `stable` is less essential but still useful because it allows for informative diagnostic about the stabilization of a feature. Compare: ```rust // src/lib.rs #![allow(internal_features)] #![feature(staged_api)] #![stable(feature = "kebab-case", since = "1.0.0")] #[stable(feature = "kebab-case", since = "1.0.0")] pub struct Struct; ``` ```rust // src/main.rs #![feature(kebab_case)] use repro::Struct; fn main() {} ``` ```console error[E0635]: unknown feature `kebab_case` --> src/main.rs:3:12 | 3 | #![feature(kebab_case)] | ^^^^^^^^^^ ``` vs the situation if we correctly use `feature = "snake_case"` and `#![feature(snake_case)]`, as enforced by this PR: ```console warning: the feature `snake_case` has been stable since 1.0.0 and no longer requires an attribute to enable --> src/main.rs:3:12 | 3 | #![feature(snake_case)] | ^^^^^^^^^^ | = note: `#[warn(stable_features)]` on by default ```
2 parents 4291748 + f34a2a8 commit fedb839

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

core/src/ffi/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//! match those defined by C, so that code that interacts with C will
77
//! refer to the correct types.
88
9-
#![stable(feature = "", since = "1.30.0")]
9+
#![stable(feature = "core_ffi", since = "1.30.0")]
1010
#![allow(non_camel_case_types)]
1111

1212
use crate::fmt;

std/src/io/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,10 +1140,10 @@ pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
11401140
#[repr(transparent)]
11411141
pub struct IoSliceMut<'a>(sys::io::IoSliceMut<'a>);
11421142

1143-
#[stable(feature = "iovec-send-sync", since = "1.44.0")]
1143+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
11441144
unsafe impl<'a> Send for IoSliceMut<'a> {}
11451145

1146-
#[stable(feature = "iovec-send-sync", since = "1.44.0")]
1146+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
11471147
unsafe impl<'a> Sync for IoSliceMut<'a> {}
11481148

11491149
#[stable(feature = "iovec", since = "1.36.0")]
@@ -1283,10 +1283,10 @@ impl<'a> DerefMut for IoSliceMut<'a> {
12831283
#[repr(transparent)]
12841284
pub struct IoSlice<'a>(sys::io::IoSlice<'a>);
12851285

1286-
#[stable(feature = "iovec-send-sync", since = "1.44.0")]
1286+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
12871287
unsafe impl<'a> Send for IoSlice<'a> {}
12881288

1289-
#[stable(feature = "iovec-send-sync", since = "1.44.0")]
1289+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
12901290
unsafe impl<'a> Sync for IoSlice<'a> {}
12911291

12921292
#[stable(feature = "iovec", since = "1.36.0")]

0 commit comments

Comments
 (0)