# Regression in v0.7 due to weird inference failure for function with Lisp-y recursion

**URL:** <https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342>\
**Category:** Internals & Design\
**Tags:** inference\
**Created:** [February 26, 2018, 3:18pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342 "2018-02-26T15:18:02Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 26, 2018, 3:18pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/1 "2018-02-26T15:18:02Z")

</div>

Consider this example, where `foo` works out a type given some inputs of other types:

```julia
mutable struct A{E, L}
end

mutable struct B{E, L}
end

mutable struct C{E, L}
end

foo(::Type{T}, t, ts...) where {T} = foo(foo(T, t), ts...)
foo(::Type{A{E, L}}, ::B{E2,L2}) where {E,E2,L,L2} = A{E2,L}
foo(::Type{A{E, L}}, ::C{E2,L2}) where {E,E2,L,L2} = A{E2,L2}

```

Let’s define some input objects of types `B` and `C`

```julia
b, c = B{Float64,2}(), C{Float64,2}()

```

Under current master the return type of the following call fails to be inferred and is very slow

```julia
julia> @btime foo(A{Float64,0}, $b, $c, $b, $b)
  258.510 ns (2 allocations: 32 bytes)
A{Float64,2}

```

However, a minuscule change to `foo` makes is completely inferrable

```julia
foo(::Type{A{E, L}}, ::C{E2,L2}) where {E,E2,L,L2} = A{E2,L}

```

which produces the following timings

```julia
julia> @btime foo(A{Float64,0}, $b, $c, $b, $b)
  0.023 ns (0 allocations: 0 bytes)
A{Float64,0}

```

I’ve been trying to figure out the reason all day today, and I cannot fathom the logic here. Something like this is killing the performance of my code. This problem arises in current master, but not in v0.6.1, where everything is nicely inferred and elided

```julia
julia> versioninfo()
Julia Version 0.7.0-DEV.4390
Commit 79c7bdd9ec (2018-02-26 07:59 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin17.4.0)
  CPU: Intel(R) Core(TM) i7-5775R CPU @ 3.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, broadwell)
Environment:

```

Is this known? Should I open an issue for this?  
[EDIT: corrected typos]

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [February 26, 2018, 3:29pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/2 "2018-02-26T15:29:26Z")

</div>

> [@pablosanjose](#):
>
> a minuscule change to foo makes is completely inferrable

I fail to see the difference between the two `foo` versions. Also you don’t define `a`.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 26, 2018, 3:32pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/3 "2018-02-26T15:32:20Z")

</div>

Oops, apologies @mauro3. Two typos corrected!

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 26, 2018, 3:57pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/4 "2018-02-26T15:57:42Z")

</div>

By the way, the `mutable` part is completely irrelevant. The regression also happens with immutable `struct`s.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [February 26, 2018, 4:18pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/5 "2018-02-26T16:18:50Z")

</div>

Interesting. I can reproduce.  
Also worth pointing out that just like changing `foo` to treat `B` and `C` the same causes type stability, replacing the `c` in the function call with `b` is also type stable with the original foo.

```julia
julia> @code_warntype foo(A{Float64,0}, b, c, b, b)
Variables:
  t<optimized out>
  ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}, 1)::C{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      Core.SSAValue(5) = (Core.getfield)(ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}, 3)::B{Float64,2}
      # meta: location REPL[4] foo 1
      Core.SSAValue(9) = $(Expr(:invoke, MethodInstance for foo(::Type{A{Float64,2}}, ::B{Float64,2}, ::B{Float64,2}, ::Vararg{B{Float64,2},N} where N), :(Main.foo), A{Float64,2}, Core.SSAValue(4), Core.SSAValue(5)))::Type{A{Float64,_1}} where _1
      # meta: pop location
      return Core.SSAValue(9)
  end::Type{A{Float64,_1}} where _1

julia> @code_warntype foo(A{Float64,0}, b, b, b, b)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}, 3)::B{Float64,2}
      return A{Float64,0}
  end::Type{A{Float64,0}}

```

Curiously, switching the position of c to anywhere but 2nd was type stable:

```julia
julia> @code_warntype foo(A{Float64,0}, c, b, b, b)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},B{Float64,2}}, 3)::B{Float64,2}
      return A{Float64,2}
  end::Type{A{Float64,2}}

julia> @code_warntype foo(A{Float64,0}, b, c, b, b)
Variables:
  t<optimized out>
  ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}, 1)::C{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      Core.SSAValue(5) = (Core.getfield)(ts::Tuple{C{Float64,2},B{Float64,2},B{Float64,2}}, 3)::B{Float64,2}
      # meta: location REPL[4] foo 1
      Core.SSAValue(9) = $(Expr(:invoke, MethodInstance for foo(::Type{A{Float64,2}}, ::B{Float64,2}, ::B{Float64,2}, ::Vararg{B{Float64,2},N} where N), :(Main.foo), A{Float64,2}, Core.SSAValue(4), Core.SSAValue(5)))::Type{A{Float64,_1}} where _1
      # meta: pop location
      return Core.SSAValue(9)
  end::Type{A{Float64,_1}} where _1

julia> @code_warntype foo(A{Float64,0}, b, b, c, b)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},C{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},C{Float64,2},B{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},C{Float64,2},B{Float64,2}}, 2)::C{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},C{Float64,2},B{Float64,2}}, 3)::B{Float64,2}
      return A{Float64,2}
  end::Type{A{Float64,2}}

julia> @code_warntype foo(A{Float64,0}, b, b, b, c)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2}}, 2)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2}}, 3)::C{Float64,2}
      return A{Float64,2}
  end::Type{A{Float64,2}}

```

I’ve encountered a problem before where incrementally calling parametric functions made them all type stable, but when jumping ahead they are not. However, I started over in a new session and called them in a different order, and that doesn’t seem to be going on here.  
I once again got that specifically the order `b, c, b, b` is not inferable, but `c` in the other three locations is.

Throwing extra `b`s on the end makes it switch back and fourth:

```julia
julia> @code_warntype foo(A{Float64,0}, b, b, b, c, b)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2}}, 3)::C{Float64,2}
      Core.SSAValue(6) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2}}, 4)::B{Float64,2}
      return A{Float64,2}
  end::Type{A{Float64,2}}

julia> @code_warntype foo(A{Float64,0}, b, b, b, c, b, b)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2}}, 3)::C{Float64,2}
      Core.SSAValue(6) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2}}, 4)::B{Float64,2}
      Core.SSAValue(7) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2}}, 5)::B{Float64,2}
      return A{Float64,2}
  end::Type{A{Float64,_1}} where _1

julia> @code_warntype foo(A{Float64,0}, b, b, b, c, b, b, b)
Variables:
  t<optimized out>
  ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}

Body:
  begin
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}, 1)::B{Float64,2}
      Core.SSAValue(4) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}, 2)::B{Float64,2}
      Core.SSAValue(5) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}, 3)::C{Float64,2}
      Core.SSAValue(6) = (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}, 4)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}, 5)::B{Float64,2}
      (Core.getfield)(ts::Tuple{B{Float64,2},B{Float64,2},C{Float64,2},B{Float64,2},B{Float64,2},B{Float64,2}}, 6)::B{Float64,2}
      return A{Float64,2}
  end::Type{A{Float64,2}}

```

I have no idea what is going on.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 26, 2018, 4:22pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/6 "2018-02-26T16:22:33Z")

</div>

Thanks @Elrod for reproducing. This matches my observations, inference goes a bit crazy here. I’ll wait for a bit and if nothing comes up I’ll open an issue.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 27, 2018, 10:43am UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/7 "2018-02-27T10:43:56Z")

</div>

[https://github.com/JuliaLang/julia/issues/26224](https://github.com/JuliaLang/julia/issues/26224)

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 27, 2018, 6:02pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/8 "2018-02-27T18:02:37Z")

</div>

Interesting! Jameson just commented on the Github issue above that this behaviour is by design. The compiler cannot demonstrate that the first recursive version of `foo` actually terminates and doesn’t enter into a recursion loop. Hence it bails out trying to infer its output type. If it didn’t do so we couldn’t have interprocedural constant propagation optimizations. Consequently, in v0.7+ one needs to be careful with this coding pattern of recursive methods. It is unfortunate, I find it rather elegant and powerful, and had gotten used to it from v0.6 and before. It does work very well if it is simple enough, for example

```julia
@inline tuplejoin(x) = x
@inline tuplejoin(x, y) = (x..., y...)
@inline tuplejoin(x, y, z...) = (x..., tuplejoin(y, z...)...)

```

but it becomes quickly unworkable as one makes it more complex. You have been warned! 😃

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [February 27, 2018, 10:03pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/9 "2018-02-27T22:03:22Z")

</div>

For completeness, I’ve been trying to find a tweak that makes the original recursive pattern workable. For some arcane reason, the following tweak, while still type-unstable and not-eliding, no longer allocates and recovers excellent performance

```julia
struct A{E, L}
end

struct B{E, L}
end

struct C{E, L}
end

foo(::Type{T}, t1, ts::Vararg{<:Any,N}) where {T, N} = foo(foo(T, t1), ts...)
foo(::Type{A{E, L}}, ::B{E2,L2}) where {E,E2,L,L2} = A{E2,L}
foo(::Type{A{E, L}}, ::C{E2,L2}) where {E,E2,L,L2} = A{E2,L2}

```

