Description
metropolis_hastings/mh currently require proposal functions to take a Weak<Trace<...>> as their first argument, and dyngen! special-cases this shape via ty_is_trace_ref. The Weak only exists because DynGenFn<Args, Ret> stores a plain fn pointer with no lifetime parameter, forcing Args: 'static. mh upgrades/downgrades an Arc to hand the proposal temporary read access to the trace and reclaim ownership after.
A cleaner design is possible: for the proposal shape specifically, have dyngen! emit a zero-sized marker type with a generic impl<'p> GenFn<(&'p Trace<...>, ProposalArgs), ...> (delegating to the existing DynGenFn impl) instead of a const DynGenFn<...> value. Unlike const items, impl blocks can be generic over a lifetime, so this satisfies mh's for<'a> GenFn<(&'a Trace<...>, _), _, ()> bound directly.
New Proposal Use Pattern
// before
dyngen!(
pub fn drift_proposal(tr: Weak<DynTrace<Vec<Real>, Vec<Real>>>, drift: Real) {
let tr = tr.upgrade().unwrap();
normal(tr.data.read::<Real>("a"), drift) %= "a";
}
);
// after
dyngen!(
pub fn drift_proposal(tr: &DynTrace<Vec<Real>, Vec<Real>>, drift: Real) {
normal(tr.data.read::<Real>("a"), drift) %= "a";
}
);
Scope is contained: DynGenFn is used as a concrete (non-generic) type in only one other place (DynUnfold::kernel), which is untouched since it isn't proposal-shaped. This is a breaking change to modppl-macros/mh's public signature and should ship as a new release.
Description
metropolis_hastings/mh currently require proposal functions to take a Weak<Trace<...>> as their first argument, and dyngen! special-cases this shape via ty_is_trace_ref. The Weak only exists because DynGenFn<Args, Ret> stores a plain fn pointer with no lifetime parameter, forcing Args: 'static. mh upgrades/downgrades an Arc to hand the proposal temporary read access to the trace and reclaim ownership after.
A cleaner design is possible: for the proposal shape specifically, have dyngen! emit a zero-sized marker type with a generic impl<'p> GenFn<(&'p Trace<...>, ProposalArgs), ...> (delegating to the existing DynGenFn impl) instead of a const DynGenFn<...> value. Unlike const items, impl blocks can be generic over a lifetime, so this satisfies mh's for<'a> GenFn<(&'a Trace<...>, _), _, ()> bound directly.
New Proposal Use Pattern
Scope is contained: DynGenFn is used as a concrete (non-generic) type in only one other place (DynUnfold::kernel), which is untouched since it isn't proposal-shaped. This is a breaking change to modppl-macros/mh's public signature and should ship as a new release.