Skip to content

Commit 0356cc1

Browse files
authored
Merge pull request JuliaCollections#142 from mofeing/fix-type-instability-due-composition
Fix type-instabilities due to function composition
2 parents a3e43a8 + a4e4834 commit 0356cc1

File tree

4 files changed

+40
-40
lines changed

4 files changed

+40
-40
lines changed

src/base.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ or `parent(root, x) ≡ nothing`. That is, while any node is the root of some t
100100
true for nodes which have parents which cannot be obtained with the `AbstractTrees` interface.
101101
"""
102102
isroot(root, x) = isnothing(parent(root, x))
103-
isroot(x) = (isnothing parent)(x)
103+
isroot(x) = isnothing(parent(x))
104104

105105
"""
106106
intree(node, root; equiv=(≡))

src/cursors.jl

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ parenttype(csr::TreeCursor) = parenttype(typeof(csr))
6060
# this is a fallback and may not always be the case
6161
Base.IteratorSize(::Type{<:TreeCursor{N,P}}) where {N,P} = Base.IteratorSize(childrentype(N))
6262

63-
Base.length(tc::TreeCursor) = (length children nodevalue)(tc)
63+
Base.length(tc::TreeCursor) = length(children(nodevalue(tc)))
6464

6565
# this is needed in case an iterator declares IteratorSize to be HasSize
66-
Base.size(tc::TreeCursor) = (size children nodevalue)(tc)
66+
Base.size(tc::TreeCursor) = size(children(nodevalue(tc)))
6767

6868
Base.IteratorEltype(::Type{<:TreeCursor}) = EltypeUnknown()
6969

@@ -112,7 +112,7 @@ end
112112
TrivialCursor(node) = TrivialCursor(parent(node), node)
113113

114114
function Base.iterate(csr::TrivialCursor, s=InitialState())
115-
cs = (children nodevalue)(csr)
115+
cs = children(nodevalue(csr))
116116
r = s isa InitialState ? iterate(cs) : iterate(cs, s)
117117
isnothing(r) && return nothing
118118
(n′, s′) = r
@@ -159,12 +159,12 @@ function Base.eltype(::Type{ImplicitCursor{N,P,S}}) where {N,P,S}
159159
end
160160

161161
function Base.eltype(csr::ImplicitCursor)
162-
cst = (childstatetype parent nodevalue)(csr)
162+
cst = childstatetype(parent(nodevalue(csr)))
163163
ImplicitCursor{childtype(nodevalue(csr)),nodevaluetype(csr),cst}
164164
end
165165

166166
function Base.iterate(csr::ImplicitCursor, s=InitialState())
167-
cs = (children nodevalue)(csr)
167+
cs = children(nodevalue(csr))
168168
# do NOT just write an iterate(x, ::InitialState) method, it's an ambiguity nightmare
169169
r = s isa InitialState ? iterate(cs) : iterate(cs, s)
170170
isnothing(r) && return nothing
@@ -202,22 +202,22 @@ struct IndexedCursor{N,P} <: TreeCursor{N,P}
202202
IndexedCursor(p::Union{Nothing,IndexedCursor}, n, idx::Integer=1) = new{typeof(n),typeof(nodevalue(p))}(p, n, idx)
203203
end
204204

205-
IndexedCursor(node) = IndexedCursor(nothing, node)
205+
IndexedCursor(node) = IndexedCursor(nothing, node)
206206

207207
Base.IteratorSize(::Type{<:IndexedCursor}) = HasLength()
208208

209209
Base.eltype(::Type{IndexedCursor{N,P}}) where {N,P} = IndexedCursor{childtype(N),N}
210210
Base.eltype(csr::IndexedCursor) = IndexedCursor{childtype(nodevalue(csr)),nodevaluetype(csr)}
211-
Base.length(csr::IndexedCursor) = (length children nodevalue)(csr)
211+
Base.length(csr::IndexedCursor) = length(children(nodevalue(csr)))
212212

213213
function Base.getindex(csr::IndexedCursor, idx)
214-
cs = (children nodevalue)(csr)
214+
cs = children(nodevalue(csr))
215215
IndexedCursor(csr, cs[idx], idx)
216216
end
217217

218218
function Base.iterate(csr::IndexedCursor, idx=1)
219219
idx > length(csr) && return nothing
220-
(csr[idx], idx+1)
220+
(csr[idx], idx + 1)
221221
end
222222

223223
function nextsibling(csr::IndexedCursor)
@@ -254,7 +254,7 @@ Base.IteratorEltype(::Type{<:SiblingCursor}) = HasEltype()
254254
Base.eltype(::Type{SiblingCursor{N,P}}) where {N,P} = SiblingCursor{childtype(N),N}
255255

256256
function Base.iterate(csr::SiblingCursor, s=InitialState())
257-
cs = (children nodevalue)(csr)
257+
cs = children(nodevalue(csr))
258258
r = s isa InitialState ? iterate(cs) : iterate(cs, s)
259259
isnothing(r) && return nothing
260260
(n′, s′) = r
@@ -283,7 +283,7 @@ struct StableCursor{N,S} <: TreeCursor{N,N}
283283
# note that this very deliberately takes childstatetype(n) and *not* childstatetype(p)
284284
# this is because p may be nothing
285285
StableCursor(::Nothing, n, st) = new{typeof(n),childstatetype(n)}(nothing, n, st)
286-
286+
287287
# this method is important for eliminating expensive calls to childstatetype
288288
StableCursor(p::StableCursor{N,S}, n, st) where {N,S} = new{N,S}(p, n, st)
289289
end
@@ -295,7 +295,7 @@ Base.IteratorEltype(::Type{<:StableCursor}) = HasEltype()
295295
Base.eltype(::Type{T}) where {T<:StableCursor} = T
296296

297297
function Base.iterate(csr::StableCursor, s=InitialState())
298-
cs = (children nodevalue)(csr)
298+
cs = children(nodevalue(csr))
299299
r = s isa InitialState ? iterate(cs) : iterate(cs, s)
300300
isnothing(r) && return nothing
301301
(n′, s′) = r
@@ -331,16 +331,16 @@ Base.IteratorEltype(::Type{<:StableIndexedCursor}) = HasEltype()
331331

332332
Base.eltype(::Type{T}) where {T<:StableIndexedCursor} = T
333333

334-
Base.length(csr::StableIndexedCursor) = (length children nodevalue)(csr)
334+
Base.length(csr::StableIndexedCursor) = length(children(nodevalue(csr)))
335335

336336
function Base.getindex(csr::StableIndexedCursor, idx)
337-
cs = (children nodevalue)(csr)
337+
cs = children(nodevalue(csr))
338338
StableIndexedCursor(csr, cs[idx], idx)
339339
end
340340

341341
function Base.iterate(csr::StableIndexedCursor, idx=1)
342342
idx > length(csr) && return nothing
343-
(csr[idx], idx+1)
343+
(csr[idx], idx + 1)
344344
end
345345

346346
function nextsibling(csr::StableIndexedCursor)

src/iteration.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct PreOrderState{T<:TreeCursor} <: IteratorState{T}
100100
PreOrderState(csr::TreeCursor) = new{typeof(csr)}(csr)
101101
end
102102

103-
PreOrderState(node) = (PreOrderState TreeCursor)(node)
103+
PreOrderState(node) = PreOrderState(TreeCursor(node))
104104

105105
initial(::Type{PreOrderState}, node) = PreOrderState(node)
106106

@@ -175,9 +175,9 @@ struct PostOrderState{T<:TreeCursor} <: IteratorState{T}
175175
PostOrderState(csr::TreeCursor) = new{typeof(csr)}(csr)
176176
end
177177

178-
PostOrderState(node) = (PostOrderState TreeCursor)(node)
178+
PostOrderState(node) = PostOrderState(TreeCursor(node))
179179

180-
initial(::Type{PostOrderState}, node) = (PostOrderState descendleft TreeCursor)(node)
180+
initial(::Type{PostOrderState}, node) = PostOrderState(descendleft(TreeCursor(node)))
181181

182182
function next(s::PostOrderState)
183183
n = nextsibling(s.cursor)
@@ -226,9 +226,9 @@ struct LeavesState{T<:TreeCursor} <: IteratorState{T}
226226
LeavesState(csr::TreeCursor) = new{typeof(csr)}(csr)
227227
end
228228

229-
LeavesState(node) = (LeavesState TreeCursor)(node)
229+
LeavesState(node) = LeavesState(TreeCursor(node))
230230

231-
initial(::Type{LeavesState}, node) = (LeavesState descendleft TreeCursor)(node)
231+
initial(::Type{LeavesState}, node) = LeavesState(descendleft(TreeCursor(node)))
232232

233233
function next(s::LeavesState)
234234
csr = s.cursor
@@ -278,7 +278,7 @@ struct SiblingState{T<:TreeCursor} <: IteratorState{T}
278278
SiblingState(csr::TreeCursor) = new{typeof(csr)}(csr)
279279
end
280280

281-
SiblingState(node) = (SiblingState TreeCursor)(node)
281+
SiblingState(node) = SiblingState(TreeCursor(node))
282282

283283
initial(::Type{SiblingState}, node) = SiblingState(node)
284284

test/trees.jl

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using AbstractTrees
22
using Test
33

4-
include(joinpath(@__DIR__,"examples","idtree.jl"))
4+
include(joinpath(@__DIR__, "examples", "idtree.jl"))
55

66
@testset "IDTree" begin
77
tree = IDTree(1 => [
@@ -25,9 +25,9 @@ include(joinpath(@__DIR__,"examples","idtree.jl"))
2525

2626
# Node/subtree properties
2727
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
28-
@test treesize.(nodes) == [16, 4, 1, 2, 1, 1, 9, 8, 1, 1, 4, 1, 1, 1, 1, 1]
28+
@test treesize.(nodes) == [16, 4, 1, 2, 1, 1, 9, 8, 1, 1, 4, 1, 1, 1, 1, 1]
2929
@test treebreadth.(nodes) == [10, 2, 1, 1, 1, 1, 6, 6, 1, 1, 3, 1, 1, 1, 1, 1]
30-
@test treeheight.(nodes) == [ 4, 2, 0, 1, 0, 0, 3, 2, 0, 0, 1, 0, 0, 0, 0, 0]
30+
@test treeheight.(nodes) == [4, 2, 0, 1, 0, 0, 3, 2, 0, 0, 1, 0, 0, 0, 0, 0]
3131

3232
# Child/descendant checking
3333
@test ischild(nodes[2], nodes[1])
@@ -61,44 +61,44 @@ include(joinpath(@__DIR__,"examples","idtree.jl"))
6161
@test [n.id for n in Leaves(tree.root)] == [3, 5, 6, 9, 10, 12, 13, 14, 15, 16]
6262
end
6363

64-
include(joinpath(@__DIR__,"examples","onenode.jl"))
64+
include(joinpath(@__DIR__, "examples", "onenode.jl"))
6565

6666
@testset "OneNode" begin
67-
ot = OneNode([2,3,4,0], 1)
67+
ot = OneNode([2, 3, 4, 0], 1)
6868
@inferred collect(Leaves(ot))
6969
@test nodevalue.(collect(Leaves(ot))) == [0]
7070
@test eltype(nodevalue.(collect(Leaves(ot)))) Int
71-
@test nodevalue.(collect(PreOrderDFS(ot))) == [2,3,4,0]
72-
@test nodevalue.(collect(PostOrderDFS(ot))) == [0,4,3,2]
71+
@test nodevalue.(collect(PreOrderDFS(ot))) == [2, 3, 4, 0]
72+
@test nodevalue.(collect(PostOrderDFS(ot))) == [0, 4, 3, 2]
7373
end
7474

75-
include(joinpath(@__DIR__,"examples","onetree.jl"))
75+
include(joinpath(@__DIR__, "examples", "onetree.jl"))
7676

7777
@testset "OneTree" begin
78-
ot = OneTree([2,3,4,0])
78+
ot = OneTree([2, 3, 4, 0])
7979
n = IndexNode(ot)
8080

8181
@inferred collect(Leaves(n))
8282
@test nodevalue.(collect(Leaves(n))) == [0]
8383
@test eltype(nodevalue.(collect(Leaves(n)))) Int
84-
@test nodevalue.(collect(PreOrderDFS(n))) == [2,3,4,0]
85-
@test nodevalue.(collect(PostOrderDFS(n))) == [0,4,3,2]
84+
@test nodevalue.(collect(PreOrderDFS(n))) == [2, 3, 4, 0]
85+
@test nodevalue.(collect(PostOrderDFS(n))) == [0, 4, 3, 2]
8686
end
8787

88-
include(joinpath(@__DIR__,"examples","fstree.jl"))
88+
include(joinpath(@__DIR__, "examples", "fstree.jl"))
8989

9090
@testset "FSNode" begin
9191
Base.VERSION >= v"1.6" && mk_tree_test_dir() do path
9292
tree = Directory(".")
9393

94-
ls = nodevalue.((collect Leaves)(tree))
94+
ls = nodevalue.(collect(Leaves(tree)))
9595
# use set so we don't have to guarantee ordering
96-
@test Set(ls) == Set([joinpath(".","A","f2"), joinpath(".","B"), joinpath(".","f1")])
96+
@test Set(ls) == Set([joinpath(".", "A", "f2"), joinpath(".", "B"), joinpath(".", "f1")])
9797
@test treeheight(tree) == 2
9898
end
9999
end
100100

101-
include(joinpath(@__DIR__,"examples","binarytree.jl"))
101+
include(joinpath(@__DIR__, "examples", "binarytree.jl"))
102102

103103
@testset "BinaryNode" begin
104104
t = binarynode_example()
@@ -107,12 +107,12 @@ include(joinpath(@__DIR__,"examples","binarytree.jl"))
107107
@test nodevalue.(ls) == [3, 2]
108108

109109
predfs = @inferred collect(PreOrderDFS(t))
110-
@test nodevalue.(predfs) == [0,1,3,2]
110+
@test nodevalue.(predfs) == [0, 1, 3, 2]
111111

112112
postdfs = @inferred collect(PostOrderDFS(t))
113-
@test nodevalue.(postdfs) == [3,1,2,0]
113+
@test nodevalue.(postdfs) == [3, 1, 2, 0]
114114

115115
sbfs = @inferred collect(StatelessBFS(t))
116-
@test nodevalue.(sbfs) == [0,1,2,3]
116+
@test nodevalue.(sbfs) == [0, 1, 2, 3]
117117
end
118118

0 commit comments

Comments
 (0)