How to detect variables of type `Any` at compiletime?

I want a macro that detects (and makes the function fail or warns me) if some variable is not inferred correctly, if the variable’s type is inferred, then it should do nothing.
E.g. something like this:

j = 3
function f(x)
    for i in 1:100 
        @warn_any j
        x += j
    end
    return x
end

can you use @inferred to do what you want? That is,

using Base.Test
function bad(x)
    innerbad(x) = if rand() < 0.5 x else true end
    @inferred innerbad(x)
end

julia> bad(4)
ERROR: return type Int64 does not match inferred return type Union{Bool, Int64}
2 Likes

I did not understand why should @inferred fail here, while

julia> Int64 <: Union{Bool, Int64}
true

is true. ???

@inferred tests for equality (as per docs).

Thanks for the tip with @inferred, your code still does the checking at runtime and not compiletime. There is no easy way to give just a warning, but this one quite close to what I want:

macro typestable(x)
    Base.Test.@inferred eval(:(()->$x))()
    return :()
end

const k = 3
l = 3

function f1(x)
    @typestable(k)
    for i in 1:10
        x += k - 1
    end
    return x
end

function f2(x)
    @typestable(l)
    for i in 1:10
        x = x + l
    end
    return x
end

Throws an error when sourcing f2 and gives very nice LLVM assembly for f1:

julia> function f2(x)
+    @typestable(l)
+    for i in 1:10
+        x = x + l
+    end
+    return x
end
ERROR: return type Int64 does not match inferred return type Any

julia> @code_llvm f1(19)

define i64 @julia_f1_71937(i64) #0 {
top:
  %1 = add i64 %0, 20
  ret i64 %1
}