-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
option to avoid compiling a method that's known to throw for any input #3
Comments
An issue is that the functions |
For Julia in general, this should work: function known_not_to_return(f, arg_types)
if (
isdefined(Base, :infer_return_type) &&
applicable(Base.infer_return_type, arg_types)
)
Base.infer_return_type(f, arg_types) <: Union{} # not public, sadly
else
false
end
end
function known_not_to_throw(f, arg_types)
if (
isdefined(Base, :infer_exception_type) &&
applicable(Base.infer_exception_type, arg_types)
)
Base.infer_exception_type(f, arg_types) <: Union{} # not public, sadly
else
false
end
end
function known_to_throw_unless_it_runs_forever(f, arg_types)
may_throw = !known_not_to_throw(f, arg_types)
may_throw && known_not_to_return(f, arg_types)
end |
That's a really good idea! Here's a quick test. v0.1.1julia> speculate(all_modules; verbosity = review)
┌ Info: Generated `6358` methods from `26794` generic methods in `124.9810` seconds
│ Compiled `2622`
│ Skipped `3736`
└ Warned `0` Using
|
The
On its own,
The always throws case is the one we want to find to avoid compiling the method. The runs forever case is rare in practice, but when it happens it's probably desirable to compile (it could be the main loop of an application). The rationale behind using There's probably a different approach that would allow greater accuracy, but this is what I came up with. In particular, it might make sense to look into what JET is doing. |
Oh, I misunderstood the intent and didn't correctly implement the combined approach. Thank you for explaining it further. I'll write some tests and try it out soon :) |
Does this reflect your intent correctly? function count_specializations(f)
...
speculate(f; ...)
...
end
f() = error()
g() = while true end
function h()
while true
rand(Bool) && error()
end
end
@test 0 == count_specializations(f)
@test 1 == count_specializations(g)
@test 1 == count_specializations(h) |
NB: I'm sure it's possible to implement a more accurate predicate, that would return |
I think that checking |
It seems unrealistic that (m)any current codebase(s) exceeds runtime of |
Do you know an example where JET.jl is able to distinguish between always throw and may loop forever or throw? julia> @report_call f()
═════ 1 possible error found ═════
┌ f() @ Main ./REPL[28]:1
│┌ error() @ Base ./error.jl:42
││ may throw: Base.throw(Base.ErrorException((Base).string::typeof(string)(s::Tuple{}...)::String)::ErrorException)
│└────────────────────
julia> @report_call g()
No errors detected
julia> @report_call h()
═════ 1 possible error found ═════
┌ h() @ Main ./REPL[30]:3
│┌ error() @ Base ./error.jl:42
││ may throw: Base.throw(Base.ErrorException((Base).string::typeof(string)(s::Tuple{}...)::String)::ErrorException) |
Seems to be such an example: function f(in::IO, out::IO)
line = readline(in)
n = parse(Int, line)
show(out, n)
print(out, '\n')
end
function g(in::IO, out::IO)
while true
f(in, out)
end
end
function g()
g(stdin, stdout)
end julia> using JET
julia> @report_call g()
No errors detected |
If a method is known to throw for any input, I think it would be good to avoid compiling it by default, or at least provide such an option.
Here's code that approximates the desired predicate of "known to throw":
The text was updated successfully, but these errors were encountered: