# Compile time: we can't find any impls for this multi dispatch fn?

**URL:** <https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736>\
**Category:** General Usage\
**Created:** [February 16, 2023, 7:22pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736 "2023-02-16T19:22:06Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 16, 2023, 7:22pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/1 "2023-02-16T19:22:06Z")

</div>

A bit of n00b question. Coming from a Scala / Rust background, I really really prefer compile time errors to runtime errors.

Right now, my biggest frustration with Julia is that issues of “we can’t find an impl for this multi dispatch fn” happen at runtime, not at compile time.

I am wondering, is there a way to detect these at compile time? This would significantly speed up my Julia coding cycle.

Thanks!

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 16, 2023, 7:25pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/2 "2023-02-16T19:25:24Z")

</div>

> [@zeroexcuses](#):
>
> I am wondering, is there a way to detect these at compile time? This would significantly speed up my Julia coding cycle.

there’s no compile time, or maybe another way to put it, you’re already hitting error at compile time 🙂

you want to use [GitHub - timholy/Revise.jl: Automatically update function definitions in a running Julia session](https://github.com/timholy/Revise.jl)

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 16, 2023, 7:36pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/3 "2023-02-16T19:36:19Z")

</div>

1. There is a compile time.
2. Errors are not thrown at that time, they’re thrown at runtime even when it’s statically known at compile time that they’ll throw.
3. Revise has nothing to do with any of this (though it’s a great tool for what it does do)

```julia
julia> function f()
           @noinline sleep(10)
           throw("Aw crap, I wasted a bunch of time.")
       end
f (generic function with 1 method)

julia> code_typed(f, ())
CodeInfo(
1 ─ invoke Main.sleep(10::Int64)::Nothing
│ Main.throw("Aw crap, I wasted a bunch of time.")::Union{}
└── unreachable
) => Union{}

julia> f() # 10 seconds later
ERROR: "Aw crap, I wasted a bunch of time."
Stacktrace:
 [1] f()
   @ Main ./REPL[14]:3
 [2] top-level scope
   @ REPL[15]:1

```

We can use JET.jl to address this:

```julia
julia> JET.report_call(f, ()) # No waiting 10 seconds
═════ 1 possible error found ═════
┌ @ REPL[14]:1 f()
│ may throw: throw("Aw crap, I wasted a bunch of time.")
└──────────────

```

@zeroexcuses Here’s an example of JET discovering a missing method error ahead of time:

```julia
julia> f(x) = g(x);

julia> g(::Int) = 1;

julia> JET.report_call(f, (Int,))
No errors detected

julia> JET.report_call(f, (Float64,)) 
═════ 1 possible error found ═════
┌ @ REPL[20]:1 g(x)
│ no matching method found `g(::Float64)`: g(x::Float64)
└──────────────

```

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 16, 2023, 8:50pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/4 "2023-02-16T20:50:57Z")

</div>

> [@jling](#):
>
> there’s no compile time,

1. Setup a HTTP handler.

2. Do something stupid in the HTTP handler with HTTP.setheader(…) involving multiple dispatch.

3. Notice: this error is not caught when we run `julia server.jl`, it happens only when we run `curl localhost:8080`

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 16, 2023, 8:54pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/5 "2023-02-16T20:54:11Z")

</div>

@Mason : Thank you for the suggestion of JET.jl .

I have a dumb question: if multiple dispatch is resolved at compile time (say when I run `julia server.jl`) for optimizations[1], it should be known then that “err, we don’t have an impl that matches this call”; and an error / warning could be thrown then.

Instead it waits until runtime. Mechanically, what is happening to cause this behaviour ?

[1] This is the justification many use for Julia’s (potential) slow startup, and the recommendations for Revise.jl and DaemonMode.jl

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 16, 2023, 9:06pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/6 "2023-02-16T21:06:20Z")

</div>

