Better type_eq (#2946)
* typeid that doesn't suck * actually, that's not const! * format, move phantomdata to alloc feature block * a --------- Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com>
This commit is contained in:
parent
abe955137f
commit
83d88546d3
@ -120,6 +120,7 @@ strum = "0.26.3"
|
||||
strum_macros = "0.26.4"
|
||||
toml = "0.8.19" # For parsing the injections toml file
|
||||
typed-builder = "0.20.0" # Implement the builder pattern at compiletime
|
||||
typeid = "1.0.0" # Safe type_eq that doesn't rely on std specialization
|
||||
uuid = { version = "1.10.0", features = ["serde", "v4"] }
|
||||
which = "6.0.3"
|
||||
windows = "0.59.0"
|
||||
|
@ -122,6 +122,7 @@ rustversion = { workspace = true }
|
||||
[dependencies]
|
||||
libafl_derive = { workspace = true, default-features = true, optional = true }
|
||||
static_assertions = { workspace = true }
|
||||
typeid = { workspace = true }
|
||||
|
||||
tuple_list = { version = "0.1.3" }
|
||||
hashbrown = { workspace = true, features = [
|
||||
|
@ -6,9 +6,10 @@ use alloc::{borrow::Cow, vec::Vec};
|
||||
use core::{
|
||||
any::type_name,
|
||||
fmt::{Debug, Formatter},
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut, Index, IndexMut},
|
||||
};
|
||||
use core::{any::TypeId, cell::Cell, marker::PhantomData, mem::transmute};
|
||||
use core::{any::TypeId, mem::transmute};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -21,36 +22,9 @@ use crate::HasLen;
|
||||
use crate::Named;
|
||||
|
||||
/// Returns if the type `T` is equal to `U`, ignoring lifetimes.
|
||||
#[inline] // this entire call gets optimized away :)
|
||||
#[must_use]
|
||||
pub fn type_eq<T: ?Sized, U: ?Sized>() -> bool {
|
||||
// decider struct: hold a cell (which we will update if the types are unequal) and some
|
||||
// phantom data using a function pointer to allow for Copy to be implemented
|
||||
struct W<'a, T: ?Sized, U: ?Sized>(&'a Cell<bool>, PhantomData<fn() -> (&'a T, &'a U)>);
|
||||
|
||||
// default implementation: if the types are unequal, we will use the clone implementation
|
||||
impl<T: ?Sized, U: ?Sized> Clone for W<'_, T, U> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
// indicate that the types are unequal
|
||||
// unfortunately, use of interior mutability (Cell) makes this not const-compatible
|
||||
// not really possible to get around at this time
|
||||
self.0.set(false);
|
||||
W(self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
// specialized implementation: Copy is only implemented if the types are the same
|
||||
#[expect(clippy::mismatching_type_param_order)]
|
||||
impl<T: ?Sized> Copy for W<'_, T, T> {}
|
||||
|
||||
let detected = Cell::new(true);
|
||||
// [].clone() is *specialized* in core.
|
||||
// Types which implement copy will have their copy implementations used, falling back to clone.
|
||||
// If the types are the same, then our clone implementation (which sets our Cell to false)
|
||||
// will never be called, meaning that our Cell's content remains true.
|
||||
let res = [W::<T, U>(&detected, PhantomData)].clone();
|
||||
res[0].0.get()
|
||||
typeid::of::<T>() == typeid::of::<U>()
|
||||
}
|
||||
|
||||
/// Borrow each member of the tuple
|
||||
@ -955,8 +929,6 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
#[expect(unused_qualifications)] // for type name tests
|
||||
fn test_type_eq() {
|
||||
// An alias for equality testing
|
||||
type OwnedMutSliceAlias<'a> = OwnedMutSlice<'a, u8>;
|
||||
@ -976,15 +948,6 @@ mod test {
|
||||
// test weirder lifetime things
|
||||
assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u8>>());
|
||||
assert!(!type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u32>>());
|
||||
|
||||
assert!(type_eq::<
|
||||
OwnedMutSlice<u8>,
|
||||
crate::ownedref::OwnedMutSlice<u8>,
|
||||
>());
|
||||
assert!(!type_eq::<
|
||||
OwnedMutSlice<u8>,
|
||||
crate::ownedref::OwnedMutSlice<u32>,
|
||||
>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user