From e5366a21ee5a458a66e9db5ab1fe3f1f66eab006 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 18 Jun 2022 11:10:09 +0200 Subject: [PATCH] fix generics --- .../src/lib.rs | 28 +++++++++-- examples/one.rs | 7 +-- src/lib.rs | 50 +++++++++++++------ 3 files changed, 62 insertions(+), 23 deletions(-) diff --git a/accursed-unutterable-type-id-derive/src/lib.rs b/accursed-unutterable-type-id-derive/src/lib.rs index 53fd4ab..d9937ee 100644 --- a/accursed-unutterable-type-id-derive/src/lib.rs +++ b/accursed-unutterable-type-id-derive/src/lib.rs @@ -39,7 +39,7 @@ pub fn my_macro(input: TokenStream) -> TokenStream { let new_value = old .checked_add(1) - .unwrap_or_else(|| fail("integer overflow. you have too many derives")); + .unwrap_or_else(|| fail("integer overflow. use cargo clean. if the problem persists, you have way too many derives, the fuck")); fs::write(&file_path, new_value.to_string()) .unwrap_or_else(|_| fail("failed to write new number")); @@ -51,7 +51,7 @@ pub fn my_macro(input: TokenStream) -> TokenStream { GenericParam::Type(ty) => { let name = &ty.ident; let bounds = ty.bounds.iter(); - quote!(#name: #(#bounds +)* 'static) + quote!(#name: #(#bounds +)* ::accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified + 'static) } other => other.to_token_stream(), }); @@ -63,16 +63,38 @@ pub fn my_macro(input: TokenStream) -> TokenStream { let where_clause = input.generics.where_clause; + let ty_param_ids = input.generics.params.iter().filter_map(|p| match p { + GenericParam::Lifetime(_) => None, + GenericParam::Type(ty) => { + let name = &ty.ident; + Some(quote! { + ::accursed_unutterable_type_id::AccursedUnutterableTypeId::of::<#name>() + }) + } + GenericParam::Const(_) => Some(quote!(compile_error!( + "const generics are not supported yet" + ))), + }); + // SAFETY: We literally are the proc macro. and we have made sure that no duplicate type ids // will ever happen, right? :ferrisClueless: let expanded = quote! { unsafe impl<#(#generics1),*> ::accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified for #name<#(#generics2),*> #where_clause { + #[allow(unused_mut)] fn type_id() -> ::accursed_unutterable_type_id::AccursedUnutterableTypeId { + let mut hasher = ::std::collections::hash_map::DefaultHasher::new(); + + #( + ::std::hash::Hash::hash(&#ty_param_ids, &mut hasher); + )* + + let value = <::std::collections::hash_map::DefaultHasher as ::std::hash::Hasher>::finish(&hasher); + ::accursed_unutterable_type_id::AccursedUnutterableTypeId::__internal_new( ::accursed_unutterable_type_id::InternalAccursedUnutterableTypeId::__internal_new( - #new_value + #new_value, value, ) ) } diff --git a/examples/one.rs b/examples/one.rs index 6eb25b5..dc960c6 100644 --- a/examples/one.rs +++ b/examples/one.rs @@ -1,11 +1,8 @@ use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified; #[derive(AccursedUnutterablyTypeIdentified)] -struct Uwu -where - T: 'static, -{ - _x: [T; N], +struct Uwu { + _x: T, } fn main() {} diff --git a/src/lib.rs b/src/lib.rs index bf0fd6e..017d92c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,10 @@ //! println!("{type_id:?}") //! ``` -use std::fmt::{Debug, Formatter}; +use std::{ + fmt::{Debug, Formatter}, + hash::Hash, +}; pub use accursed_unutterable_type_id_derive::AccursedUnutterablyTypeIdentified; @@ -66,30 +69,30 @@ impl AccursedUnutterableTypeId { #[doc(hidden)] #[cfg(debug_assertions)] // we do a little trolling -pub struct InternalAccursedUnutterableTypeId(u128, u64); +pub struct InternalAccursedUnutterableTypeId(u128, u64, u64); #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[doc(hidden)] #[cfg(not(debug_assertions))] -pub struct InternalAccursedUnutterableTypeId(u64); +pub struct InternalAccursedUnutterableTypeId(u64, u64); #[cfg(debug_assertions)] impl InternalAccursedUnutterableTypeId { - pub fn __internal_new(n: u64) -> Self { - Self(0, n) + pub fn __internal_new(s: u64, g: u64) -> Self { + Self(0, s, g) } - fn inner(self) -> u64 { - self.1 + fn inner(self) -> (u64, u64) { + (self.1, self.2) } } #[cfg(not(debug_assertions))] impl InternalAccursedUnutterableTypeId { - pub fn __internal_new(n: u64) -> Self { - Self(n) + pub fn __internal_new(s: u64, g: u64) -> Self { + Self(s, g) } - fn inner(self) -> u64 { - self.0 + fn inner(self) -> (u64, u64) { + (self.0, self.1) } } @@ -130,8 +133,8 @@ mod __doctest { /// use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified; /// /// #[derive(AccursedUnutterablyTypeIdentified)] - /// struct Uwu { - /// _x: [T; N], + /// struct Uwu { + /// _x: [T; /* N */ 0], /// } /// ``` mod complex {} @@ -142,8 +145,8 @@ mod __doctest { /// trait Sussy {} /// /// #[derive(AccursedUnutterablyTypeIdentified)] - /// struct Uwu { - /// _x: [T; N], + /// struct Uwu { + /// _x: T, /// } /// ``` mod type_bounds {} @@ -167,4 +170,21 @@ mod __doctest { /// } /// ``` mod where_clause {} + + /// ``` + /// use accursed_unutterable_type_id::{AccursedUnutterableTypeId as Id, AccursedUnutterablyTypeIdentified}; + /// + /// #[derive(AccursedUnutterablyTypeIdentified)] + /// struct Uwu { + /// _x: T, + /// } + /// + /// #[derive(AccursedUnutterablyTypeIdentified)] + /// struct A; + /// #[derive(AccursedUnutterablyTypeIdentified)] + /// struct B; + /// + /// assert_ne!(Id::of::>(), Id::of::>()); + /// ``` + mod type_param {} }