> [@zeroexcuses](#):
>
> I have a dumb question: if multiple dispatch is resolved at compile time (say when I run `julia server.jl`) for optimizations[1], it should be known then that “err, we don’t have an impl that matches this call”; and an error / warning could be thrown then.
> 
> Instead it waits until runtime. Mechanically, what is happening to cause this behaviour ?

As far as I understand, the reason is that **semantically** julia is supposed to behave as an interpreted language. Our type inference is only meant to be used as an optimization to speed up the execution of the language. Throwing known errors early at compile time could potentially break these semantics.

For instance, consider this code:

```julia
const store = []
function foo()
   push!(store, 1)
   throw("an error")
end

foo()

```

In an interpreted mode that doesn’t do any inference or optimizations, after running this code you’d get that `store == [1]`, but if you threw the error at the start of the function you’d get `store == []`.

Now, I suppose if the compiler knew that a function did not have side effects, it’d be semantically okay for us to hoist the error path to the start of the runtime, but either it was decided that was also a bad idea, or it may be nobody thought it was a good enough of an idea to put the work into implementing it.

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 16, 2023, 9:19pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/7 "2023-02-16T21:19:00Z")

</div>

I realize this is a bit untypical, but I’m running a webserver as follows:

```julia
sigint_handler() {
	kill $PID
	exit
}

trap sigint_handler SIGINT

while true; do
	sleep 0.1s
  clear
  echo "==============================="
	julia www/server.jl &
	PID=$!
	inotifywait -e close_write www/server.jl
	kill $PID
done

```

I’m wondering if there is a way to inject the JET.jl as a static check before the julia server.jl; so it starts the server if and only if JET.jl finds no obvious errors.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 16, 2023, 9:36pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/8 "2023-02-16T21:36:21Z")

</div>

I’d recommend instead that you do that loop in julia itself instead of constantly launching and closing julia every 0.1 seconds.

But to answer your question, yeah you could just right before the loop run a quick check with JET.jl, though JET is really best used as a development aid than a automatic checker.

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 16, 2023, 9:43pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/9 "2023-02-16T21:43:42Z")

</div>

> [@Mason](#):
>
> I’d recommend instead that you do that loop in julia itself instead of constantly launching and closing julia every 0.1 seconds.

This is not the behavior. The inotifywait causes it to only trigger when www/server.jl is modified. The 0.1 second is a safety in case the IDE does weird things to www/server.jl .

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 16, 2023, 9:45pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/10 "2023-02-16T21:45:37Z")

</div>

> [@Mason](#):
>
> I’d recommend instead that you do that loop in julia itself

Can you enlighten me on this? How would you do this in Julia? You would somehow need a way to kill the old HTTP.jl server and start a new one based on www/server.jl . It is not obvious to me how to do this besides calling out to shell commands.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 16, 2023, 11:27pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/11 "2023-02-16T23:27:20Z")

</div>

> [@Mason](#):
>
> Revise has nothing to do with any of this (though it’s a great tool for what it does do)

I’m mentioning Revise to answer “This would significantly speed up my Julia coding cycle.”

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 16, 2023, 11:30pm UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/12 "2023-02-16T23:30:11Z")

</div>

> [@zeroexcuses](#):
>
> Notice: this error is not caught when we run `julia server.jl`, it happens only when we run `curl localhost:8080`

yeah because that code is only compiled when you “run into” the piece of code that contains stupid code.

You can technically say every language has “compile time” because somewhere there’s time spent on translating human-readable code into assembly binary, but the point is in Julia you only compile “just ahead of time”, loosely you can even say “compile is just an optimization”

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 17, 2023, 12:10am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/13 "2023-02-17T00:10:21Z")

</div>

> [@jling](#):
>
> but the point is in Julia you only compile “just ahead of time”, loosely you can even say “compile is just an optimization”

I’m really confused now. This sounds alot like a JIT, but instead, it’s called “just AOT” ?

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 17, 2023, 12:49am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/14 "2023-02-17T00:49:20Z")

</div>

