That explanation is a bit off actually, it's not that f1 can't optimize for t, it's that f1 has to do method lookup every time it's called.
type X; x::Int end g1(x) = x.x+1 g2(x::X) = x.x+1 x = X(1) const y = X(1) @code_warntype g1(x) #... # begin # return (Base.box)(Int64,(Base.add_int)((Core.getfield)(x::X,:x)::Int64,1)) # end::Int64 @code_warntype g2(x) #... # begin # return (Base.box)(Int64,(Base.add_int)((Core.getfield)(x::X,:x)::Int64,1)) # end::Int64 # same generated code, but... h1() = g1(x) h2() = g2(x) @code_warntype h1() # ... # begin # SSAValue(0) = Main.x # return ((Core.getfield)(SSAValue(0),:x)::Any + 1)::Any # end::Any @code_warntype h2() # ... # begin # return (Main.g2)(Main.x)::Int64 # end::Int64 # The specialized method can't be found beforehand on h1! @timeit h1() # 1000000 loops, best of 3: 228.03 ns per loop # 2.28028349e-7 @timeit h2() # 1000000 loops, best of 3: 185.79 ns per loop # 1.85790018e-7 You probably already know this, but correcting my wrong info and explaining it makes me feel better :P
