Skip to content

Go over all libstd traits and see which of them !/TyNever should implement #35866

Closed

Description

@arielb1

E.g. ! should implement Default.

Activity

  1. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
    and removed
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    on Jul 26, 2017
  2. added
    C-feature-acceptedCategory: A feature request that has been accepted pending implementation.
    and removed
    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
    on Nov 18, 2017
  3. Jules-Bertholet commented on Jul 3, 2023

    @Jules-Bertholet
    Contributor

    @rustbot label F-never_type

  4. added
    A-never-typeArea: `!` type. For issues not specific to `!`, use A-uninhabited-types.
    on Jul 3, 2023
  5. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    and removed
    C-feature-acceptedCategory: A feature request that has been accepted pending implementation.
    on Oct 18, 2025
  6. WaffleLapkin commented on Oct 18, 2025

    @WaffleLapkin
    Member

    The conditions under which it is reasonable for ! to implement a trait are:

    1. All functions accept an argument of type Self
    2. The trait does not have associated types1

    I went through all of the traits in the standard library, here is my analysis:

    • Most traits which make sense to implement for ! are already implemented
    • Because ! inherently relates to dead code it's very hard to come up with actual use-cases
    • There are a lot of traits which could be implemented for !, but why would you need it?

    IMO it's better to go on a case-by-case basis. I.e. if there is a use case for a certain trait to be implemented, implement it specifically, rather than trying to implement all that could be implemented.

    Here is a table with all traits in std:

    trait decision comment
    std::alloc::GlobalAlloc no while it fulfills the conditions, to use this trait you need a static with a value of Self, which is not possible for !
    std::alloc::Allocator yes I'm not fully sure, but it feels like there should be a use case?
    std::any::Any yes2 implemented for all types
    std::ascii::AsciiExt no deprecated, assoc type
    std::borrow::Borrow yes
    std::borrow::BorrowMut yes
    std::borrow::ToOwned no assoc type
    std::clone::Clone yes2
    std::clone::CloneToUninit yes2
    std::clone::UseCloned yes? seems mostly irrelevant
    std::cmp::Eq yes2
    std::cmp::Ord yes2
    std::cmp::PartialEq yes2
    std::cmp::PartialOrd yes2
    std::convert::AsMut yes
    std::convert::AsRef yes
    std::convert::From no it doesn't make sense to convert T -> !. for<T> From<!> for T could make sense, but it overlaps with for<T> From<T> for T and thus isn't happening
    std::convert::Into no see From
    std::convert::TryFrom no see From
    std::convert::TryInto no see From
    std::convert::FloatToInt no ! is not a float
    std::default::Default no default doesn't take an argument of type Self
    std::error::Error yes2
    std::ffi::VaArgSafe no you can't pass ! in varargs...
    std::fmt::Binary yes? not as useful as Debug/Display, but why not
    std::fmt::Debug yes2
    std::fmt::Display yes2
    std::fmt::LowerExp yes? not as useful as Debug/Display, but why not
    std::fmt::LowerHex yes? not as useful as Debug/Display, but why not
    std::fmt::Octal yes? not as useful as Debug/Display, but why not
    std::fmt::Pointer yes? not as useful as Debug/Display, but why not
    std::fmt::UpperExp yes? not as useful as Debug/Display, but why not
    std::fmt::UpperHex yes? not as useful as Debug/Display, but why not
    std::fmt::Write yes?3
    std::future::Future no assoc type
    std::future::IntoFuture no assoc type
    std::future::AsyncDrop no irrelevant
    std::hash::BuildHasher no assoc type
    std::hash::Hash yes2
    std::hash::Hasher yes?3
    std::io::BufRead yes?3
    std::io::IsTerminal yes?3
    std::io::Read yes?3
    std::io::Seek yes?3
    std::io::Write yes?3
    std::iter::DoubleEndedIterator no assoc type
    std::iter::ExactSizeIterator no assoc type
    std::iter::Extend yes?3
    std::iter::FromIterator no from_iter doesn't accept an argument of type Self
    std::iter::FusedIterator no assoc type
    std::iter::IntoIterator no assoc type
    std::iter::Iterator no assoc type
    std::iter::Product no product doesn't accept an argument of type Self
    std::iter::Sum no sum doesn't accept an argument of type Self
    std::iter::Step yes?3
    std::iter::TrustedLen no assoc type
    std::iter::TrustedStep no irrelevant, optimization only
    std::marker::Copy yes2
    std::marker::Send yes2
    std::marker::Sized yes2 automatically implemented
    std::marker::Sync yes2
    std::marker::Unpin yes2
    std::marker::ConstParamTy_ no you can't have a value of !, so you can't pass it as a const generic parameter
    std::marker::Destruct yes24
    std::marker::DiscriminantKind no assoc type
    std::marker::FnPtr no5 FnPtr seems to only be used as a bound for fn_addr_eq and is perma-unstable. there is never a need for the ! impl
    std::marker::Freeze yes2
    std::marker::MetaSized yes2 automatically implemented
    std::marker::PointeeSized yes2 automatically implemented
    std::marker::StructuralPartialEq no used for pattern matching, you can't have a value of ! => that'd be useless
    std::marker::Tuple no not a tuple
    std::marker::Unsize no automatically implemented / not relevant
    std::marker::UnsizedConstParamTy no same as ConstParamTy_?
    std::marker::Variance no not a variance type
    std::mem::TransmuteFrom ? implemented by the compiler, unclear if it matters for !
    std::net::ToSocketAddrs no assoc type
    std::num::ZeroablePrimitive no ! is never valid
    std::ops::*Assign yes?3
    std::ops::Not yes?2 see #91122 for the reasoning
    std::ops::Neg yes?3 similarly to Not? There hasn't been a feature request for that yet...
    std::ops::Drop no no need for a destructor / !: Copy
    std::ops::RangeBounds yes?3
    std::ops::CoerceUnsized no never type doesn't use or need unsize coercions (because there is always never to any)
    std::ops::DispatchFromDyn no doesn't make sense
    std::ops::IntoBounds yes?3
    std::ops::OneSidedRange yes?3
    std::ops::* (the rest) no assoc types6
    std::panic::RefUnwindSafe yes2
    std::panic::UnwindSafe yes2
    std::pin::PinCoerceUnsized no irrelevant
    std::process::Termination yes2
    std::ptr::Pointee yes2 automatically implemented for all types
    std::slice::SliceIndex no assoc type
    std::slice::Concat no assoc type
    std::slice::Join no assoc type
    std::std::FromStr no ! can't be constructed and thus can't be parsed
    std::string::ToString yes2
    std::sync::atomic::AtomicPrimitive no not an atomic primitive
    std::task::Wake yes?3
    std::task::LocalWake yes?3
    std::async_iter::AsyncIterator no assoc type
    std::async_iter::IntoAsyncIterator no assoc type
    std::random::Distribution yes?3
    std::random::RandomSource yes?3
    std::range::IntoBounds yes?3
    std::range::OneSidedRange yes?3
    std::range::RangeBounds yes?3
    std::range::Step yes?3
    std::simd::* no irrelevant

    Footnotes

    1. and there are multiple potential choices for it ↩

    2. ! already implements this traits ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21 ↩22 ↩23 ↩24 ↩25 ↩26

    3. I don't see a usecase, but it's possible ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21 ↩22

    4. https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=c1b0e0dc1208eb8871b7e22712768fb9 ↩

    5. possible to implement, but useless ↩

    6. technically it's possible to have for<T> !: Add<T, Output = T>, but why would you need this?... ↩

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-never-typeArea: `!` type. For issues not specific to `!`, use A-uninhabited-types.C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-libs-api[DEPRECATED; DO NOT USE]

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions