You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Plate-local alias in symbolic UDF return size emits an out-of-scope declaration #60
A plate cell may bind an input to a local name before calling a helper whose declared vector return length depends on that input. The local alias causes the emitted outer storage declaration to refer to a name outside its scope. The same helper call with the input passed directly emits ragged per-cell storage and compiles.
Verified at StanBlocks commit 75d9feb41f6f9148799c4c1f3236aacd5bdfdf7c with Julia 1.10.12.
Minimal reproducer
using StanBlocks
StanBlocks.@deffunbeginalias_probe_cell(reads::int[n])::vector[max(reads)] =rep_vector(1.0, max(reads))
end
data = (; reads=[[1, 2], [1, 2, 3]], y=[1.0, 1.0])
alias_model = StanBlocks.@slic data begin
out ~plate(reads, y; outer=(2,)) do reads, y
local_reads = reads
conc =alias_probe_cell(local_reads)
y ~normal(conc[1], 1.0)
conc[2]
endend
direct_model = StanBlocks.@slic data begin
out ~plate(reads, y; outer=(2,)) do reads, y
conc =alias_probe_cell(reads)
y ~normal(conc[1], 1.0)
conc[2]
endendfor (label, model) in (("alias", alias_model), ("direct", direct_model))
result = StanBlocks.stanc_check(StanBlocks.stan_code(model); warn_pedantic=false)
println(label, ": ", result.ok)
end
Observed output: alias: false, direct: true. The alias case emits matrix[max(out_local_reads), 2] out_conc; in transformed data, then stanc reports Identifier "out_local_reads" not in scope. The direct case emits per-cell lengths and a ragged out_conc__pl_mem_1 carrier and passes stanc.
Expected: the local alias retains the same per-cell return length as its input, with valid ragged storage. The two calls have the same helper arguments and model meaning.
This occurs in a pure StanBlocks model; no application-specific code or data are required.
Fixed on devibe by 3896a56. That commit builds on the per-cell size inference from f711046 and adds a follow-up that keeps the outer input sizes when plate parameters shadow the data names, as do reads, y does above.
At that commit, with Julia 1.10.12, the reproducer above prints alias: true and direct: true. The alias case now emits per-cell lengths and ragged storage, like the direct case.
Activity
nsiccha commentedon Oct 12, 2026
Fixed on
devibeby 3896a56. That commit builds on the per-cell size inference from f711046 and adds a follow-up that keeps the outer input sizes when plate parameters shadow the data names, asdo reads, ydoes above.At that commit, with Julia 1.10.12, the reproducer above prints
alias: trueanddirect: true. The alias case now emits per-cell lengths and ragged storage, like the direct case.