From 24a4f323f4fee7fb525821a2dddb65c48ce950f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 14 Jun 2025 08:24:32 +0200 Subject: [PATCH 1/3] allow constants to refer to mutable/external memory, but reject such constants as patterns --- src/items/constant-items.md | 3 --- src/patterns.md | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/items/constant-items.md b/src/items/constant-items.md index be94be6cb..269d10aec 100644 --- a/src/items/constant-items.md +++ b/src/items/constant-items.md @@ -48,9 +48,6 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { }; ``` -r[items.const.final-value-immutable] -The final value of a `const` item cannot contain references to anything mutable. - r[items.const.expr-omission] The constant expression may only be omitted in a [trait definition]. diff --git a/src/patterns.md b/src/patterns.md index 60cfb21c4..df9c7c0c3 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -975,6 +975,9 @@ r[patterns.const.generic] In particular, the value of `C` must be known at pattern-building time (which is pre-monomorphization). This means that associated consts that involve generic parameters cannot be used as patterns. +r[patterns.const.immutable] +Finally, the value of `C` must not contain any references to mutable statics (`static mut` or interior mutable) or `extern` statics. + r[patterns.const.translation] After ensuring all conditions are met, the constant value is translated into a pattern, and now behaves exactly as-if that pattern had been written directly. In particular, it fully participates in exhaustiveness checking. From dd6e807336979459d10be9bf91713ac9fa4fa3a5 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 24 Jun 2025 20:49:32 +0000 Subject: [PATCH 2/3] Add clarifications In the text as revised, it wasn't clear what rule prevented a mutable reference from appearing in the final value of a constant item, so let's add a rule specifically for that. Similarly, it may not be immediately clear what rule prevents a reference to a lifetime-extended interior mutable temporary created in the initializer, so let's add an admonition section describing how other rules apply to prevent this. --- src/items/constant-items.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/items/constant-items.md b/src/items/constant-items.md index 269d10aec..10038c640 100644 --- a/src/items/constant-items.md +++ b/src/items/constant-items.md @@ -48,6 +48,37 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { }; ``` +r[items.const.no-mut-refs] +The final value of a `const` item cannot contain any mutable references. + +```rust +# #![allow(static_mut_refs)] +static mut S: u8 = 0; +const C: &u8 = unsafe { &mut S }; // OK +``` + +```rust +# use core::sync::atomic::AtomicU8; +static S: AtomicU8 = AtomicU8::new(0); +const C: &AtomicU8 = &S; // OK +``` + +```rust,compile_fail,E0080 +# #![allow(static_mut_refs)] +static mut S: u8 = 0; +const C: &mut u8 = unsafe { &mut S }; // ERROR not allowed +``` + +> [!NOTE] +> We also disallow, in the final value, shared references to mutable statics created in the initializer for a separate reason. Consider: +> +> ```rust,compile_fail,E0492 +> # use core::sync::atomic::AtomicU8; +> const C: &AtomicU8 = &AtomicU8::new(0); // ERROR +> ``` +> +> Here, the `AtomicU8` is a temporary that is lifetime extended to `'static` (see [destructors.scope.lifetime-extension.static]), and references to lifetime-extended temporaries with interior mutability are not allowed in the final value of a constant expression (see [const-eval.const-expr.borrows]). + r[items.const.expr-omission] The constant expression may only be omitted in a [trait definition]. From 5910551b3a7f8cbee80dfcd2cdd65f20ac3d37ac Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 24 Jun 2025 21:18:17 +0000 Subject: [PATCH 3/3] Revise editorially --- src/patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patterns.md b/src/patterns.md index df9c7c0c3..6bfe20a84 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -976,7 +976,7 @@ In particular, the value of `C` must be known at pattern-building time (which is This means that associated consts that involve generic parameters cannot be used as patterns. r[patterns.const.immutable] -Finally, the value of `C` must not contain any references to mutable statics (`static mut` or interior mutable) or `extern` statics. +The value of `C` must not contain any references to mutable statics (`static mut` items or interior mutable `static` items) or `extern` statics. r[patterns.const.translation] After ensuring all conditions are met, the constant value is translated into a pattern, and now behaves exactly as-if that pattern had been written directly.