Rollup merge of #121840 - oli-obk:freeze, r=dtolnay
Expose the Freeze trait again (unstably) and forbid implementing it manually non-emoji version of https://github.com/rust-lang/rust/pull/121501 cc #60715 This trait is useful for generic constants (associated consts of generic traits). See the test (`tests/ui/associated-consts/freeze.rs`) added in this PR for a usage example. The builtin `Freeze` trait is the only way to do it, users cannot work around this issue. It's also a useful trait for building some very specific abstrations, as shown by the usage by the `zerocopy` crate: https://github.com/google/zerocopy/issues/941 cc ```@RalfJung``` T-lang signed off on reexposing this unstably: https://github.com/rust-lang/rust/pull/121501#issuecomment-1969827742
This commit is contained in:
commit
05f22c3614
15 changed files with 89 additions and 11 deletions
|
@ -8,6 +8,7 @@
|
||||||
rustc_attrs,
|
rustc_attrs,
|
||||||
transparent_unions,
|
transparent_unions,
|
||||||
auto_traits,
|
auto_traits,
|
||||||
|
freeze_impls,
|
||||||
thread_local
|
thread_local
|
||||||
)]
|
)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![feature(
|
#![feature(
|
||||||
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
|
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
|
thread_local
|
||||||
)]
|
)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
|
@ -471,6 +471,8 @@ declare_features! (
|
||||||
(unstable, fn_align, "1.53.0", Some(82232)),
|
(unstable, fn_align, "1.53.0", Some(82232)),
|
||||||
/// Support delegating implementation of functions to other already implemented functions.
|
/// Support delegating implementation of functions to other already implemented functions.
|
||||||
(incomplete, fn_delegation, "1.76.0", Some(118212)),
|
(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`.
|
/// Allows defining gen blocks and `gen fn`.
|
||||||
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
||||||
/// Infer generic args for both consts and types.
|
/// Infer generic args for both consts and types.
|
||||||
|
|
|
@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||||
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::{sym, ErrorGuaranteed};
|
use rustc_span::{sym, ErrorGuaranteed};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
||||||
|
@ -49,6 +50,19 @@ fn enforce_trait_manually_implementable(
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let impl_header_span = tcx.def_span(impl_def_id);
|
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]`
|
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
|
||||||
if trait_def.deny_explicit_impl {
|
if trait_def.deny_explicit_impl {
|
||||||
let trait_name = tcx.item_name(trait_def_id);
|
let trait_name = tcx.item_name(trait_def_id);
|
||||||
|
|
|
@ -864,6 +864,7 @@ symbols! {
|
||||||
format_placeholder,
|
format_placeholder,
|
||||||
format_unsafe_arg,
|
format_unsafe_arg,
|
||||||
freeze,
|
freeze,
|
||||||
|
freeze_impls,
|
||||||
freg,
|
freg,
|
||||||
frem_algebraic,
|
frem_algebraic,
|
||||||
frem_fast,
|
frem_fast,
|
||||||
|
|
|
@ -204,6 +204,7 @@
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![cfg_attr(bootstrap, feature(diagnostic_namespace))]
|
#![cfg_attr(bootstrap, feature(diagnostic_namespace))]
|
||||||
#![cfg_attr(bootstrap, feature(platform_intrinsics))]
|
#![cfg_attr(bootstrap, feature(platform_intrinsics))]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(freeze_impls))]
|
||||||
#![feature(abi_unadjusted)]
|
#![feature(abi_unadjusted)]
|
||||||
#![feature(adt_const_params)]
|
#![feature(adt_const_params)]
|
||||||
#![feature(allow_internal_unsafe)]
|
#![feature(allow_internal_unsafe)]
|
||||||
|
|
|
@ -810,15 +810,21 @@ pub trait DiscriminantKind {
|
||||||
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
|
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.
|
/// any `UnsafeCell` internally, but not through an indirection.
|
||||||
/// This affects, for example, whether a `static` of that type is
|
/// This affects, for example, whether a `static` of that type is
|
||||||
/// placed in read-only static memory or writable static memory.
|
/// 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"]
|
#[lang = "freeze"]
|
||||||
pub(crate) unsafe auto trait Freeze {}
|
#[unstable(feature = "freeze", issue = "121675")]
|
||||||
|
pub unsafe auto trait Freeze {}
|
||||||
|
|
||||||
|
#[unstable(feature = "freeze", issue = "121675")]
|
||||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
||||||
marker_impls! {
|
marker_impls! {
|
||||||
|
#[unstable(feature = "freeze", issue = "121675")]
|
||||||
unsafe Freeze for
|
unsafe Freeze for
|
||||||
{T: ?Sized} PhantomData<T>,
|
{T: ?Sized} PhantomData<T>,
|
||||||
{T: ?Sized} *const T,
|
{T: ?Sized} *const T,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(no_core, lang_items)]
|
#![feature(no_core, lang_items, freeze_impls)]
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,10 @@ pub trait Signal2 {
|
||||||
type Item2;
|
type Item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, C> Signal2 for B where B: Signal<Item = C> {
|
impl<B, C> Signal2 for B
|
||||||
|
where
|
||||||
|
B: Signal<Item = C>,
|
||||||
|
{
|
||||||
type Item2 = C;
|
type Item2 = C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +20,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
|
||||||
// @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
|
// @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
|
||||||
// @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
|
// @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
|
||||||
// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
|
// @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<B: Signal> {
|
pub struct Switch<B: Signal> {
|
||||||
pub inner: <B as Signal2>::Item2,
|
pub inner: <B as Signal2>::Item2,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#![crate_name = "foo"]
|
#![crate_name = "foo"]
|
||||||
|
#![feature(negative_impls, freeze_impls, freeze)]
|
||||||
#![feature(negative_impls)]
|
|
||||||
|
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
|
@ -8,6 +7,7 @@ pub struct Foo;
|
||||||
// @!hasraw - 'Auto Trait Implementations'
|
// @!hasraw - 'Auto Trait Implementations'
|
||||||
impl !Send for Foo {}
|
impl !Send for Foo {}
|
||||||
impl !Sync for Foo {}
|
impl !Sync for Foo {}
|
||||||
|
impl !std::marker::Freeze for Foo {}
|
||||||
impl !std::marker::Unpin for Foo {}
|
impl !std::marker::Unpin for Foo {}
|
||||||
impl !std::panic::RefUnwindSafe for Foo {}
|
impl !std::panic::RefUnwindSafe for Foo {}
|
||||||
impl !std::panic::UnwindSafe for Foo {}
|
impl !std::panic::UnwindSafe for Foo {}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
|
// @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
|
||||||
// @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
|
// @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
|
||||||
// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
|
// @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<T> {
|
pub struct Foo<T> {
|
||||||
field: T,
|
field: T,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// 'impl<T> Send for Foo<T>'
|
// 'impl<T> Send for Foo<T>'
|
||||||
//
|
//
|
||||||
// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
|
// @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<T> {
|
pub struct Foo<T> {
|
||||||
field: T,
|
field: T,
|
||||||
}
|
}
|
||||||
|
|
12
tests/ui/associated-consts/freeze.rs
Normal file
12
tests/ui/associated-consts/freeze.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#![feature(freeze)]
|
||||||
|
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
use std::marker::Freeze;
|
||||||
|
|
||||||
|
trait Trait<T: Freeze + 'static> {
|
||||||
|
const VALUE: T;
|
||||||
|
const VALUE_REF: &'static T = &Self::VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
15
tests/ui/feature-gates/feature-gate-freeze-impls.rs
Normal file
15
tests/ui/feature-gates/feature-gate-freeze-impls.rs
Normal file
|
@ -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() {}
|
23
tests/ui/feature-gates/feature-gate-freeze-impls.stderr
Normal file
23
tests/ui/feature-gates/feature-gate-freeze-impls.stderr
Normal file
|
@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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`.
|
Loading…
Add table
Add a link
Reference in a new issue