You are right, nothing obvious in the code will change. However, my personal advantage would be that if I want to write an AOT compilable function I get assistance from the language and the compiler:
-
from the language because I can simply look up which functions I could call to preserve type stability (obviously all which are marked with
@typestable). E.g., when calling some standard library function likeBase.randn(), how should I know a priori if this function is intended to be type stable without testing it (for all possible variants in which I’m using it)? -
from the compiler because if I mess up my own function it should warn me that type stability can not be inferred, e.g., simple example:
@typestable foo(x::Number) = x<1 ? 0 : 1.0
AOTcompile(foo, (Int32,) ) #error: type instability detected Union{Int64,Float64}
#or in REPL
foo(3) #error: type instability detected Union{Int64,Float64}
returning different data types is maybe just a programming error in this case. @typestable could warn me about that (already when calling in REPL).
- additional advantage: I could then test smaller units of my final program for type stability
This is basically what I expect. Note that in your example @typestable g(x::Vector{Any}) = x[1] should be perfectly fine - the concrete output type can always be inferred by the concrete input type. E.g., when calling
AOTcompile(g, (Vector{Int64},) ) #is fine, or
AOTcompile(g, (Vector{Float32},) ) #is also fine
AOTcompile(g, (Vector,) ) #not fine because the type is not concretized,
#this can always happen independently of the type stability