Repository navigation
Conversation
`Union{}` is a subtype of every type, so `Vector{Union{}}` matched
`dictlike(::Type{<:AbstractVector{<:Pair}}) = true` while `arraylike`
was also `true` for it. `make` checks `dictlike` first, so an empty
`Union{}`-element vector (e.g. JSON3.jl's empty arrays) was built via
the dict path. Add a more specific `dictlike` method returning `false`
so the traits agree that such a vector is an (always empty) array.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`make(Union{}, source)` fell into the `T <: Tuple` branch (Union{} is a
subtype of everything) and failed inside `fieldcount` with an unrelated
"does not have a well-defined number of fields" message. Check for the
bottom type up front and throw a dedicated, type-free ArgumentError.
Also mention the AbstractVector{<:Pair} rule and the Vector{Union{}}
exception in the `dictlike` docstring, and replace two union-selection
tests that passed with or without the fix by `make!` and error-message
checks.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Union{}is a subtype of every type, soVector{Union{}} <: AbstractVector{<:Pair}holds andmatches it, while
arraylike(::Type{<:AbstractArray}) = truematches it too. The two traits disagree for a type that can only ever be an empty array, andmakechecksdictlikefirst, so such vectors are built throughmakedict(andmake!on one goes through the dict path as well).This adds a more specific method:
Before / after:
Observable behaviour is nearly identical since the vector is always empty:
make(Vector{Union{}}, [])andmake(Vector{Union{}}, Dict())still returnUnion{}[], and a non-empty source still throws. The point is trait consistency for downstream consumers that branch ondictlikebeforearraylikethe waymakedoes. This surfaced while fixing JuliaIO/JSON.jl#499, where the sameUnion{} <: Pairsubtyping made JSON.jl writeUnion{}[]as{}(fixed on the JSON.jl side in JuliaIO/JSON.jl#500; that fix does not depend on this one).The other
Pair-vector special cases here (applyeach,_keytype,_valtype) use the invariantAbstractVector{Pair{K,V}}and are not affected.Test.detect_ambiguities(StructUtils)is unchanged (1 default, 51 withambiguous_bottom=true). Full test suite passes locally on Julia 1.12.7, including the trim-compile stage.Second commit, from a self-review pass:
make(Union{}, source)(reached e.g. viamake(Vector{Union{}}, [1])) used to fall into theT <: Tuplebranch and die insidefieldcount(Union{})with "The empty type does not have a well-defined number of fields". It now throws a dedicated, type-freeArgumentError("cannot make a value of typeUnion{}because it has no instances")from a@noinlinehelper, same shape as_absentfield_error. TheT === Union{}check constant-folds away for every otherT.dictlikedocstring now mentions theAbstractVector{<:Pair}rule and theUnion{}exception.Union{Vector{Union{}}, Dict}selection assertions that passed with or without the fix (union disambiguation only consultsarraylike) for amake!check and the exact error messages.One thing I left for you to decide:
dictlike(::Type{<:AbstractVector{<:Pair}})is covariant, but every consumer of a dictlike Pair vector (applyeach,_keytype/_valtype,addkeyval!) only handles the invariantAbstractVector{Pair{K,V}}, so e.g.make(Vector{Pair}, Dict("a" => 1))fails onliftkey(Int, "a")andmake(Vector{<:Pair}, ...)has no(undef, 0)constructor. Tightening the rule toAbstractVector{Pair{K,V}} where {K,V}would also make theUnion{}special case unnecessary, but it changes whatdictlike(Vector{<:Pair})reports, so I kept the narrower fix here.🤖 Generated with Claude Code