Stream: helpdesk (published)

Topic: ✔ Tracking down "multiple type declarations"


view this post on Zulip Chad Scherrer (Apr 19 2022 at 13:08):

I have some code leading to this error:

julia> logdensityof(m(x), rand(m(x)))
ERROR: syntax: multiple type declarations for "x"
Stacktrace:
 [1] top-level scope
   @ REPL[74]:1

That's it, pretty useless stack trace. I could see this if you just type garbage at the REPL prompt, but I think what I entered is ok:

julia> dump(:(logdensityof(m(x), rand(m(x)))))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol logdensityof
    2: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol m
        2: Symbol x
    3: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol rand
        2: Expr
          head: Symbol call
          args: Array{Any}((2,))
            1: Symbol m
            2: Symbol x

Has anyone seen this before? Why no real stack trace? How can I even begin to debug this?

view this post on Zulip Chad Scherrer (Apr 19 2022 at 13:32):

This seems to come from this line of julia-syntax.scm:

        ((decl)
         ;; handle var::T declaration by storing the type in the var-info
         ;; record. for non-symbols or globals, emit a type assertion.
         (let ((vi (get tab (cadr e) #f)))
           (if vi
               (begin (if (not (equal? (vinfo:type vi) '(core Any)))
                          (error (string "multiple type declarations for \""
                                         (cadr e) "\"")))
                      (if (assq (cadr e) captvars)
                          (error (string "type of \"" (cadr e)
                                         "\" declared in inner scope")))
                      (vinfo:set-type! vi (caddr e))))))

But it's still not clear why the stack trace is so broken

view this post on Zulip Sebastian Pfitzner (Apr 19 2022 at 13:33):

Is this a revise issue? The line you pasted isn't related to the error at all, no?

view this post on Zulip Chad Scherrer (Apr 19 2022 at 13:34):

Revise seems happy, as far as I can tell

view this post on Zulip Chad Scherrer (Apr 19 2022 at 13:35):

Maybe a parser bug? I mean, I may well have an error, but it's getting the stack trace wrong

view this post on Zulip Sebastian Pfitzner (Apr 19 2022 at 13:36):

can you repro this in a fresh session?

view this post on Zulip Chad Scherrer (Apr 19 2022 at 13:38):

Yes

view this post on Zulip Takafumi Arakaki (tkf) (Apr 19 2022 at 14:44):

You can check that the code typed in the REPL is syntactically fine

julia> logdensityof = m = x = rand = Returns(123);

julia> logdensityof(m(x), rand(m(x)))
123

I agree that the stacktrace is not informative though

view this post on Zulip Mason Protter (Apr 19 2022 at 14:47):

Can you reproduce it in a session started as julia --startup=no?

view this post on Zulip Takafumi Arakaki (tkf) (Apr 19 2022 at 14:50):

Just as yet another sanity check, did you try renaming the variable x to something else? Does the syntax error still report the variable name x? (Otherwise, maybe it's from some dynamically-generated code?)

Also, did you try evaluating the sub-expressions one by one?

(I know that these are kind of stupid things to ask but the error in the OP is very mind-boggling...)

view this post on Zulip Chad Scherrer (Apr 19 2022 at 14:51):

It's tricky, because the problem is in a generated function. I've just tricked it into printing what's generated instead of executing it, having a look at that now

view this post on Zulip Chad Scherrer (Apr 19 2022 at 14:55):

It comes down to

begin
    begin
        $(Expr(:meta, :inline))
        local _retn
        _args = argvals(_mc)
        _obs = observations(_mc)
        _cfg = merge(_cfg, (args = _args, obs = _obs, pars = _pars))
        x::Vector{Float64} = _args.x
        x::Vector{Float64} = _pars.x
        #= /home/chad/git/Tilde.jl/src/primitives/interpret.jl:52 =#
        (x, _ctx, _retn) = tilde(unsafe_logdensityof, (Accessors.opticcompose)((Accessors.IndexLens)((1,))), static(:x), x, Normal(), _cfg, _ctx)
        #= /home/chad/git/Tilde.jl/src/primitives/interpret.jl:53 =#
        isa(_retn, ReturnNow) && return _retn.value
        for j = :(:)(2, length(x))
            begin
                #= /home/chad/git/Tilde.jl/src/primitives/interpret.jl:52 =#
                (x, _ctx, _retn) = tilde(unsafe_logdensityof, (Accessors.opticcompose)((Accessors.IndexLens)((j,))), static(:x), x, Normal(μ = x[:-(j, 1)]), _cfg, _ctx)
                #= /home/chad/git/Tilde.jl/src/primitives/interpret.jl:53 =#
                isa(_retn, ReturnNow) && return _retn.value
            end
        end
        _retn
    end
end

This could use a little cleaning up, but I wouldn't think it would lead to the error I'm getting

view this post on Zulip Chad Scherrer (Apr 19 2022 at 14:57):

Can you reproduce it in a session started as julia --startup=no?

I'll try that soon. FWIW my startup.jl is

atreplinit() do repl
    repl.options.iocontext[:compact] = true
end

view this post on Zulip Chad Scherrer (Apr 19 2022 at 15:11):

It works for some models:

julia> m1 = @model begin
           a ~ Uniform()
           b ~ Normal(a,2)
       end;

julia> r = rand(m1())
(a = 0.652999, b = 3.04375)

julia> logdensityof(m1(), r)
-2.32655

But then

julia> m2 = @model x begin
           x[1] ~ Normal()
           for j in 2:length(x)
               x[j] ~ Normal(μ = x[j-1])
           end
       end;

julia> x = zeros(4);

julia> r2 = rand(m2(x))
(x = [0.333947, 1.06483, 2.35892, 1.45661],)

julia> logdensityof(m2(x), r2)
ERROR: syntax: multiple type declarations for "x"
Stacktrace:
 [1] top-level scope
   @ REPL[160]:1

It's not specific to x

julia> m2 = @model y begin
           y[1] ~ Normal()
           for j in 2:length(y)
               y[j] ~ Normal(μ = y[j-1])
           end
       end;

julia> y = zeros(4);

julia> r2 = rand(m2(x))
(y = [0.0852394, 0.492802, 0.68513, 0.760316],)

julia> logdensityof(m2(y), r2)
ERROR: syntax: multiple type declarations for "y"
Stacktrace:
 [1] top-level scope
   @ REPL[164]:1

view this post on Zulip Chad Scherrer (Apr 19 2022 at 16:10):

I think I got it. I pass in named tuples for arguments, observations, and parameters. Then in the generated function, I push some lines like

:($k::$T = _pars.$k)

I thought maybe I needed to get rid of the type annotation, but I think it might work out better to make sure the variable is treated as local. So I added

    for k in keys(args)  keys(pars)  keys(data)
        push!(loader.args, :(local $k))
    end

and I think that fixes things. Thanks all for the helpful discussion :smile:

view this post on Zulip Notification Bot (Apr 19 2022 at 16:10):

Chad Scherrer has marked this topic as resolved.


Last updated: Nov 06 2024 at 04:40 UTC