Nope, it’s called JIT. Julia is JIT compiled.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 17, 2023, 12:58am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/15 "2023-02-17T00:58:43Z")

</div>

if you understand JIT and knows it’s a JIT then you know what I mean by “no compile time” – because the compiler doesn’t see the function until you hit the function during runtime.

But one thing that’s different from other things people call “JIT” is that Julia always eagerly and very extensively compiles the code you are about to execute. (which is very different than, say, Java)

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 17, 2023, 1:08am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/16 "2023-02-17T01:08:11Z")

</div>

> [@jling](#):
>
> But one thing that’s different from other things people call “JIT” is that Julia always eagerly and very extensively compiles the code you are about to execute

I don’t understand this statement. Suppose we have:

```julia
f(x, y, z):
  a = f_a(x, y);
  b = f_b(a, x, y, z);
  c = f_c(a, b, x, y, z);
  return c

```

and now we have to compile function `f`. Does it then compile `f_a, f_b, f_c` (and what those functions depend on)?

If so, it seems like we’re going to compile the entire program at once, on the first execution of main().

If not, it is not clear what “aggressive optimizations” it can do.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 17, 2023, 2:09am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/17 "2023-02-17T02:09:06Z")

</div>

> [@zeroexcuses](#):
>
> on the first execution of main().

if recursively every function call can be inferred, yes, we can probe this behavior by using `@generated` so we know when the function is getting compiled:

```julia
julia> @generated function g(i)
           @show "compiling $i"
           return 1
       end

julia> function main()
           sleep(10)
           if 0.5 > rand()
               g(1)
           else
               g(1.0)
           end
       end

julia> main()
"compiling $(i)" = "compiling Int64" # instant
"compiling $(i)" = "compiling Float64" # instant
# 10 seconds wait here
1

# you need to re-start Julia here, or re-define g()
julia> function main2()
           sleep(10)
           a = rand((1, 1.0, "1", pi)) # this is unstable enough Julia won't try to union split
           g(a)
       end

julia> main2()
# 10 seconds wait here
"compiling $(i)" = "compiling Irrational{:π}" 
1

```

* * *

but usually it’s not the case, and some function calls are bound to be dynamic, thus you get to complain error not occurring earlier

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 17, 2023, 2:22am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/18 "2023-02-17T02:22:40Z")

</div>

> [@jling](#):
>
> but usually it’s not the case, and some function calls are bound to be dynamic, thus you get to complain error not occurring earlier

I can see how it looks like I’m complaining about a minor issue. I have a webserver currently written in OCaml. I’m considering rewriting it in Julia, as I now need it to serve tensor related requests.

During the rewrite process, I’m running into issues I’m surprised are not reported at compile time. I don’t have a mathematical proof of this, but I suspect ML code, wiritten in Julia style, tend to be statically type-infer-able? [Not 100% sure].

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 17, 2023, 2:35am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/19 "2023-02-17T02:35:58Z")

</div>

I don’t think that’s a safe assumption, compiler can easily give up inference for many reasons. I think your complain is perfectly reasonable, and I’m aware the powerfulness of OCaml (for example, it has typed function (in/out put) that Julia doesn’t have, so that’s simply a large chunk of information inaccessible to Julia compiler).

I suspect you should focus on making development workflow better by using Revise, instead of trying to force Julia to infer every “business” logic function at compile time (may not be possible)

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 17, 2023, 2:38am UTC](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/20 "2023-02-17T02:38:30Z")

</div>

> [@jling](#):
>
> I suspect you should focus on making development workflow better by using Revise, instead of trying to force Julia to infer every “business” logic function at compile time (may not be possible)

It does feel like I’m fighting an uphill battle. Do you have a recommendation of a Youtube video of someone showing off “idiomatic” Julia development workflow for non-numerical code ?

For numerical code, everything is a tensor, and there is not much to show off on the type side. I’m really interested in seeing what “idiomatic” Julia development for using types looks like.

[Next page](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736.md?page=2)
