Ah, I see the problem now. This eluded me for a bit. The problem is that you’re using
::Union{Element, Nothing}
for the field next. This looks like a small union, but it’s actually not because Element is really Element{T} where {T}, a UnionAll!
Here’s a modified version of your code that doesn’t allocate and is two orders of magnitude faster:
abstract type AbstractElement end
mutable struct Element{T<:AbstractElement} <: AbstractElement
input::String
name::UnitRange{Int64}
attributes::Union{Nothing, Int}
value::Union{T, Nothing}
parent::Union{Element{T}, Nothing}
next::Union{Element{T}, Nothing}
end
example(node::Element) = begin
while !isnothing(node)
if node.name == 1:1 return node end
node = node.next
end
return error("error")
end
first = Element{Element}("", 2:2, nothing, nothing, nothing, nothing)
second = Element{Element}("", 1:1, nothing, nothing, nothing, nothing)
first.next = second
@btime example($first)
#+RESULTS:
3.110 ns (0 allocations: 0 bytes)
Element{Element}("", 1:1, nothing, nothing, nothing, nothing)