Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions library/core/src/convert/num.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
use crate::num::{IntErrorKind, TryFromIntError};

mod private {
/// This trait being unreachable from outside the crate
/// prevents other implementations of the `FloatToInt` trait,
/// which allows potentially adding more trait methods after the trait is `#[stable]`.
#[unstable(feature = "convert_float_to_int", issue = "67057")]
pub trait Sealed {}
}

/// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`.
/// Typically doesn’t need to be used directly.
#[unstable(feature = "convert_float_to_int", issue = "67057")]
pub trait FloatToInt<Int>: private::Sealed + Sized {
pub impl(self) trait FloatToInt<Int>: Sized {
#[unstable(feature = "convert_float_to_int", issue = "67057")]
#[doc(hidden)]
unsafe fn to_int_unchecked(self) -> Int;
}

macro_rules! impl_float_to_int {
($Float:ty => $($Int:ty),+) => {
#[unstable(feature = "convert_float_to_int", issue = "67057")]
impl private::Sealed for $Float {}
$(
#[unstable(feature = "convert_float_to_int", issue = "67057")]
impl FloatToInt<$Int> for $Float {
Expand Down
22 changes: 1 addition & 21 deletions library/core/src/ffi/va_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,26 +279,6 @@ const impl<'f> Drop for VaList<'f> {
}
}

mod sealed {
pub trait Sealed {}

impl Sealed for i16 {}
impl Sealed for i32 {}
impl Sealed for i64 {}
impl Sealed for isize {}

impl Sealed for u16 {}
impl Sealed for u32 {}
impl Sealed for u64 {}
impl Sealed for usize {}

impl Sealed for f32 {}
impl Sealed for f64 {}

impl<T> Sealed for *mut T {}
impl<T> Sealed for *const T {}
}

/// Types that are valid to read using [`VaList::next_arg`].
///
/// This trait is implemented for primitive types that have a variable argument application-binary
Expand Down Expand Up @@ -333,7 +313,7 @@ mod sealed {
// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
// to accept unsupported types in the meantime.
#[lang = "va_arg_safe"]
pub unsafe trait VaArgSafe: Copy + sealed::Sealed {}
pub impl(self) unsafe trait VaArgSafe: Copy {}

crate::cfg_select! {
any(target_arch = "avr", target_arch = "msp430") => {
Expand Down
10 changes: 1 addition & 9 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@
#![feature(offset_of_enum)]
#![feature(panic_internals)]
#![feature(pattern_type_macro)]
#![feature(sealed)]
#![feature(ub_checks)]
// tidy-alphabetical-end
//
Expand Down Expand Up @@ -141,6 +140,7 @@
#![feature(freeze_impls)]
#![feature(fundamental)]
#![feature(funnel_shifts)]
#![feature(impl_restriction)]
#![feature(intra_doc_pointers)]
#![feature(intrinsics)]
#![feature(lang_items)]
Expand Down Expand Up @@ -218,14 +218,6 @@ pub mod from {
pub use crate::macros::builtin::From;
}

mod sealed {
/// This trait being unreachable from outside the crate
/// prevents outside implementations of our extension traits.
/// This allows adding more trait methods in the future.
#[unstable(feature = "sealed", issue = "none")]
pub trait Sealed {}
}

// We don't export this through #[macro_export] for now, to avoid breakage.
#[unstable(feature = "autodiff", issue = "124509")]
#[doc = include_str!("../../core/src/autodiff.md")]
Expand Down
10 changes: 5 additions & 5 deletions library/core/src/marker/variance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ macro_rules! phantom_type {
}
}

impl<T> self::sealed::Sealed for $name<T> where T: ?Sized {
impl<T> self::private_items::PrivateItems for $name<T> where T: ?Sized {
const VALUE: Self = Self::new();
}
impl<T> Variance for $name<T> where T: ?Sized {}
Expand Down Expand Up @@ -114,7 +114,7 @@ macro_rules! phantom_lifetime {
}
}

impl self::sealed::Sealed for $name<'_> {
impl self::private_items::PrivateItems for $name<'_> {
const VALUE: Self = Self::new();
}
impl Variance for $name<'_> {}
Expand Down Expand Up @@ -233,14 +233,14 @@ phantom_type! {
pub struct PhantomInvariant<T>(PhantomData<fn(T) -> T>);
}

mod sealed {
pub trait Sealed {
mod private_items {
pub trait PrivateItems {
const VALUE: Self;
}
}

/// A marker trait for phantom variance types.
pub trait Variance: sealed::Sealed + Default {}
pub trait Variance: private_items::PrivateItems + Default {}
Copy link
Copy Markdown
Contributor

@fbstj fbstj May 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason this was left as sealed instead of impl(self) and if so is it worth a comment or a TODO/FIXME?

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name change sums it up — the VALUE item is private and never intended to be exposed publicly, so we need to continue using the previous hack. The alternative is to use a const Default bound and remove VALUE altogether, but iirc that was decided against in my PR implementing the variance helpers.


/// Construct a variance marker; equivalent to [`Default::default`].
///
Expand Down
9 changes: 0 additions & 9 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1848,12 +1848,3 @@ macro_rules! from_str_int_impl {

from_str_int_impl! { signed isize i8 i16 i32 i64 i128 }
from_str_int_impl! { unsigned usize u8 u16 u32 u64 u128 }

macro_rules! impl_sealed {
($($t:ty)*) => {$(
/// Allows extension traits within `core`.
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for $t {}
)*}
}
impl_sealed! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
18 changes: 1 addition & 17 deletions library/core/src/num/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,14 @@ use crate::{fmt, intrinsics, ptr, ub_checks};
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {
pub impl(self) unsafe trait ZeroablePrimitive: Sized + Copy {
/// A type like `Self` but with a niche that includes zero.
type NonZeroInner: Sized + Copy;
}

macro_rules! impl_zeroable_primitive {
($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => {
mod private {
#[unstable(
feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
pub trait Sealed {}
}

$(
#[unstable(
feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
impl private::Sealed for $primitive {}

#[unstable(
feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time",
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/num/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/// Trait for types that this type can be truncated to
#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")]
pub const trait TruncateTarget<Target>: crate::sealed::Sealed {
pub impl(self) const trait TruncateTarget<Target> {
#[doc(hidden)]
fn internal_truncate(self) -> Target;

Expand All @@ -18,7 +18,7 @@ pub const trait TruncateTarget<Target>: crate::sealed::Sealed {
/// Trait for types that this type can be widened to
#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")]
pub const trait WidenTarget<Target>: crate::sealed::Sealed {
pub impl(self) const trait WidenTarget<Target> {
#[doc(hidden)]
fn internal_widen(self) -> Target;
}
Expand Down
42 changes: 1 addition & 41 deletions library/core/src/slice/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,46 +102,6 @@ const unsafe fn get_offset_len_mut_noubcheck<T>(
crate::intrinsics::aggregate_raw_ptr(ptr, len)
}

mod private_slice_index {
use super::{ops, range};

#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub trait Sealed {}

#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for usize {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::Range<usize> {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::RangeTo<usize> {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::RangeFrom<usize> {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::RangeFull {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::RangeInclusive<usize> {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::RangeToInclusive<usize> {}
#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}

#[stable(feature = "new_range_api", since = "1.96.0")]
impl Sealed for range::Range<usize> {}
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
impl Sealed for range::RangeInclusive<usize> {}
#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
impl Sealed for range::RangeToInclusive<usize> {}
#[stable(feature = "new_range_from_api", since = "1.96.0")]
impl Sealed for range::RangeFrom<usize> {}

impl Sealed for ops::IndexRange {}

#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
impl Sealed for crate::index::Last {}
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
impl<T> Sealed for crate::index::Clamp<T> where T: Sealed {}
}

/// A helper trait used for indexing operations.
///
/// Implementations of this trait have to promise that if the argument
Expand All @@ -160,7 +120,7 @@ mod private_slice_index {
label = "slice indices are of type `usize` or ranges of `usize`"
)]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub const unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
pub impl(crate) const unsafe trait SliceIndex<T: ?Sized> {
/// The output type returned by methods.
#[stable(feature = "slice_get_slice", since = "1.28.0")]
type Output: ?Sized;
Expand Down
22 changes: 1 addition & 21 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5740,34 +5740,14 @@ impl fmt::Display for GetDisjointMutError {
}
}

mod private_get_disjoint_mut_index {
use super::{Range, RangeInclusive, range};

#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
pub trait Sealed {}

#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
impl Sealed for usize {}
#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
impl Sealed for Range<usize> {}
#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
impl Sealed for RangeInclusive<usize> {}
#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
impl Sealed for range::Range<usize> {}
#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
impl Sealed for range::RangeInclusive<usize> {}
}

/// A helper trait for `<[T]>::get_disjoint_mut()`.
///
/// # Safety
///
/// If `is_in_bounds()` returns `true` and `is_overlapping()` returns `false`,
/// it must be safe to index the slice with the indices.
#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
pub unsafe trait GetDisjointMutIndex:
Clone + private_get_disjoint_mut_index::Sealed
{
pub impl(self) unsafe trait GetDisjointMutIndex: Clone {
/// Returns `true` if `self` is in bounds for `len` slice elements.
#[unstable(feature = "get_disjoint_mut_helpers", issue = "none")]
fn is_in_bounds(&self, len: usize) -> bool;
Expand Down
7 changes: 1 addition & 6 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,6 @@ use crate::{fmt, intrinsics};
)]
#[expect(missing_debug_implementations)]
mod private {
pub(super) trait Sealed {}

#[cfg(target_has_atomic_load_store = "8")]
#[repr(C, align(1))]
pub struct Align1<T>(T);
Expand Down Expand Up @@ -291,17 +289,14 @@ mod private {
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
#[expect(private_bounds)]
pub unsafe trait AtomicPrimitive: Sized + Copy + private::Sealed {
pub impl(self) unsafe trait AtomicPrimitive: Sized + Copy {
/// Temporary implementation detail.
type Storage: Sized;
}

macro impl_atomic_primitive(
[$($T:ident)?] $Primitive:ty as $Storage:ident<$Operand:ty>, size($size:literal)
) {
impl $(<$T>)? private::Sealed for $Primitive {}

#[unstable(
feature = "atomic_internals",
reason = "implementation detail which may disappear or be replaced at any time",
Expand Down
8 changes: 0 additions & 8 deletions library/std/src/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,6 @@ pub struct OsString {
inner: Buf,
}

/// Allows extension traits within `std`.
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for OsString {}

/// Borrowed reference to an OS string (see [`OsString`]).
///
/// This type represents a borrowed reference to a string in the operating system's preferred
Expand All @@ -120,10 +116,6 @@ pub struct OsStr {
inner: Slice,
}

/// Allows extension traits within `std`.
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for OsStr {}

impl OsString {
/// Constructs a new empty `OsString`.
///
Expand Down
5 changes: 0 additions & 5 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ mod tests;
use crate::ffi::OsString;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
use crate::path::{Path, PathBuf};
use crate::sealed::Sealed;
use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, fs as fs_imp};
use crate::time::SystemTime;
use crate::{error, fmt};
Expand Down Expand Up @@ -2190,10 +2189,6 @@ impl AsInnerMut<fs_imp::FileTimes> for FileTimes {
}
}

// For implementing OS extension traits in `std::os`
#[stable(feature = "file_set_times", since = "1.75.0")]
impl Sealed for FileTimes {}

impl Permissions {
/// Returns `true` if these permissions describe a readonly (unwritable) file.
///
Expand Down
5 changes: 1 addition & 4 deletions library/std/src/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {

/// Trait to determine if a descriptor/handle refers to a terminal/tty.
#[stable(feature = "is_terminal", since = "1.70.0")]
pub trait IsTerminal: crate::sealed::Sealed {
pub impl(crate) trait IsTerminal {
Copy link
Copy Markdown
Member

@fmease fmease May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to block this PR on rustdoc support?

IsTerminal is stable and AFAICT the docs don't mention anywhere that the trait is sealed, so if we were to merge your PR now, users would no longer know that the trait is sealed just by looking at the docs. That feels unfortunate.

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not opposed to blocking it on such. I deliberately left any "this trait is sealed" comments for that reason. Once there's rustdoc support, all of those can be removed as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to wait for rustdoc as long as it's clear that the trait is sealed in the docs. We might have a rustdoc implementation soon enough1.

I could also see a middleground and have both the Sealed trait and impl(..) restrictions.

Let's nominate it for T-libs to decide.

Footnotes

  1. #t-rustdoc > Documenting `impl` restrictions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could temporarily add doc comments to each relevant trait.

/// Returns `true` if the descriptor/handle refers to a terminal/tty.
///
/// On platforms where Rust does not know how to detect a terminal yet, this will return
Expand Down Expand Up @@ -1250,9 +1250,6 @@ pub trait IsTerminal: crate::sealed::Sealed {

macro_rules! impl_is_terminal {
($($t:ty),*$(,)?) => {$(
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for $t {}

#[stable(feature = "is_terminal", since = "1.70.0")]
impl IsTerminal for $t {
#[inline]
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@
#![feature(f128)]
#![feature(ffi_const)]
#![feature(gpu_offload)]
#![feature(impl_restriction)]
#![feature(intra_doc_pointers)]
#![feature(lang_items)]
#![feature(link_cfg)]
Expand Down Expand Up @@ -785,6 +786,8 @@ include!("keyword_docs.rs");
#[unstable(feature = "restricted_std", issue = "none")]
mod __restricted_std_workaround {}

// FIXME(jhpratt) This is currently only used by portable SIMD. Once rust-lang/portable-simd#529 is
// merged, this should be able to be removed.
mod sealed {
/// This trait being unreachable from outside the crate
/// prevents outside implementations of our extension traits.
Expand Down
Loading
Loading