Skip to content

Commit fc0da43

Browse files
yebaiclaude
andcommitted
Polish evaluator API: public stubs, docstrings, AD-missing hints
- Mark generate_testcases / run_testcases as public (1.11+) so downstream AD-backend packages can reuse the conformance suite without reaching into private API. - Note in the Prepared docstring that the two-arg constructor is for backends that allocate fresh storage per call. - Expand the _ad_output_arity error message to call out matrix/tuple outputs explicitly and recommend flattening. - Add a MethodError hint on value_and_gradient!! / value_and_jacobian!! that fires when no AD backend extension is loaded — also surfaces through LogDensityProblems.logdensity_and_gradient, which delegates to value_and_gradient!!. Suppressed once any backend registers a method, where the standard candidate list is more informative. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0378609 commit fc0da43

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

src/AbstractPPL.jl

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,21 @@ include("abstractprobprog.jl")
1212
include("evaluate.jl")
1313
include("evaluators/Evaluators.jl")
1414
using .Evaluators: prepare, value_and_gradient!!, value_and_jacobian!!
15-
@static if VERSION >= v"1.11.0"
16-
eval(Meta.parse("public prepare, value_and_gradient!!, value_and_jacobian!!"))
17-
end
1815

19-
# Stubs implemented by `AbstractPPLTestExt` (loaded with `Test`).
16+
# Stubs implemented by `AbstractPPLTestExt` (loaded with `Test`). Part of the
17+
# public API for downstream AD-backend packages that want to reuse the shared
18+
# conformance suite in their own test setups.
2019
function generate_testcases end
2120
function run_testcases end
2221

22+
@static if VERSION >= v"1.11.0"
23+
eval(
24+
Meta.parse(
25+
"public prepare, value_and_gradient!!, value_and_jacobian!!, generate_testcases, run_testcases",
26+
),
27+
)
28+
end
29+
2330
include("varname/optic.jl")
2431
include("varname/varname.jl")
2532
include("varname/subsumes.jl")

src/evaluators/Evaluators.jl

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ AD-prepared evaluator parameterised by backend type `AD`.
1616
`NamedTupleEvaluator`); forwarded on `p(x)`.
1717
- `cache` — backend-specific pre-allocated state (ForwardDiff configs, Mooncake
1818
caches, DifferentiationInterface preps, etc.). `Nothing` when the backend requires
19-
no cached state.
19+
no cached state. The two-argument constructor is for backends that allocate
20+
fresh storage on every `value_and_gradient!!` call.
2021
2122
Extension packages implement `value_and_gradient!!` (and optionally
2223
`value_and_jacobian!!`) by specialising on the `cache` type:
@@ -219,7 +220,7 @@ function _ad_output_arity(y)
219220
y isa AbstractVector && return :vector
220221
throw(
221222
ArgumentError(
222-
"A prepared AD evaluator must return a scalar or AbstractVector; got $(typeof(y)).",
223+
"A prepared AD evaluator must return a scalar (`Number`) or `AbstractVector`; got $(typeof(y)). Matrix- or tuple-valued outputs are not supported — flatten into a vector before returning.",
223224
),
224225
)
225226
end
@@ -272,6 +273,19 @@ function __init__()
272273
"\nCalling `prepare` with an AD backend requires loading the corresponding extension (e.g., `using DifferentiationInterface`).",
273274
)
274275
end
276+
# `value_and_gradient!!` / `value_and_jacobian!!` are stubs until an AD
277+
# backend extension adds methods. Suppress the hint once any backend is
278+
# loaded — the standard `MethodError` candidate list is then more useful
279+
# than a generic "load an extension" message. Also fires when reached via
280+
# `LogDensityProblems.logdensity_and_gradient`, which delegates here.
281+
Base.Experimental.register_error_hint(MethodError) do io, exc, args, kwargs
282+
exc.f === value_and_gradient!! || exc.f === value_and_jacobian!! || return nothing
283+
isempty(methods(exc.f)) || return nothing
284+
print(
285+
io,
286+
"\nNo AD backend extension is loaded. Load `DifferentiationInterface` (with a backend like `ForwardDiff`) or `Mooncake` to enable gradient/jacobian computation.",
287+
)
288+
end
275289
end
276290

277291
end # module

0 commit comments

Comments
 (0)