I am puzzled by this
julia> test(flag) = flag ? 1.0 : 1
test (generic function with 2 methods)
julia> @code_warntype test(true)
Variables
#self#::Core.Compiler.Const(test, false)
flag::Bool
Body::Union{Float64, Int64}
1 ─ goto #4 if not flag
2 ─ return 1.0
3 ─ Core.Compiler.Const(:(goto %5), false)
4 ┄ false
└── return 1
Is flag
being constant-propagated here? Why is the return type of this particular call test(true)
not inferred? Or is constant propagation orthogonal to inference?
Wrap in a function:
julia> test(flag) = flag ? 1.0 : 1
test (generic function with 1 method)
julia> f() = test(true)
f (generic function with 1 method)
julia> @code_warntype f()
Variables
#self#::Core.Compiler.Const(f, false)
Body::Float64
1 ─ %1 = Main.test(true)::Core.Compiler.Const(1.0, false)
└── return %1
2 Likes
Oh! Why is this? Isn’t true
a compile-time constant here? (Still slightly puzzled…)
@code_warntype test(true)
gets macro expanded to
code_warntype(test, Tuple{Bool})
where clearly, all information that the bool was a constant true
has been lost.
4 Likes
Aaaaah! Got it now… Many thanks to both!
If I may, just a quick followup: why doesn’t this work with kwargs?
julia> test(; flag = true) = flag ? 1.0 : 1
test (generic function with 1 method)
julia> f() = test(flag = true)
f (generic function with 1 method)
julia> @code_warntype f()
Variables
#self#::Core.Compiler.Const(f, false)
Body::Union{Float64, Int64}
1 ─ %1 = (:flag,)::Core.Compiler.Const((:flag,), false)
│ %2 = Core.apply_type(Core.NamedTuple, %1)::Core.Compiler.Const(NamedTuple{(:flag,),T} where T<:Tuple, false)
│ %3 = Core.tuple(true)::Core.Compiler.Const((true,), false)
│ %4 = (%2)(%3)::NamedTuple{(:flag,),Tuple{Bool}}
│ %5 = Core.kwfunc(Main.test)::Core.Compiler.Const(getfield(Main, Symbol("#kw##test"))(), false)
│ %6 = (%5)(%4, Main.test)::Union{Float64, Int64}
└── return %6
Curiously, however
julia> f() = test()
f (generic function with 1 method)
julia> @code_warntype f()
Variables
#self#::Core.Compiler.Const(f, false)
Body::Float64
1 ─ %1 = Main.test()::Core.Compiler.Const(1.0, false)
└── return %1
2 Likes