-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Enable frozen_abi on banking trace file #33501
Changes from 9 commits
5e3a8a8
c875a1a
4a34a58
368d5a5
f5bdb30
56111b7
2230884
bd5e2cc
b564f05
fd6c28d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -137,25 +137,12 @@ tuple_example_impls! { | |
| } | ||
| } | ||
|
|
||
| // Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/array/mod.rs#L417 | ||
| macro_rules! array_example_impls { | ||
| {$n:expr, $t:ident $($ts:ident)*} => { | ||
| impl<T> AbiExample for [T; $n] where T: AbiExample { | ||
| fn example() -> Self { | ||
| [$t::example(), $($ts::example()),*] | ||
| } | ||
| } | ||
| array_example_impls!{($n - 1), $($ts)*} | ||
| }; | ||
| {$n:expr,} => { | ||
| impl<T> AbiExample for [T; $n] { | ||
| fn example() -> Self { [] } | ||
| } | ||
| }; | ||
| impl<const N: usize, T: AbiExample> AbiExample for [T; N] { | ||
| fn example() -> Self { | ||
| std::array::from_fn(|_| T::example()) | ||
| } | ||
| } | ||
|
Comment on lines
158
to
162
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. elegance of const generics... off-topic: really wish Default is reimplementd like this as soon as possible...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes please, I get so annoyed at the lack of Default whenever I use a fixed byte-buffer size |
||
|
|
||
| array_example_impls! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} | ||
|
|
||
| // Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/default.rs#L137 | ||
| macro_rules! example_impls { | ||
| ($t:ty, $v:expr) => { | ||
|
|
@@ -232,7 +219,14 @@ impl<T: BlockType> AbiExample for BitVec<T> { | |
| } | ||
|
|
||
| impl<T: BlockType> IgnoreAsHelper for BitVec<T> {} | ||
| impl<T: BlockType> EvenAsOpaque for BitVec<T> {} | ||
| // This (EvenAsOpaque) marker trait is needed for BitVec because we can't impl AbiExample for its | ||
| // private type: | ||
| // thread '...TestBitVec_frozen_abi...' panicked at ...: | ||
| // derive or implement AbiExample/AbiEnumVisitor for | ||
| // bv::bit_vec::inner::Inner<u64> | ||
| impl<T: BlockType> EvenAsOpaque for BitVec<T> { | ||
| const TYPE_NAME_MATCHER: &'static str = "bv::bit_vec::inner::"; | ||
| } | ||
|
|
||
| pub(crate) fn normalize_type_name(type_name: &str) -> String { | ||
| type_name.chars().filter(|c| *c != '&').collect() | ||
|
|
@@ -329,13 +323,38 @@ impl<T: AbiExample> AbiExample for std::sync::Arc<T> { | |
| } | ||
| } | ||
|
|
||
| // When T is weakly owned by the likes of `std::{sync, rc}::Weak`s, we need to uphold the ownership | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Appreciate the explanation here. However, I'm not super clear on why we need to have the implementations for #[serde(skip)]
recycler: Weak<RecyclerX<PinnedVec<T>>>,so shouldn't this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
another good question. yeah, some unspoken nuances are lying here... ;) i did my best to answer that in patch: fd6c28d
yep, i noticed this bug in as you correctly pointed out, |
||
| // of T in some way at least during abi digesting... However, there's no easy way. Stashing them | ||
| // into static is confronted with Send/Sync issue. Stashing them into thread_local is confronted | ||
| // with not enough (T + 'static) lifetime bound.. So, just leak the examples. This should be | ||
| // tolerated, considering ::example() should ever be called inside tests, not in production code... | ||
| fn leak_and_inhibit_drop<'a, T>(t: T) -> &'a mut T { | ||
| Box::leak(Box::new(t)) | ||
| } | ||
|
|
||
| impl<T: AbiExample> AbiExample for std::sync::Weak<T> { | ||
| fn example() -> Self { | ||
| info!("AbiExample for (Arc's Weak<T>): {}", type_name::<Self>()); | ||
| // leaking is needed otherwise Arc::upgrade() will always return None... | ||
| std::sync::Arc::downgrade(leak_and_inhibit_drop(std::sync::Arc::new(T::example()))) | ||
| } | ||
| } | ||
|
|
||
| impl<T: AbiExample> AbiExample for std::rc::Rc<T> { | ||
| fn example() -> Self { | ||
| info!("AbiExample for (Rc<T>): {}", type_name::<Self>()); | ||
| std::rc::Rc::new(T::example()) | ||
| } | ||
| } | ||
|
|
||
| impl<T: AbiExample> AbiExample for std::rc::Weak<T> { | ||
| fn example() -> Self { | ||
| info!("AbiExample for (Rc's Weak<T>): {}", type_name::<Self>()); | ||
| // leaking is needed otherwise Rc::upgrade() will always return None... | ||
| std::rc::Rc::downgrade(leak_and_inhibit_drop(std::rc::Rc::new(T::example()))) | ||
| } | ||
| } | ||
|
|
||
| impl<T: AbiExample> AbiExample for std::sync::Mutex<T> { | ||
| fn example() -> Self { | ||
| info!("AbiExample for (Mutex<T>): {}", type_name::<Self>()); | ||
|
|
@@ -457,6 +476,13 @@ impl AbiExample for std::path::PathBuf { | |
| } | ||
| } | ||
|
|
||
| #[cfg(not(target_os = "solana"))] | ||
| impl AbiExample for std::time::SystemTime { | ||
| fn example() -> Self { | ||
| std::time::SystemTime::UNIX_EPOCH | ||
| } | ||
| } | ||
|
|
||
| use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | ||
| impl AbiExample for SocketAddr { | ||
| fn example() -> Self { | ||
|
|
@@ -470,13 +496,22 @@ impl AbiExample for IpAddr { | |
| } | ||
| } | ||
|
|
||
| // This is a control flow indirection needed for digesting all variants of an enum | ||
| // This is a control flow indirection needed for digesting all variants of an enum. | ||
| // | ||
| // All of types (including non-enums) will be processed by this trait, albeit the | ||
| // name of this trait. | ||
| // User-defined enums usually just need to impl this with namesake derive macro (AbiEnumVisitor). | ||
| // | ||
| // Note that sometimes this indirection doesn't work for various reasons. For that end, there are | ||
| // hacks with marker traits (IgnoreAsHelper/EvenAsOpaque). | ||
| pub trait AbiEnumVisitor: Serialize { | ||
| fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult; | ||
| } | ||
|
|
||
| pub trait IgnoreAsHelper {} | ||
| pub trait EvenAsOpaque {} | ||
| pub trait EvenAsOpaque { | ||
| const TYPE_NAME_MATCHER: &'static str; | ||
| } | ||
|
|
||
| impl<T: Serialize + ?Sized> AbiEnumVisitor for T { | ||
| default fn visit_for_abi(&self, _digester: &mut AbiDigester) -> DigestResult { | ||
|
|
@@ -489,7 +524,9 @@ impl<T: Serialize + ?Sized> AbiEnumVisitor for T { | |
|
|
||
| impl<T: Serialize + ?Sized + AbiExample> AbiEnumVisitor for T { | ||
| default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult { | ||
| info!("AbiEnumVisitor for (default): {}", type_name::<T>()); | ||
| info!("AbiEnumVisitor for T: {}", type_name::<T>()); | ||
| // not calling self.serialize(...) is intentional here as the most generic impl | ||
| // consider IgnoreAsHelper and EvenAsOpaque if you're stuck on this.... | ||
| T::example() | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instantiating
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well, i was wrong... 35dd93725ff1caa45287ae5644fcb3bbd255b983 |
||
| .serialize(digester.create_new()) | ||
| .map_err(DigestError::wrap_by_type::<T>) | ||
|
|
@@ -501,7 +538,7 @@ impl<T: Serialize + ?Sized + AbiExample> AbiEnumVisitor for T { | |
| // relevant test: TestVecEnum | ||
| impl<T: Serialize + ?Sized + AbiEnumVisitor> AbiEnumVisitor for &T { | ||
| default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult { | ||
| info!("AbiEnumVisitor for (&default): {}", type_name::<T>()); | ||
| info!("AbiEnumVisitor for &T: {}", type_name::<T>()); | ||
| // Don't call self.visit_for_abi(...) to avoid the infinite recursion! | ||
| T::visit_for_abi(self, digester) | ||
| } | ||
|
|
@@ -521,9 +558,13 @@ impl<T: Serialize + IgnoreAsHelper> AbiEnumVisitor for &T { | |
| // inability of implementing AbiExample for private structs from other crates | ||
| impl<T: Serialize + IgnoreAsHelper + EvenAsOpaque> AbiEnumVisitor for &T { | ||
| default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult { | ||
| info!("AbiEnumVisitor for (IgnoreAsOpaque): {}", type_name::<T>()); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this |
||
| let top_scope = type_name::<T>().split("::").next().unwrap(); | ||
| self.serialize(digester.create_new_opaque(top_scope)) | ||
| let type_name = type_name::<T>(); | ||
| let matcher = T::TYPE_NAME_MATCHER; | ||
| info!( | ||
| "AbiEnumVisitor for (EvenAsOpaque): {}: matcher: {}", | ||
| type_name, matcher | ||
| ); | ||
| self.serialize(digester.create_new_opaque(matcher)) | ||
| .map_err(DigestError::wrap_by_type::<T>) | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| extern crate rustc_version; | ||
| use rustc_version::{version_meta, Channel}; | ||
|
|
||
| fn main() { | ||
| #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | ||
| { | ||
|
|
@@ -8,4 +11,27 @@ fn main() { | |
| println!("cargo:rustc-cfg=build_target_feature_avx2"); | ||
| } | ||
| } | ||
|
|
||
| // Copied and adapted from | ||
| // https://github.com/Kimundi/rustc-version-rs/blob/1d692a965f4e48a8cb72e82cda953107c0d22f47/README.md#example | ||
| // Licensed under Apache-2.0 + MIT | ||
| match version_meta().unwrap().channel { | ||
| Channel::Stable => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITHOUT_SPECIALIZATION"); | ||
| } | ||
| Channel::Beta => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITHOUT_SPECIALIZATION"); | ||
| } | ||
| Channel::Nightly => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITH_SPECIALIZATION"); | ||
| } | ||
| Channel::Dev => { | ||
| println!("cargo:rustc-cfg=RUSTC_WITH_SPECIALIZATION"); | ||
| // See https://github.com/solana-labs/solana/issues/11055 | ||
| // We may be running the custom `rust-bpf-builder` toolchain, | ||
| // which currently needs `#![feature(proc_macro_hygiene)]` to | ||
| // be applied. | ||
| println!("cargo:rustc-cfg=RUSTC_NEEDS_PROC_MACRO_HYGIENE"); | ||
| } | ||
| } | ||
|
Comment on lines
15
to
36
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. copy-pasta without shame because of existing |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as you can see, enabling frozen_abi for banking trace files wasn't so joyful... xD