You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am suprised by some poor inference which happens by introducing a new function layer. I think somehow this triggers a special recursive case which is poorly resolved.
I am the author of ExtensibleEffects.jl and am trying to track down performance problems. I have now been able to produce a minimal example (as minimal as I could get it so far), which at least is self-contained and does not need ExtensibleEffects.
Example
Here is the basics which we need to run the tests. It is a minimal implementation for Algebraic Effects.
struct NoEffect{T}
value::Tendstruct Eff{Effectful, Fs}
effectful::Effectful
funcs::FsendEff(effectful) =Eff(effectful, ())
# immediately run continuation if there is a continuation# and the wrapped value has no effectfunctionEff(effectful::E, funcs::Tuple{}) where E<:NoEffectEff{E, Tuple{}}(effectful, funcs)
endfunctionEff(effectful::NoEffect, funcs::Fs) where Fs
func = Base.first(funcs)
rest = Base.tail(funcs)
eff =func(effectful.value)
Eff(eff.effectful, (eff.funcs..., rest...))
endnoeffect(value) =Eff(NoEffect(value))
noeffect(eff::Eff) = eff
If you directly use the Eff constructor, everything works nicely
but if you wrap the typical Eff construction into its own separate function, the inference fails.
functionmyeff_flatmap(f_flatmap::F, e1_f::E) where {F, E}
Eff(e1_f.effectful, (e1_f.funcs..., f_flatmap))
endfunctioninference_fails(e1::E1, e2::E2) where {E1, E2}
e1_f =myeff_flatmap(v1 ->noeffect(curried_combine(v1)), e1)
f_flatmap(f) =myeff_flatmap(v2 ->noeffect(f(v2)), e2)
myeff_flatmap(f_flatmap, e1_f)
endinference_fails(e1, e2).effectful.value # 3@inferredinference_fails(e1, e2)
# ERROR: return type Eff{NoEffect{Int64}, Tuple{}} does not match inferred return type Eff
I was not able to find anything useful to fix this. I heard about a trick which(myeff_flatmap, Tuple{Any, Any}).recursion_relation = (@nospecialize(_...)) -> true, but I couldn't make it work, if it could work at all.
My best bet is that this has something to do with the point that myeff_flatmap is called recursively within the call.
Workaround
My current workaround is to write the function as a generated function instead, so that the code is inlined, which works as expected and does not require too much boilerplate.
Julia version
julia>versioninfo()
Julia Version 1.8.1
Commit afb6c60d69a (2022-09-0615:09 UTC)
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU:8×Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
WORD_SIZE:64
LIBM: libopenlibm
LLVM: libLLVM-13.0.1 (ORCJIT, icelake-client)
Threads:1 on 8 virtual cores
The text was updated successfully, but these errors were encountered:
I didn't test it locally. Looks like myeff_flatmap would cause call chain like Eff -> myeff_flatmap -> Eff -> myeff_flatmap -> ...
In this case, you have to loose the recursion check of Eff and myeff_flatmap at the same time to make sure the inference success.
You can use Cthulhu.jl to check if the inference is blocked in Eff. If so, then I think this is a duplicate of #45759. (As inference_works is a good example that the compiler would do eager inference on direct recursion. Eff -> Eff -> Eff -> ...)
Hi there,
I am suprised by some poor inference which happens by introducing a new function layer. I think somehow this triggers a special recursive case which is poorly resolved.
I am the author of ExtensibleEffects.jl and am trying to track down performance problems. I have now been able to produce a minimal example (as minimal as I could get it so far), which at least is self-contained and does not need ExtensibleEffects.
Example
Here is the basics which we need to run the tests. It is a minimal implementation for Algebraic Effects.
If you directly use the
Eff
constructor, everything works nicelybut if you wrap the typical Eff construction into its own separate function, the inference fails.
I was not able to find anything useful to fix this. I heard about a trick
which(myeff_flatmap, Tuple{Any, Any}).recursion_relation = (@nospecialize(_...)) -> true
, but I couldn't make it work, if it could work at all.My best bet is that this has something to do with the point that
myeff_flatmap
is called recursively within the call.Workaround
My current workaround is to write the function as a generated function instead, so that the code is inlined, which works as expected and does not require too much boilerplate.
Julia version
The text was updated successfully, but these errors were encountered: