JuliaLang / julia

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

Vararg affecting constant propagation #55042

Open MilesCranmer opened 2 weeks ago

MilesCranmer commented 2 weeks ago

It seems like constant propagation is affected by a vararg, even if typed to ::Vararg{Any,N} which I would expect to force specialization via this page of the docs.

call1(f::F, x, y) where {F} = f(x, y)
call2(f::F, x, y...) where {F} = f(x, y...)
call3(f::F, x, y::Vararg{Any,N}) where {F,N} = f(x, y...)

g1(a) = call1(isa, a, Int) ? a : 0
g2(a) = call2(isa, a, Int) ? a : 0
g3(a) = call3(isa, a, Int) ? a : 0

Constant propagation only happens through call1, but call2 and call3 block it:

julia> Base.return_types(g1, (Any,))
1-element Vector{Any}:
 Int64

julia> Base.return_types(g2, (Any,))
1-element Vector{Any}:
 Any

julia> Base.return_types(g3, (Any,))
1-element Vector{Any}:
 Any
nsajko commented 2 weeks ago

The effect inference seems fine. I guess this is just the usual limitation of #29368:

julia> typeof((Int,))
Tuple{DataType}

julia> typeof((Int,)) <: Tuple{Type{Int}}
false
MilesCranmer commented 2 weeks ago

I guess im also surprised it doesn’t inline it

(Is there any general way to force specialisation for a Vararg which includes types? There is this but it seems to only work if all the Vararg is types)