Compare commits

..

No commits in common. "master" and "rocq_hdl" have entirely different histories.

2 changed files with 18 additions and 75 deletions

View file

@ -2396,16 +2396,13 @@ impl ModuleBuilder {
#[track_caller]
pub fn extern_module_simulation_fn<
Args: fmt::Debug + Clone + Hash + Eq + Send + Sync + 'static,
F: Copy + Fn(Args, crate::sim::ExternModuleSimulationState) -> Fut + Send + Sync + 'static,
Fut: IntoFuture<Output = ()> + 'static,
>(
&self,
args: Args,
f: F,
f: fn(Args, crate::sim::ExternModuleSimulationState) -> Fut,
) {
// use for compile-time side-effect
let _ = crate::sim::SimGeneratorFn::<Args, F, Fut>::ASSERT_F_IS_ZERO_SIZED;
self.extern_module_simulation(crate::sim::SimGeneratorFn::new(args, f));
self.extern_module_simulation(crate::sim::SimGeneratorFn { args, f });
}
}

View file

@ -54,6 +54,7 @@ use std::{
hash::Hash,
mem,
pin::{Pin, pin},
ptr,
rc::Rc,
sync::{Arc, Mutex, MutexGuard},
task::Poll,
@ -4064,48 +4065,13 @@ pub trait ExternModuleSimGenerator: Clone + Eq + Hash + Any + Send + Sync + fmt:
fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a;
}
/// Type requirements: `F` must be zero-sized, this guarantees that the function called
/// by `F` is entirely determined by the type `F` and not by its value, allowing us to
/// correctly leave `F` out of the stuff used for `Hash` and `Eq`.
///
/// Note we can't just use function pointers instead -- comparing them is non-deterministic
/// since Rust will duplicate and/or merge functions, even if those functions happen to have
/// different UB but just happen to compile to the same assembly language:
/// <https://github.com/rust-lang/unsafe-code-guidelines/issues/589#issuecomment-3515424930>
pub struct SimGeneratorFn<Args, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> {
args: Args,
f: F,
pub struct SimGeneratorFn<Args, Fut> {
pub args: Args,
pub f: fn(Args, ExternModuleSimulationState) -> Fut,
}
impl<Args, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut>
SimGeneratorFn<Args, F, Fut>
{
pub const ASSERT_F_IS_ZERO_SIZED: () = {
if size_of::<F>() != 0 {
panic!(
"F must be zero-sized -- so it must be a closure with no captures or a function item, it can't be a function pointer"
);
}
};
pub const fn new(args: Args, f: F) -> Self {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
Self { args, f }
}
pub const fn args(&self) -> &Args {
&self.args
}
pub const fn f(&self) -> F {
self.f
}
}
impl<Args: fmt::Debug, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> fmt::Debug
for SimGeneratorFn<Args, F, Fut>
{
impl<Args: fmt::Debug, Fut> fmt::Debug for SimGeneratorFn<Args, Fut> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
let Self { args, f: _ } = self;
f.debug_struct("SimGeneratorFn")
.field("args", args)
@ -4114,39 +4080,25 @@ impl<Args: fmt::Debug, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, F
}
}
impl<Args: Hash, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Hash
for SimGeneratorFn<Args, F, Fut>
{
impl<Args: Hash, Fut> Hash for SimGeneratorFn<Args, Fut> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
let Self { args, f: _ } = self;
let Self { args, f } = self;
args.hash(state);
f.hash(state);
}
}
impl<Args: Eq, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Eq
for SimGeneratorFn<Args, F, Fut>
{
}
impl<Args: Eq, Fut> Eq for SimGeneratorFn<Args, Fut> {}
impl<Args: PartialEq, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> PartialEq
for SimGeneratorFn<Args, F, Fut>
{
impl<Args: PartialEq, Fut> PartialEq for SimGeneratorFn<Args, Fut> {
fn eq(&self, other: &Self) -> bool {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
let Self { args, f: _ } = self;
*args == other.args
let Self { args, f } = self;
*args == other.args && ptr::fn_addr_eq(*f, other.f)
}
}
impl<Args: Clone, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Clone
for SimGeneratorFn<Args, F, Fut>
{
impl<Args: Clone, Fut> Clone for SimGeneratorFn<Args, Fut> {
fn clone(&self) -> Self {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
Self {
args: self.args.clone(),
f: self.f,
@ -4154,20 +4106,14 @@ impl<Args: Clone, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> C
}
}
impl<Args: Copy, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Copy
for SimGeneratorFn<Args, F, Fut>
{
}
impl<Args: Copy, Fut> Copy for SimGeneratorFn<Args, Fut> {}
impl<
Args: fmt::Debug + Clone + Eq + Hash + Send + Sync + 'static,
F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut + Send + Sync + 'static,
T: fmt::Debug + Clone + Eq + Hash + Send + Sync + 'static,
Fut: IntoFuture<Output = ()> + 'static,
> ExternModuleSimGenerator for SimGeneratorFn<Args, F, Fut>
> ExternModuleSimGenerator for SimGeneratorFn<T, Fut>
{
fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
(self.f)(self.args.clone(), sim)
}
}