diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 67a0d0dabea94..39988cf64e54b 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -8,6 +8,7 @@ rustc_attrs, transparent_unions, auto_traits, + freeze_impls, thread_local )] #![no_core] diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index cc3d647c8c82f..a868471ed1d4d 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -1,6 +1,6 @@ #![feature( no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types, - decl_macro, rustc_attrs, transparent_unions, auto_traits, + decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls, thread_local )] #![no_core] diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a10f4b934ea0a..52421fce86738 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -471,6 +471,8 @@ declare_features! ( (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. (incomplete, fn_delegation, "1.76.0", Some(118212)), + /// Allows impls for the Freeze trait. + (internal, freeze_impls, "CURRENT_RUSTC_VERSION", Some(121675)), /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), /// Infer generic args for both consts and types. diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index fc7a73e12be0a..054a3af212a55 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_session::parse::feature_err; use rustc_span::{sym, ErrorGuaranteed}; use rustc_trait_selection::traits; @@ -49,6 +50,19 @@ fn enforce_trait_manually_implementable( ) -> Result<(), ErrorGuaranteed> { let impl_header_span = tcx.def_span(impl_def_id); + if tcx.lang_items().freeze_trait() == Some(trait_def_id) { + if !tcx.features().freeze_impls { + feature_err( + &tcx.sess, + sym::freeze_impls, + impl_header_span, + "explicit impls for the `Freeze` trait are not permitted", + ) + .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed")) + .emit(); + } + } + // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]` if trait_def.deny_explicit_impl { let trait_name = tcx.item_name(trait_def_id); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a8426d78cace0..f592c1d3dd373 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -864,6 +864,7 @@ symbols! { format_placeholder, format_unsafe_arg, freeze, + freeze_impls, freg, frem_algebraic, frem_fast, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0f7885769c267..6bcf7c13e64eb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -204,6 +204,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(diagnostic_namespace))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] +#![cfg_attr(not(bootstrap), feature(freeze_impls))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 2e22129d7b64d..a56a2578c2241 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -810,15 +810,21 @@ pub trait DiscriminantKind { type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin; } -/// Compiler-internal trait used to determine whether a type contains +/// Used to determine whether a type contains /// any `UnsafeCell` internally, but not through an indirection. /// This affects, for example, whether a `static` of that type is /// placed in read-only static memory or writable static memory. +/// This can be used to declare that a constant with a generic type +/// will not contain interior mutability, and subsequently allow +/// placing the constant behind references. #[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +#[unstable(feature = "freeze", issue = "121675")] +pub unsafe auto trait Freeze {} +#[unstable(feature = "freeze", issue = "121675")] impl !Freeze for UnsafeCell {} marker_impls! { + #[unstable(feature = "freeze", issue = "121675")] unsafe Freeze for {T: ?Sized} PhantomData, {T: ?Sized} *const T, diff --git a/tests/run-make/min-global-align/min_global_align.rs b/tests/run-make/min-global-align/min_global_align.rs index 135792e937205..cd1ef8cb351ff 100644 --- a/tests/run-make/min-global-align/min_global_align.rs +++ b/tests/run-make/min-global-align/min_global_align.rs @@ -1,4 +1,4 @@ -#![feature(no_core, lang_items)] +#![feature(no_core, lang_items, freeze_impls)] #![crate_type = "rlib"] #![no_core] diff --git a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs index 0663ed5fc81ff..7d9133b85a613 100644 --- a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs +++ b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs @@ -1,5 +1,5 @@ // https://github.com/rust-lang/rust/issues/50159 -#![crate_name="foo"] +#![crate_name = "foo"] pub trait Signal { type Item; @@ -9,7 +9,10 @@ pub trait Signal2 { type Item2; } -impl Signal2 for B where B: Signal { +impl Signal2 for B +where + B: Signal, +{ type Item2 = C; } @@ -17,7 +20,7 @@ impl Signal2 for B where B: Signal { // @has - '//h3[@class="code-header"]' 'impl Send for Switchwhere ::Item: Send' // @has - '//h3[@class="code-header"]' 'impl Sync for Switchwhere ::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6 pub struct Switch { pub inner: ::Item2, } diff --git a/tests/rustdoc/empty-section.rs b/tests/rustdoc/empty-section.rs index d8241ab96f6dd..0d6afb0e44447 100644 --- a/tests/rustdoc/empty-section.rs +++ b/tests/rustdoc/empty-section.rs @@ -1,6 +1,5 @@ #![crate_name = "foo"] - -#![feature(negative_impls)] +#![feature(negative_impls, freeze_impls, freeze)] pub struct Foo; @@ -8,6 +7,7 @@ pub struct Foo; // @!hasraw - 'Auto Trait Implementations' impl !Send for Foo {} impl !Sync for Foo {} +impl !std::marker::Freeze for Foo {} impl !std::marker::Unpin for Foo {} impl !std::panic::RefUnwindSafe for Foo {} impl !std::panic::UnwindSafe for Foo {} diff --git a/tests/rustdoc/synthetic_auto/basic.rs b/tests/rustdoc/synthetic_auto/basic.rs index 043ac24148838..16b8cce490c84 100644 --- a/tests/rustdoc/synthetic_auto/basic.rs +++ b/tests/rustdoc/synthetic_auto/basic.rs @@ -2,7 +2,7 @@ // @has - '//h3[@class="code-header"]' 'impl Send for Foowhere T: Send' // @has - '//h3[@class="code-header"]' 'impl Sync for Foowhere T: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6 pub struct Foo { field: T, } diff --git a/tests/rustdoc/synthetic_auto/manual.rs b/tests/rustdoc/synthetic_auto/manual.rs index 7fc8447df3efc..692d68294a7ef 100644 --- a/tests/rustdoc/synthetic_auto/manual.rs +++ b/tests/rustdoc/synthetic_auto/manual.rs @@ -6,7 +6,7 @@ // 'impl Send for Foo' // // @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 pub struct Foo { field: T, } diff --git a/tests/ui/associated-consts/freeze.rs b/tests/ui/associated-consts/freeze.rs new file mode 100644 index 0000000000000..2364ee1f4956f --- /dev/null +++ b/tests/ui/associated-consts/freeze.rs @@ -0,0 +1,12 @@ +#![feature(freeze)] + +//@ check-pass + +use std::marker::Freeze; + +trait Trait { + const VALUE: T; + const VALUE_REF: &'static T = &Self::VALUE; +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.rs b/tests/ui/feature-gates/feature-gate-freeze-impls.rs new file mode 100644 index 0000000000000..c14c9494874a2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-freeze-impls.rs @@ -0,0 +1,15 @@ +#![feature(freeze, negative_impls)] + +use std::marker::Freeze; + +struct Foo; + +unsafe impl Freeze for Foo {} +//~^ explicit impls for the `Freeze` trait are not permitted + +struct Bar; + +impl !Freeze for Bar {} +//~^ explicit impls for the `Freeze` trait are not permitted + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.stderr b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr new file mode 100644 index 0000000000000..eef524fe78e8b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr @@ -0,0 +1,23 @@ +error[E0658]: explicit impls for the `Freeze` trait are not permitted + --> $DIR/feature-gate-freeze-impls.rs:7:1 + | +LL | unsafe impl Freeze for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed + | + = note: see issue #121675 for more information + = help: add `#![feature(freeze_impls)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: explicit impls for the `Freeze` trait are not permitted + --> $DIR/feature-gate-freeze-impls.rs:12:1 + | +LL | impl !Freeze for Bar {} + | ^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed + | + = note: see issue #121675 for more information + = help: add `#![feature(freeze_impls)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`.