Movatterモバイル変換


[0]ホーム

URL:


core/
any.rs

1//! Utilities for dynamic typing or type reflection.2//!3//! # `Any` and `TypeId`4//!5//! `Any` itself can be used to get a `TypeId`, and has more features when used6//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is`7//! and `downcast_ref` methods, to test if the contained value is of a given type,8//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there9//! is also the `downcast_mut` method, for getting a mutable reference to the10//! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to11//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.12//!13//! Note that `&dyn Any` is limited to testing whether a value is of a specified14//! concrete type, and cannot be used to test whether a type implements a trait.15//!16//! [`Box`]: ../../std/boxed/struct.Box.html17//!18//! # Smart pointers and `dyn Any`19//!20//! One piece of behavior to keep in mind when using `Any` as a trait object,21//! especially with types like `Box<dyn Any>` or `Arc<dyn Any>`, is that simply22//! calling `.type_id()` on the value will produce the `TypeId` of the23//! *container*, not the underlying trait object. This can be avoided by24//! converting the smart pointer into a `&dyn Any` instead, which will return25//! the object's `TypeId`. For example:26//!27//! ```28//! use std::any::{Any, TypeId};29//!30//! let boxed: Box<dyn Any> = Box::new(3_i32);31//!32//! // You're more likely to want this:33//! let actual_id = (&*boxed).type_id();34//! // ... than this:35//! let boxed_id = boxed.type_id();36//!37//! assert_eq!(actual_id, TypeId::of::<i32>());38//! assert_eq!(boxed_id, TypeId::of::<Box<dyn Any>>());39//! ```40//!41//! ## Examples42//!43//! Consider a situation where we want to log a value passed to a function.44//! We know the value we're working on implements `Debug`, but we don't know its45//! concrete type. We want to give special treatment to certain types: in this46//! case printing out the length of `String` values prior to their value.47//! We don't know the concrete type of our value at compile time, so we need to48//! use runtime reflection instead.49//!50//! ```rust51//! use std::fmt::Debug;52//! use std::any::Any;53//!54//! // Logger function for any type that implements `Debug`.55//! fn log<T: Any + Debug>(value: &T) {56//!     let value_any = value as &dyn Any;57//!58//!     // Try to convert our value to a `String`. If successful, we want to59//!     // output the `String`'s length as well as its value. If not, it's a60//!     // different type: just print it out unadorned.61//!     match value_any.downcast_ref::<String>() {62//!         Some(as_string) => {63//!             println!("String ({}): {}", as_string.len(), as_string);64//!         }65//!         None => {66//!             println!("{value:?}");67//!         }68//!     }69//! }70//!71//! // This function wants to log its parameter out prior to doing work with it.72//! fn do_work<T: Any + Debug>(value: &T) {73//!     log(value);74//!     // ...do some other work75//! }76//!77//! fn main() {78//!     let my_string = "Hello World".to_string();79//!     do_work(&my_string);80//!81//!     let my_i8: i8 = 100;82//!     do_work(&my_i8);83//! }84//! ```85//!8687#![stable(feature ="rust1", since ="1.0.0")]8889usecrate::{fmt, hash, intrinsics, ptr};9091///////////////////////////////////////////////////////////////////////////////92// Any trait93///////////////////////////////////////////////////////////////////////////////9495/// A trait to emulate dynamic typing.96///97/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.98/// See the [module-level documentation][mod] for more details.99///100/// [mod]: crate::any101// This trait is not unsafe, though we rely on the specifics of it's sole impl's102// `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be103// a problem, but because the only impl of `Any` is a blanket implementation, no104// other code can implement `Any`.105//106// We could plausibly make this trait unsafe -- it would not cause breakage,107// since we control all the implementations -- but we choose not to as that's108// both not really necessary and may confuse users about the distinction of109// unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call,110// but we would likely want to indicate as such in documentation).111#[stable(feature ="rust1", since ="1.0.0")]112#[rustc_diagnostic_item ="Any"]113pub traitAny:'static{114/// Gets the `TypeId` of `self`.115    ///116    /// If called on a `dyn Any` trait object117    /// (or a trait object of a subtrait of `Any`),118    /// this returns the `TypeId` of the underlying119    /// concrete type, not that of `dyn Any` itself.120    ///121    /// # Examples122    ///123    /// ```124    /// use std::any::{Any, TypeId};125    ///126    /// fn is_string(s: &dyn Any) -> bool {127    ///     TypeId::of::<String>() == s.type_id()128    /// }129    ///130    /// assert_eq!(is_string(&0), false);131    /// assert_eq!(is_string(&"cookie monster".to_string()), true);132    /// ```133#[stable(feature ="get_type_id", since ="1.34.0")]134fntype_id(&self) -> TypeId;135}136137#[stable(feature ="rust1", since ="1.0.0")]138impl<T:'static+?Sized> AnyforT {139fntype_id(&self) -> TypeId {140        TypeId::of::<T>()141    }142}143144///////////////////////////////////////////////////////////////////////////////145// Extension methods for Any trait objects.146///////////////////////////////////////////////////////////////////////////////147148#[stable(feature ="rust1", since ="1.0.0")]149implfmt::Debugfor dynAny {150fnfmt(&self, f:&mutfmt::Formatter<'_>) -> fmt::Result {151        f.debug_struct("Any").finish_non_exhaustive()152    }153}154155// Ensure that the result of e.g., joining a thread can be printed and156// hence used with `unwrap`. May eventually no longer be needed if157// dispatch works with upcasting.158#[stable(feature ="rust1", since ="1.0.0")]159implfmt::Debugfor dynAny + Send {160fnfmt(&self, f:&mutfmt::Formatter<'_>) -> fmt::Result {161        f.debug_struct("Any").finish_non_exhaustive()162    }163}164165#[stable(feature ="any_send_sync_methods", since ="1.28.0")]166implfmt::Debugfor dynAny + Send + Sync {167fnfmt(&self, f:&mutfmt::Formatter<'_>) -> fmt::Result {168        f.debug_struct("Any").finish_non_exhaustive()169    }170}171172impl dynAny {173/// Returns `true` if the inner type is the same as `T`.174    ///175    /// # Examples176    ///177    /// ```178    /// use std::any::Any;179    ///180    /// fn is_string(s: &dyn Any) {181    ///     if s.is::<String>() {182    ///         println!("It's a string!");183    ///     } else {184    ///         println!("Not a string...");185    ///     }186    /// }187    ///188    /// is_string(&0);189    /// is_string(&"cookie monster".to_string());190    /// ```191#[stable(feature ="rust1", since ="1.0.0")]192    #[inline]193pub fnis<T: Any>(&self) -> bool {194// Get `TypeId` of the type this function is instantiated with.195lett = TypeId::of::<T>();196197// Get `TypeId` of the type in the trait object (`self`).198letconcrete =self.type_id();199200// Compare both `TypeId`s on equality.201t == concrete202    }203204/// Returns some reference to the inner value if it is of type `T`, or205    /// `None` if it isn't.206    ///207    /// # Examples208    ///209    /// ```210    /// use std::any::Any;211    ///212    /// fn print_if_string(s: &dyn Any) {213    ///     if let Some(string) = s.downcast_ref::<String>() {214    ///         println!("It's a string({}): '{}'", string.len(), string);215    ///     } else {216    ///         println!("Not a string...");217    ///     }218    /// }219    ///220    /// print_if_string(&0);221    /// print_if_string(&"cookie monster".to_string());222    /// ```223#[stable(feature ="rust1", since ="1.0.0")]224    #[inline]225pub fndowncast_ref<T: Any>(&self) ->Option<&T> {226ifself.is::<T>() {227// SAFETY: just checked whether we are pointing to the correct type, and we can rely on228            // that check for memory safety because we have implemented Any for all types; no other229            // impls can exist as they would conflict with our impl.230unsafe{Some(self.downcast_unchecked_ref()) }231        }else{232None233}234    }235236/// Returns some mutable reference to the inner value if it is of type `T`, or237    /// `None` if it isn't.238    ///239    /// # Examples240    ///241    /// ```242    /// use std::any::Any;243    ///244    /// fn modify_if_u32(s: &mut dyn Any) {245    ///     if let Some(num) = s.downcast_mut::<u32>() {246    ///         *num = 42;247    ///     }248    /// }249    ///250    /// let mut x = 10u32;251    /// let mut s = "starlord".to_string();252    ///253    /// modify_if_u32(&mut x);254    /// modify_if_u32(&mut s);255    ///256    /// assert_eq!(x, 42);257    /// assert_eq!(&s, "starlord");258    /// ```259#[stable(feature ="rust1", since ="1.0.0")]260    #[inline]261pub fndowncast_mut<T: Any>(&mutself) ->Option<&mutT> {262ifself.is::<T>() {263// SAFETY: just checked whether we are pointing to the correct type, and we can rely on264            // that check for memory safety because we have implemented Any for all types; no other265            // impls can exist as they would conflict with our impl.266unsafe{Some(self.downcast_unchecked_mut()) }267        }else{268None269}270    }271272/// Returns a reference to the inner value as type `dyn T`.273    ///274    /// # Examples275    ///276    /// ```277    /// #![feature(downcast_unchecked)]278    ///279    /// use std::any::Any;280    ///281    /// let x: Box<dyn Any> = Box::new(1_usize);282    ///283    /// unsafe {284    ///     assert_eq!(*x.downcast_unchecked_ref::<usize>(), 1);285    /// }286    /// ```287    ///288    /// # Safety289    ///290    /// The contained value must be of type `T`. Calling this method291    /// with the incorrect type is *undefined behavior*.292#[unstable(feature ="downcast_unchecked", issue ="90850")]293    #[inline]294pub unsafe fndowncast_unchecked_ref<T: Any>(&self) ->&T {295debug_assert!(self.is::<T>());296// SAFETY: caller guarantees that T is the correct type297unsafe{&*(selfas*constdynAnyas*constT) }298    }299300/// Returns a mutable reference to the inner value as type `dyn T`.301    ///302    /// # Examples303    ///304    /// ```305    /// #![feature(downcast_unchecked)]306    ///307    /// use std::any::Any;308    ///309    /// let mut x: Box<dyn Any> = Box::new(1_usize);310    ///311    /// unsafe {312    ///     *x.downcast_unchecked_mut::<usize>() += 1;313    /// }314    ///315    /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);316    /// ```317    ///318    /// # Safety319    ///320    /// The contained value must be of type `T`. Calling this method321    /// with the incorrect type is *undefined behavior*.322#[unstable(feature ="downcast_unchecked", issue ="90850")]323    #[inline]324pub unsafe fndowncast_unchecked_mut<T: Any>(&mutself) ->&mutT {325debug_assert!(self.is::<T>());326// SAFETY: caller guarantees that T is the correct type327unsafe{&mut *(selfas*mutdynAnyas*mutT) }328    }329}330331impl dynAny + Send {332/// Forwards to the method defined on the type `dyn Any`.333    ///334    /// # Examples335    ///336    /// ```337    /// use std::any::Any;338    ///339    /// fn is_string(s: &(dyn Any + Send)) {340    ///     if s.is::<String>() {341    ///         println!("It's a string!");342    ///     } else {343    ///         println!("Not a string...");344    ///     }345    /// }346    ///347    /// is_string(&0);348    /// is_string(&"cookie monster".to_string());349    /// ```350#[stable(feature ="rust1", since ="1.0.0")]351    #[inline]352pub fnis<T: Any>(&self) -> bool {353        <dynAny>::is::<T>(self)354    }355356/// Forwards to the method defined on the type `dyn Any`.357    ///358    /// # Examples359    ///360    /// ```361    /// use std::any::Any;362    ///363    /// fn print_if_string(s: &(dyn Any + Send)) {364    ///     if let Some(string) = s.downcast_ref::<String>() {365    ///         println!("It's a string({}): '{}'", string.len(), string);366    ///     } else {367    ///         println!("Not a string...");368    ///     }369    /// }370    ///371    /// print_if_string(&0);372    /// print_if_string(&"cookie monster".to_string());373    /// ```374#[stable(feature ="rust1", since ="1.0.0")]375    #[inline]376pub fndowncast_ref<T: Any>(&self) ->Option<&T> {377        <dynAny>::downcast_ref::<T>(self)378    }379380/// Forwards to the method defined on the type `dyn Any`.381    ///382    /// # Examples383    ///384    /// ```385    /// use std::any::Any;386    ///387    /// fn modify_if_u32(s: &mut (dyn Any + Send)) {388    ///     if let Some(num) = s.downcast_mut::<u32>() {389    ///         *num = 42;390    ///     }391    /// }392    ///393    /// let mut x = 10u32;394    /// let mut s = "starlord".to_string();395    ///396    /// modify_if_u32(&mut x);397    /// modify_if_u32(&mut s);398    ///399    /// assert_eq!(x, 42);400    /// assert_eq!(&s, "starlord");401    /// ```402#[stable(feature ="rust1", since ="1.0.0")]403    #[inline]404pub fndowncast_mut<T: Any>(&mutself) ->Option<&mutT> {405        <dynAny>::downcast_mut::<T>(self)406    }407408/// Forwards to the method defined on the type `dyn Any`.409    ///410    /// # Examples411    ///412    /// ```413    /// #![feature(downcast_unchecked)]414    ///415    /// use std::any::Any;416    ///417    /// let x: Box<dyn Any> = Box::new(1_usize);418    ///419    /// unsafe {420    ///     assert_eq!(*x.downcast_unchecked_ref::<usize>(), 1);421    /// }422    /// ```423    ///424    /// # Safety425    ///426    /// The contained value must be of type `T`. Calling this method427    /// with the incorrect type is *undefined behavior*.428#[unstable(feature ="downcast_unchecked", issue ="90850")]429    #[inline]430pub unsafe fndowncast_unchecked_ref<T: Any>(&self) ->&T {431// SAFETY: guaranteed by caller432unsafe{ <dynAny>::downcast_unchecked_ref::<T>(self) }433    }434435/// Forwards to the method defined on the type `dyn Any`.436    ///437    /// # Examples438    ///439    /// ```440    /// #![feature(downcast_unchecked)]441    ///442    /// use std::any::Any;443    ///444    /// let mut x: Box<dyn Any> = Box::new(1_usize);445    ///446    /// unsafe {447    ///     *x.downcast_unchecked_mut::<usize>() += 1;448    /// }449    ///450    /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);451    /// ```452    ///453    /// # Safety454    ///455    /// The contained value must be of type `T`. Calling this method456    /// with the incorrect type is *undefined behavior*.457#[unstable(feature ="downcast_unchecked", issue ="90850")]458    #[inline]459pub unsafe fndowncast_unchecked_mut<T: Any>(&mutself) ->&mutT {460// SAFETY: guaranteed by caller461unsafe{ <dynAny>::downcast_unchecked_mut::<T>(self) }462    }463}464465impl dynAny + Send + Sync {466/// Forwards to the method defined on the type `Any`.467    ///468    /// # Examples469    ///470    /// ```471    /// use std::any::Any;472    ///473    /// fn is_string(s: &(dyn Any + Send + Sync)) {474    ///     if s.is::<String>() {475    ///         println!("It's a string!");476    ///     } else {477    ///         println!("Not a string...");478    ///     }479    /// }480    ///481    /// is_string(&0);482    /// is_string(&"cookie monster".to_string());483    /// ```484#[stable(feature ="any_send_sync_methods", since ="1.28.0")]485    #[inline]486pub fnis<T: Any>(&self) -> bool {487        <dynAny>::is::<T>(self)488    }489490/// Forwards to the method defined on the type `Any`.491    ///492    /// # Examples493    ///494    /// ```495    /// use std::any::Any;496    ///497    /// fn print_if_string(s: &(dyn Any + Send + Sync)) {498    ///     if let Some(string) = s.downcast_ref::<String>() {499    ///         println!("It's a string({}): '{}'", string.len(), string);500    ///     } else {501    ///         println!("Not a string...");502    ///     }503    /// }504    ///505    /// print_if_string(&0);506    /// print_if_string(&"cookie monster".to_string());507    /// ```508#[stable(feature ="any_send_sync_methods", since ="1.28.0")]509    #[inline]510pub fndowncast_ref<T: Any>(&self) ->Option<&T> {511        <dynAny>::downcast_ref::<T>(self)512    }513514/// Forwards to the method defined on the type `Any`.515    ///516    /// # Examples517    ///518    /// ```519    /// use std::any::Any;520    ///521    /// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) {522    ///     if let Some(num) = s.downcast_mut::<u32>() {523    ///         *num = 42;524    ///     }525    /// }526    ///527    /// let mut x = 10u32;528    /// let mut s = "starlord".to_string();529    ///530    /// modify_if_u32(&mut x);531    /// modify_if_u32(&mut s);532    ///533    /// assert_eq!(x, 42);534    /// assert_eq!(&s, "starlord");535    /// ```536#[stable(feature ="any_send_sync_methods", since ="1.28.0")]537    #[inline]538pub fndowncast_mut<T: Any>(&mutself) ->Option<&mutT> {539        <dynAny>::downcast_mut::<T>(self)540    }541542/// Forwards to the method defined on the type `Any`.543    ///544    /// # Examples545    ///546    /// ```547    /// #![feature(downcast_unchecked)]548    ///549    /// use std::any::Any;550    ///551    /// let x: Box<dyn Any> = Box::new(1_usize);552    ///553    /// unsafe {554    ///     assert_eq!(*x.downcast_unchecked_ref::<usize>(), 1);555    /// }556    /// ```557    /// # Safety558    ///559    /// The contained value must be of type `T`. Calling this method560    /// with the incorrect type is *undefined behavior*.561#[unstable(feature ="downcast_unchecked", issue ="90850")]562    #[inline]563pub unsafe fndowncast_unchecked_ref<T: Any>(&self) ->&T {564// SAFETY: guaranteed by caller565unsafe{ <dynAny>::downcast_unchecked_ref::<T>(self) }566    }567568/// Forwards to the method defined on the type `Any`.569    ///570    /// # Examples571    ///572    /// ```573    /// #![feature(downcast_unchecked)]574    ///575    /// use std::any::Any;576    ///577    /// let mut x: Box<dyn Any> = Box::new(1_usize);578    ///579    /// unsafe {580    ///     *x.downcast_unchecked_mut::<usize>() += 1;581    /// }582    ///583    /// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);584    /// ```585    /// # Safety586    ///587    /// The contained value must be of type `T`. Calling this method588    /// with the incorrect type is *undefined behavior*.589#[unstable(feature ="downcast_unchecked", issue ="90850")]590    #[inline]591pub unsafe fndowncast_unchecked_mut<T: Any>(&mutself) ->&mutT {592// SAFETY: guaranteed by caller593unsafe{ <dynAny>::downcast_unchecked_mut::<T>(self) }594    }595}596597///////////////////////////////////////////////////////////////////////////////598// TypeID and its methods599///////////////////////////////////////////////////////////////////////////////600601/// A `TypeId` represents a globally unique identifier for a type.602///603/// Each `TypeId` is an opaque object which does not allow inspection of what's604/// inside but does allow basic operations such as cloning, comparison,605/// printing, and showing.606///607/// A `TypeId` is currently only available for types which ascribe to `'static`,608/// but this limitation may be removed in the future.609///610/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth611/// noting that the hashes and ordering will vary between Rust releases. Beware612/// of relying on them inside of your code!613///614/// # Layout615///616/// Like other [`Rust`-representation][repr-rust] types, `TypeId`'s size and layout are unstable.617/// In particular, this means that you cannot rely on the size and layout of `TypeId` remaining the618/// same between Rust releases; they are subject to change without prior notice between Rust619/// releases.620///621/// [repr-rust]: https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.rust.unspecified622///623/// # Danger of Improper Variance624///625/// You might think that subtyping is impossible between two static types,626/// but this is false; there exists a static type with a static subtype.627/// To wit, `fn(&str)`, which is short for `for<'any> fn(&'any str)`, and628/// `fn(&'static str)`, are two distinct, static types, and yet,629/// `fn(&str)` is a subtype of `fn(&'static str)`, since any value of type630/// `fn(&str)` can be used where a value of type `fn(&'static str)` is needed.631///632/// This means that abstractions around `TypeId`, despite its633/// `'static` bound on arguments, still need to worry about unnecessary634/// and improper variance: it is advisable to strive for invariance635/// first. The usability impact will be negligible, while the reduction636/// in the risk of unsoundness will be most welcome.637///638/// ## Examples639///640/// Suppose `SubType` is a subtype of `SuperType`, that is,641/// a value of type `SubType` can be used wherever642/// a value of type `SuperType` is expected.643/// Suppose also that `CoVar<T>` is a generic type, which is covariant over `T`644/// (like many other types, including `PhantomData<T>` and `Vec<T>`).645///646/// Then, by covariance, `CoVar<SubType>` is a subtype of `CoVar<SuperType>`,647/// that is, a value of type `CoVar<SubType>` can be used wherever648/// a value of type `CoVar<SuperType>` is expected.649///650/// Then if `CoVar<SuperType>` relies on `TypeId::of::<SuperType>()` to uphold any invariants,651/// those invariants may be broken because a value of type `CoVar<SuperType>` can be created652/// without going through any of its methods, like so:653/// ```654/// type SubType = fn(&());655/// type SuperType = fn(&'static ());656/// type CoVar<T> = Vec<T>; // imagine something more complicated657///658/// let sub: CoVar<SubType> = CoVar::new();659/// // we have a `CoVar<SuperType>` instance without660/// // *ever* having called `CoVar::<SuperType>::new()`!661/// let fake_super: CoVar<SuperType> = sub;662/// ```663///664/// The following is an example program that tries to use `TypeId::of` to665/// implement a generic type `Unique<T>` that guarantees unique instances for each `Unique<T>`,666/// that is, and for each type `T` there can be at most one value of type `Unique<T>` at any time.667///668/// ```669/// mod unique {670///     use std::any::TypeId;671///     use std::collections::BTreeSet;672///     use std::marker::PhantomData;673///     use std::sync::Mutex;674///675///     static ID_SET: Mutex<BTreeSet<TypeId>> = Mutex::new(BTreeSet::new());676///677///     // TypeId has only covariant uses, which makes Unique covariant over TypeAsId 🚨678///     #[derive(Debug, PartialEq)]679///     pub struct Unique<TypeAsId: 'static>(680///         // private field prevents creation without `new` outside this module681///         PhantomData<TypeAsId>,682///     );683///684///     impl<TypeAsId: 'static> Unique<TypeAsId> {685///         pub fn new() -> Option<Self> {686///             let mut set = ID_SET.lock().unwrap();687///             (set.insert(TypeId::of::<TypeAsId>())).then(|| Self(PhantomData))688///         }689///     }690///691///     impl<TypeAsId: 'static> Drop for Unique<TypeAsId> {692///         fn drop(&mut self) {693///             let mut set = ID_SET.lock().unwrap();694///             (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected"));695///         }696///     }697/// }698///699/// use unique::Unique;700///701/// // `OtherRing` is a subtype of `TheOneRing`. Both are 'static, and thus have a TypeId.702/// type TheOneRing = fn(&'static ());703/// type OtherRing = fn(&());704///705/// fn main() {706///     let the_one_ring: Unique<TheOneRing> = Unique::new().unwrap();707///     assert_eq!(Unique::<TheOneRing>::new(), None);708///709///     let other_ring: Unique<OtherRing> = Unique::new().unwrap();710///     // Use that `Unique<OtherRing>` is a subtype of `Unique<TheOneRing>` 🚨711///     let fake_one_ring: Unique<TheOneRing> = other_ring;712///     assert_eq!(fake_one_ring, the_one_ring);713///714///     std::mem::forget(fake_one_ring);715/// }716/// ```717#[derive(Copy, PartialOrd, Ord)]718#[derive_const(Clone, Eq)]719#[stable(feature ="rust1", since ="1.0.0")]720#[lang ="type_id"]721pub structTypeId {722/// This needs to be an array of pointers, since there is provenance723    /// in the first array field. This provenance knows exactly which type724    /// the TypeId actually is, allowing CTFE and miri to operate based off it.725    /// At runtime all the pointers in the array contain bits of the hash, making726    /// the entire `TypeId` actually just be a `u128` hash of the type.727pub(crate) data: [*const();16/ size_of::<*const()>()],728}729730// SAFETY: the raw pointer is always an integer731#[stable(feature ="rust1", since ="1.0.0")]732unsafe implSendforTypeId {}733// SAFETY: the raw pointer is always an integer734#[stable(feature ="rust1", since ="1.0.0")]735unsafe implSyncforTypeId {}736737#[stable(feature ="rust1", since ="1.0.0")]738#[rustc_const_unstable(feature ="const_cmp", issue ="143800")]739impl constPartialEqforTypeId {740#[inline]741fneq(&self, other:&Self) -> bool {742#[cfg(miri)]743returncrate::intrinsics::type_id_eq(*self,*other);744#[cfg(not(miri))]745{746letthis =self;747crate::intrinsics::const_eval_select!(748                @capture { this:&TypeId, other:&TypeId } -> bool:749if const{750crate::intrinsics::type_id_eq(*this,*other)751                }else{752// Ideally we would just invoke `type_id_eq` unconditionally here,753                    // but since we do not MIR inline intrinsics, because backends754                    // may want to override them (and miri does!), MIR opts do not755                    // clean up this call sufficiently for LLVM to turn repeated calls756                    // of `TypeId` comparisons against one specific `TypeId` into757                    // a lookup table.758                    // SAFETY: We know that at runtime none of the bits have provenance and all bits759                    // are initialized. So we can just convert the whole thing to a `u128` and compare that.760unsafe{761crate::mem::transmute::<_, u128>(*this) ==crate::mem::transmute::<_, u128>(*other)762                    }763                }764            )765        }766    }767}768769implTypeId {770/// Returns the `TypeId` of the generic type parameter.771    ///772    /// # Examples773    ///774    /// ```775    /// use std::any::{Any, TypeId};776    ///777    /// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {778    ///     TypeId::of::<String>() == TypeId::of::<T>()779    /// }780    ///781    /// assert_eq!(is_string(&0), false);782    /// assert_eq!(is_string(&"cookie monster".to_string()), true);783    /// ```784#[must_use]785    #[stable(feature ="rust1", since ="1.0.0")]786    #[rustc_const_stable(feature ="const_type_id", since ="1.91.0")]787pub const fnof<T:?Sized +'static>() -> TypeId {788const{ intrinsics::type_id::<T>() }789    }790791fnas_u128(self) -> u128 {792letmutbytes = [0;16];793794// This is a provenance-stripping memcpy.795for(i, chunk)inself.data.iter().copied().enumerate() {796letchunk = chunk.addr().to_ne_bytes();797letstart = i * chunk.len();798            bytes[start..(start + chunk.len())].copy_from_slice(&chunk);799        }800        u128::from_ne_bytes(bytes)801    }802}803804#[stable(feature ="rust1", since ="1.0.0")]805implhash::HashforTypeId {806#[inline]807fnhash<H: hash::Hasher>(&self, state:&mutH) {808// We only hash the lower 64 bits of our (128 bit) internal numeric ID,809        // because:810        // - The hashing algorithm which backs `TypeId` is expected to be811        //   unbiased and high quality, meaning further mixing would be somewhat812        //   redundant compared to choosing (the lower) 64 bits arbitrarily.813        // - `Hasher::finish` returns a u64 anyway, so the extra entropy we'd814        //   get from hashing the full value would probably not be useful815        //   (especially given the previous point about the lower 64 bits being816        //   high quality on their own).817        // - It is correct to do so -- only hashing a subset of `self` is still818        //   compatible with an `Eq` implementation that considers the entire819        //   value, as ours does.820letdata =821// SAFETY: The `offset` stays in-bounds, it just moves the pointer to the 2nd half of the `TypeId`.822        // Only the first ptr-sized chunk ever has provenance, so that second half is always823        // fine to read at integer type.824unsafe{crate::ptr::read_unaligned(self.data.as_ptr().cast::<u64>().offset(1)) };825        data.hash(state);826    }827}828829#[stable(feature ="rust1", since ="1.0.0")]830implfmt::DebugforTypeId {831fnfmt(&self, f:&mutfmt::Formatter<'_>) ->Result<(), fmt::Error> {832write!(f,"TypeId({:#034x})",self.as_u128())833    }834}835836/// Returns the name of a type as a string slice.837///838/// # Note839///840/// This is intended for diagnostic use. The exact contents and format of the841/// string returned are not specified, other than being a best-effort842/// description of the type. For example, amongst the strings843/// that `type_name::<Option<String>>()` might return are `"Option<String>"` and844/// `"std::option::Option<std::string::String>"`.845///846/// The returned string must not be considered to be a unique identifier of a847/// type as multiple types may map to the same type name. Similarly, there is no848/// guarantee that all parts of a type will appear in the returned string. In849/// addition, the output may change between versions of the compiler. For850/// example, lifetime specifiers were omitted in some earlier versions.851///852/// The current implementation uses the same infrastructure as compiler853/// diagnostics and debuginfo, but this is not guaranteed.854///855/// # Examples856///857/// ```rust858/// assert_eq!(859///     std::any::type_name::<Option<String>>(),860///     "core::option::Option<alloc::string::String>",861/// );862/// ```863#[must_use]864#[stable(feature ="type_name", since ="1.38.0")]865#[rustc_const_unstable(feature ="const_type_name", issue ="63084")]866pub const fntype_name<T:?Sized>() ->&'staticstr {867const{ intrinsics::type_name::<T>() }868}869870/// Returns the type name of the pointed-to value as a string slice.871///872/// This is the same as `type_name::<T>()`, but can be used where the type of a873/// variable is not easily available.874///875/// # Note876///877/// Like [`type_name`], this is intended for diagnostic use and the exact output is not878/// guaranteed. It provides a best-effort description, but the output may change between879/// versions of the compiler.880///881/// In short: use this for debugging, avoid using the output to affect program behavior. More882/// information is available at [`type_name`].883///884/// Additionally, this function does not resolve trait objects. This means that885/// `type_name_of_val(&7u32 as &dyn Debug)` may return `"dyn Debug"`, but will not return `"u32"`886/// at this time.887///888/// # Examples889///890/// Prints the default integer and float types.891///892/// ```rust893/// use std::any::type_name_of_val;894///895/// let s = "foo";896/// let x: i32 = 1;897/// let y: f32 = 1.0;898///899/// assert!(type_name_of_val(&s).contains("str"));900/// assert!(type_name_of_val(&x).contains("i32"));901/// assert!(type_name_of_val(&y).contains("f32"));902/// ```903#[must_use]904#[stable(feature ="type_name_of_val", since ="1.76.0")]905#[rustc_const_unstable(feature ="const_type_name", issue ="63084")]906pub const fntype_name_of_val<T:?Sized>(_val:&T) ->&'staticstr {907    type_name::<T>()908}909910/// Returns `Some(&U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`.911///912/// # Compile-time failures913/// Determining whether `T` can be coerced to the trait object type `U` requires compiler trait resolution.914/// In some cases, that resolution can exceed the recursion limit,915/// and compilation will fail instead of this function returning `None`.916/// # Examples917///918/// ```rust919/// #![feature(try_as_dyn)]920///921/// use core::any::try_as_dyn;922///923/// trait Animal {924///     fn speak(&self) -> &'static str;925/// }926///927/// struct Dog;928/// impl Animal for Dog {929///     fn speak(&self) -> &'static str { "woof" }930/// }931///932/// struct Rock; // does not implement Animal933///934/// let dog = Dog;935/// let rock = Rock;936///937/// let as_animal: Option<&dyn Animal> = try_as_dyn::<Dog, dyn Animal>(&dog);938/// assert_eq!(as_animal.unwrap().speak(), "woof");939///940/// let not_an_animal: Option<&dyn Animal> = try_as_dyn::<Rock, dyn Animal>(&rock);941/// assert!(not_an_animal.is_none());942/// ```943#[must_use]944#[unstable(feature ="try_as_dyn", issue ="144361")]945pub const fntry_as_dyn<946    T: Any +'static,947    U: ptr::Pointee<Metadata = ptr::DynMetadata<U>> +?Sized +'static,948>(949    t:&T,950) ->Option<&U> {951letvtable:Option<ptr::DynMetadata<U>> =const{ intrinsics::vtable_for::<T, U>() };952matchvtable {953Some(dyn_metadata) => {954letpointer = ptr::from_raw_parts(t, dyn_metadata);955// SAFETY: `t` is a reference to a type, so we know it is valid.956            // `dyn_metadata` is a vtable for T, implementing the trait of `U`.957Some(unsafe{&*pointer })958        }959None=>None,960    }961}962963/// Returns `Some(&mut U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`.964///965/// # Compile-time failures966/// Determining whether `T` can be coerced to the trait object type `U` requires compiler trait resolution.967/// In some cases, that resolution can exceed the recursion limit,968/// and compilation will fail instead of this function returning `None`.969/// # Examples970///971/// ```rust972/// #![feature(try_as_dyn)]973///974/// use core::any::try_as_dyn_mut;975///976/// trait Animal {977///     fn speak(&self) -> &'static str;978/// }979///980/// struct Dog;981/// impl Animal for Dog {982///     fn speak(&self) -> &'static str { "woof" }983/// }984///985/// struct Rock; // does not implement Animal986///987/// let mut dog = Dog;988/// let mut rock = Rock;989///990/// let as_animal: Option<&mut dyn Animal> = try_as_dyn_mut::<Dog, dyn Animal>(&mut dog);991/// assert_eq!(as_animal.unwrap().speak(), "woof");992///993/// let not_an_animal: Option<&mut dyn Animal> = try_as_dyn_mut::<Rock, dyn Animal>(&mut rock);994/// assert!(not_an_animal.is_none());995/// ```996#[must_use]997#[unstable(feature ="try_as_dyn", issue ="144361")]998pub const fntry_as_dyn_mut<999    T: Any +'static,1000    U: ptr::Pointee<Metadata = ptr::DynMetadata<U>> +?Sized +'static,1001>(1002    t:&mutT,1003) ->Option<&mutU> {1004letvtable:Option<ptr::DynMetadata<U>> =const{ intrinsics::vtable_for::<T, U>() };1005matchvtable {1006Some(dyn_metadata) => {1007letpointer = ptr::from_raw_parts_mut(t, dyn_metadata);1008// SAFETY: `t` is a reference to a type, so we know it is valid.1009            // `dyn_metadata` is a vtable for T, implementing the trait of `U`.1010Some(unsafe{&mut *pointer })1011        }1012None=>None,1013    }1014}

[8]ページ先頭

©2009-2025 Movatter.jp