Skip to content

Replace Weak<Trace> in proposals with a borrowed &Trace #9

Description

@agarret7

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions