# Promote constructor causing stack overflow

**URL:** <https://discourse.julialang.org/t/promote-constructor-causing-stack-overflow/32070>\
**Category:** General Usage\
**Created:** [December 9, 2019, 9:45pm UTC](https://discourse.julialang.org/t/promote-constructor-causing-stack-overflow/32070 "2019-12-09T21:45:35Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![doomphoenix-qxz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doomphoenix-qxz/32/7009_2.png) [@doomphoenix-qxz](https://discourse.julialang.org/u/doomphoenix-qxz)\
**Post date:** [December 9, 2019, 9:45pm UTC](https://discourse.julialang.org/t/promote-constructor-causing-stack-overflow/32070/1 "2019-12-09T21:45:35Z")

</div>

```julia
julia> struct parametrict{T}
              a::T
              b::T
              end

julia> parametrict(a::Real, b::Real) = parametrict(promote(a, b)...)
parametrict

julia> parametrict(0.5, 0.5)
ERROR: StackOverflowError:
Stacktrace:
 [1] parametrict(::Float64, ::Float64) at ./REPL[2]:1 (repeats 80000 times)

```

The Julia docs [seem to suggest doing exactly this](https://docs.julialang.org/en/v1/manual/constructors/#Parametric-Constructors-1), perhaps they should be updated? And what’s the recommended method for accomplishing this right now (i.e. making all sets of real input Just Work regardless of type)? I’m also using version 1.1.1 if that makes any difference.

---

<div class="post-metadata">

**Author:** ![findmyway](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/findmyway/32/4946_2.png) [@findmyway](https://discourse.julialang.org/u/findmyway)\
**Post date:** [December 10, 2019, 2:33am UTC](https://discourse.julialang.org/t/promote-constructor-causing-stack-overflow/32070/2 "2019-12-10T02:33:02Z")

</div>

Your definition of `parametric` is not the same with the one in the doc:

```julia
julia> struct Point{T<:Real}
           x::T
           y::T
           Point{T}(x,y) where {T<:Real} = new(x,y) # this is the main difference
       end

```

And another definition is missing

```julia
julia> Point(x::T, y::T) where {T<:Real} = Point{T}(x,y);

```

---

<div class="post-metadata">

**Author:** ![doomphoenix-qxz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doomphoenix-qxz/32/7009_2.png) [@doomphoenix-qxz](https://discourse.julialang.org/u/doomphoenix-qxz)\
**Post date:** [December 10, 2019, 4:01pm UTC](https://discourse.julialang.org/t/promote-constructor-causing-stack-overflow/32070/3 "2019-12-10T16:01:05Z")

</div>

> [@findmyway](#):
>
> And another definition is missing
> 
> ```julia
> julia> Point(x::T, y::T) where {T<:Real} = Point{T}(x,y);
> 
> ```

This was the key to fixing the problem, rather than the inner constructor. After playing with it a bit I realized that the `where {T<:Real}` is the key element; remove that and you get the stack overflow again. My guess is that the default constructor Julia supplies to such a type looks like this:

`Point(x::T, y::T) where {T} = Point{T}(x,y)`

and if you define the `promote` method on Reals with only this default constructor, the `promote` method always gets selected as the most specific method for `Real` input and continues to call itself, leading to the stack overflow.

EDIT: Upon reading the docs more closely, another valid solution is to just specify `struct Point{T<:Real}` instead of just plain `struct Point{T}` (or `struct parametrict{T}`). That annotation alone changes the default constructor to the form specified explicitly in your answer!
