1.13: docstring on two const OffsetVectors

I have a program which I think was working in Julia 1.12, but when I upgraded to 1.13 it fails to compile. The offending lines are these:

"""
    ptable::OffsetArray(::Vector{UInt16}, 0:1023)

Given the ten-bit code for a permutation, look up the 15-bit permoct code if it's
canonical, and another ten-bit code for the same permutation, with the high bit
set, if it isn't. Repeated lookup of codes with the high bit set will eventually
find the canonical code.
"""
const (ptable,invPerm)=makeperms()

ptable and invPerm are both OffsetVectors with indices from 0 to 1023. How can I rewrite it so that it compiles?

What error do you get? How and where is makeperms defined? Is it your own analysis or an LLM that has located these lines as problematic?

(Yes, many questions, but there’s just not nearly enough information to venture any answers.)

ERROR: LoadError: Could not find something to document in `(ptable, invPerm)`.

<snip long series of backtrace in code I didn’t write>

in expression starting at /home/phma/src/MumzelCode/src/MumzelCode.jl:307
in expression starting at /home/phma/src/MumzelCode/src/MumzelCode.jl:20
in expression starting at stdin:5

307 is the line number of the start of the docstring.

This is my own analysis. I do not use LLMs; it is forbidden.

Reduced example:

julia> """
       it's a
       """
       a = 1
1

julia> """
       it's (b, c)
       """
       (b, c) = (2, 3)
ERROR: LoadError: Could not find something to document in `(b, c)`.

Documenting variables with explicit docstrings is not common, but appears to be legal for a single assignment in v1.13. If it was legal to document a destructured (i.e., multi-variable) assignment before, it isn’t any more.

This might be a new parser bug or it might be fixing something that never made sense to begin with. What did it do (i.e., what did the docstring get attached to?) in previous versions?

You can still do

bc = (2, 3)
"""
document b
"""
const b = bc[1]
const c = bc[2]

It’s not exactly beautiful but

@doc """
    ptable::OffsetArray(::Vector{UInt16}, 0:1023)

Given the ten-bit code for a permutation, look up the 15-bit permoct code if it's
canonical, and another ten-bit code for the same permutation, with the high bit
set, if it isn't. Repeated lookup of codes with the high bit set will eventually
find the canonical code.
""" ptable
const (ptable,invPerm)=makeperms()

seems to work.

If I saw the original code, I would have no idea why ptable was being documented; I would have thought that the tuple (ptable,invPerm) has somehow documented with that, which is surely not what anyone would want. Personally, I would regard this as something that shouldn’t have parsed in 1.12.

But Julia already supplies a way to document things separately from their definition. You don’t need to use @doc (unless you would otherwise), and you can put the documentation before or after the definition of the thing, and they don’t need to be smooshed together like @GunnarFarneback’s version. IMO, something like this would be much more readable.

"""
    ptable::OffsetArray(::Vector{UInt16}, 0:1023)

Given the ten-bit code for a permutation, look up the 15-bit permoct code if it's
canonical, and another ten-bit code for the same permutation, with the high bit
set, if it isn't. Repeated lookup of codes with the high bit set will eventually
find the canonical code.
"""
ptable

# You could put more code in here if you want...

const (ptable,invPerm)=makeperms()

This works, putting ptable after const (ptable, invPerm), as putting it before would be using the constant before defining it.

It works both ways. Documenting ptable isn’t the same as defining it.

If it makes more sense to you to have the documentation go later, that’s fine.