JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.42k stars 5.45k forks source link

`isconst` has surprising and undocumented edge case behaviours #53493

Open jakobnissen opened 6 months ago

jakobnissen commented 6 months ago

Examples:

julia> isconst(BitSet, :ajkhfd) # non-existent field
true

julia> mutable struct Foo
           const x::Int
       end

julia> isconst(Union{BitSet, Foo}, 1) # is actually true, but type is Union
false

Neither of these behaviours are documented. I think it would be better if it threw for non-DataType types, (since its result is meaningless when applied to other kinds of types), or perhaps returned some sentinel value like nothing. At the very least, if the current edge case behaviour is considered best, then it should be documented.

vtjnash commented 6 months ago

I think more concerning is that it also reports that abstract types have only constant-field subtypes:

julia> isconst(Any, 1)
true

Actually, this one is documented (in the code at least):

julia> isconst(BitSet, :ajkhfd) # non-existent field

Since a non-existent field always returns the same value (it always throws), its value is consistent

jakobnissen commented 6 months ago

Since a non-existent field always returns the same value (it always throws), its value is consistent

Ah, I see. The purpose of the function is to check for consistent behaviour (for the compiler, perhaps?). From a user POV, It's not very clear from the documentation that the intended use of the function is to answer "does loading this field result in a consistent value", rather than "is this field declared as a const of this type"? The documentation seems to imply the latter. And if that's the latter, then a non-existent field is certainly not declared const because it's not declared at all.