Note the `Vararg{<:Any, N}`. That’s the key for some reason. Now:

```julia
julia> b, c = B{Float64,2}(), C{Float64,2}()
(B{Float64,2}(), C{Float64,2}())

julia> @btime foo(A{Float64,0}, $b, $c, $b, $b)
  5.830 ns (0 allocations: 0 bytes)
A{Float64,2}

```

As you increase the number of `b` and `c` parameters, the execution time grows, but only mildly, in contrast to the original example which exploded. This is so whatever the input pattern, as far as I can tell. In other words, this version performs similarly to the `tuplejoin` example above, despite being type-unstable! It seems to be a good solution for even more complex recursions of this kind, also with more than three types `A`, `B`, `C` and pairwise rules.

Any light on why `ts::Vararg{<:Any,N}` is so different than `ts...` would be very welcome!

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [March 17, 2018, 11:37pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/10 "2018-03-17T23:37:39Z")

</div>

FWIW, you might “solve” these problems by putting `@generated` in front of `foo` (at least, that’s my go-to strategy on 0.6). This makes the compiler run the recursion at compilation-time.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [March 19, 2018, 11:11am UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/11 "2018-03-19T11:11:15Z")

</div>

Good one! Indeed, that works.

```julia
@generated foo(::Type{T}, t, ts...) where {T} = :(foo(foo(T, t), ts...))
@generated foo(::Type{A{E, L}}, ::B{E2,L2}) where {E,E2,L,L2} = :(A{E2,L})
@generated foo(::Type{A{E, L}}, ::C{E2,L2}) where {E,E2,L,L2} = :(A{E2,L2})

```

```julia
julia> @btime foo(A{Float64,0}, $b, $c, $b, $b)
  1.873 ns (0 allocations: 0 bytes)
A{Float64,2}

```

At some point in the past I loosely recall there was a recommendation to do things without generated functions if possible, but I don’t remember the reasons (compilation times, precompilation perhaps?). Do I remember correctly? If so, does the reason still apply in the new 1.0 world?

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [March 19, 2018, 11:16am UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/12 "2018-03-19T11:16:00Z")

</div>

By the way, interestingly, the `@code_native` output using your `@generated` approach and the `ts::Vararg{<:Any,N}` approach is _identical_, and looks very compact to my untrained eye

```julia
julia> @code_native foo(A{Float64,0}, b, c, b, b)
	.section	__TEXT,__ text,regular,pure_instructions
; Function foo {
; Location: REPL[4]:1
	subq	$40, %rsp
	movq	%rsi, 32(%rsp)
; Function @generated body; {
; Location: REPL[4]:1
; Function foo; {
; Location: REPL[4]:1
; Function @generated body; {
; Location: REPL[4]:1
	movabsq	$4546854976, %rax ## imm = 0x10F038040
	movq	%rax, (%rsp)
	movabsq	$4563281216, %rax ## imm = 0x10FFE2540
	movq	%rax, 8(%rsp)
	movabsq	$4546855192, %rax ## imm = 0x10F038118
	movq	%rax, 16(%rsp)
	movq	%rax, 24(%rsp)
	movabsq	$jl_invoke, %rax
	movabsq	$4558629776, %rdi ## imm = 0x10FB72B90
	leaq	(%rsp), %rsi
	movl	$4, %edx
	callq	*%rax
;}}
	addq	$40, %rsp
	retq
;}}

```

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [March 19, 2018, 11:56pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/13 "2018-03-19T23:56:08Z")

</div>

It’s interesting that it worked that way, but it’s not what I meant. I meant literally just putting `@generated`, without quoting the expression.

```julia
@generated foo(::Type{T}, t, ts...) where {T} = foo(foo(T, t), ts...)
...

```

Then the generated body of `foo` becomes a constant (i.e. the computed type).

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [March 20, 2018, 2:42pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/14 "2018-03-20T14:42:45Z")

</div>

Mmm, nope, that does not work for me. `foo(A{Float64,0}, b, c, b, b)` just hangs if I don’t quote the result (master and 0.6.2)… I thought generated functions where supposed to return a quoted expression, right?

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [March 23, 2018, 6:46pm UTC](https://discourse.julialang.org/t/regression-in-v0-7-due-to-weird-inference-failure-for-function-with-lisp-y-recursion/9342/15 "2018-03-23T18:46:21Z")

</div>

> [@pablosanjose](#):
>
> I thought generated functions where supposed to return a quoted expression, right?

Yes, but you can returned a quoted constant. Typically this just indicates you are doing something inappropriate for generated function usage (unsound). For similar reasons, it’s often a bad idea to have a generated function call itself (it’s bad enough that inference already might get run recursively inside it and think that it _might_ call itself, resulting in a StackOverflow and crash, but so far we’ve usually managed to avoid that).
