Question about constant propagation and inference

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…)

See eg

1 Like
@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