about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-24 15:06:20 +0000
committerbors <bors@rust-lang.org>2023-10-24 15:06:20 +0000
commit07a4b7e2a9a4dc2840cd9311aad3ac3ebcb41543 (patch)
tree9ec0d777c16b42b9e54f5585c7b98cb890c5f569 /library
parent642bfb254a851d0deca01d6e2f4db13b60536210 (diff)
parent6a02e20fb5e80f1d05070af0cb2b0f85185a62d0 (diff)
Auto merge of #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
```
Diffstat (limited to 'library')
-rw-r--r--library/core/src/ffi/mod.rs2
-rw-r--r--library/std/src/io/mod.rs8
2 files changed, 5 insertions, 5 deletions
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index b2c9a0800c9..6908c824f44 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -6,7 +6,7 @@
 //! match those defined by C, so that code that interacts with C will
 //! refer to the correct types.
 
-#![stable(feature = "", since = "1.30.0")]
+#![stable(feature = "core_ffi", since = "1.30.0")]
 #![allow(non_camel_case_types)]
 
 use crate::fmt;
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 063464046e0..bca5d859b66 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1140,10 +1140,10 @@ pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
 #[repr(transparent)]
 pub struct IoSliceMut<'a>(sys::io::IoSliceMut<'a>);
 
-#[stable(feature = "iovec-send-sync", since = "1.44.0")]
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
 unsafe impl<'a> Send for IoSliceMut<'a> {}
 
-#[stable(feature = "iovec-send-sync", since = "1.44.0")]
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
 unsafe impl<'a> Sync for IoSliceMut<'a> {}
 
 #[stable(feature = "iovec", since = "1.36.0")]
@@ -1283,10 +1283,10 @@ impl<'a> DerefMut for IoSliceMut<'a> {
 #[repr(transparent)]
 pub struct IoSlice<'a>(sys::io::IoSlice<'a>);
 
-#[stable(feature = "iovec-send-sync", since = "1.44.0")]
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
 unsafe impl<'a> Send for IoSlice<'a> {}
 
-#[stable(feature = "iovec-send-sync", since = "1.44.0")]
+#[stable(feature = "iovec_send_sync", since = "1.44.0")]
 unsafe impl<'a> Sync for IoSlice<'a> {}
 
 #[stable(feature = "iovec", since = "1.36.0")]