Skip to content
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

Type inference failing for nested reduction #46557

Closed
simsurace opened this issue Aug 30, 2022 · 7 comments · Fixed by #50696
Closed

Type inference failing for nested reduction #46557

simsurace opened this issue Aug 30, 2022 · 7 comments · Fixed by #50696

Comments

@simsurace
Copy link
Contributor

The following nested reduction does not infer, even after #45789:

using Test

struct FunctionSum{Tf}
    functions::Tf
end

(F::FunctionSum)(x) = sum(f -> f(x), F.functions)

F = FunctionSum((x -> sqrt(x), FunctionSum((x -> x^2, x -> x^3))))
@inferred F(1.) # ERROR
@Keno
Copy link
Member

Keno commented Aug 30, 2022

This trips the recursion heuristic, because it can't prove that the FunctionSum -> sum -> FunctionSum -> sum method loop terminates. We could perhaps see if we can tweak the heuristics to notice that the tparam is shrinking, but it's a tricky bit of the code.

@N5N3
Copy link
Member

N5N3 commented Aug 31, 2022

#45789 only works for reduction on nested Iterator, not nested reduction.
As @Keno pointed out, your code will triger indirect recursion anyway, so our compiler would give up inference even the type is shrinking.(see #45759)
As a temporary workaround, you can try to avoid constructing nested FunctionSum or flatten the nested FunctionSum before you call sum (like ComposedFunction on master).

@jakobnissen
Copy link
Contributor

Probably a duplicate of #40084. I was bitten by this with the following example. Even more mysterious, the inference works if I define the same function twice...

julia> using Test

julia> f(x) = sum(x) do v
           sum(length, v)
       end;

julia> @inferred f([[[1]]])
ERROR: return type Int64 does not match inferred return type Any
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] top-level scope
   @ REPL[3]:1

julia> f(x) = sum(x) do v
           sum(length, v)
       end;

julia> @inferred f([[[1]]])
1

@simsurace
Copy link
Contributor Author

Great example! The phenomenon about it being inferred after a second definition has happened to me as well, it is really weird. E.g. I redefined a function in a package that was type-unstable in the unit tests, but then was type stable after being overwritten with the same source code.

@schlichtanders
Copy link

I run into similar issues. Redefining the same helps.

In a sense this looks promising, as the compiler had all information already on the first run, but somehow needed to runs to actually get it.

@oscardssmith
Copy link
Member

I just ran into a similar example:

julia> f(u) = [u[] for _ in 1:2]
f (generic function with 1 method)

julia> @inferred f(Float64)
ERROR: return type Vector{Vector{Float64}} does not match inferred return type Vector

@vtjnash
Copy link
Sponsor Member

vtjnash commented Dec 9, 2022

Don't think that has anything to do with this issue, since there is no nested inference there (only a closure capture of a Type)

vtjnash added a commit that referenced this issue Jul 27, 2023
vtjnash added a commit that referenced this issue Aug 10, 2023
vtjnash added a commit that referenced this issue Aug 14, 2023
Fix #45759
Fix #46557
Fix #31485

Depends on #50694 due to a failing broadcast test without it (related to
#50695)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants