Dear Julia type inference masters,

I am facing some inference/performance problems which look like they could be circumvented, but I don’t know enough about what is going on here.

```
struct ValType{T, V} end
ValTypeof(v::T) where T = ValType{T, v}
surprising_type_widening(i) = Tuple{Int, ValTypeof(i)}
@code_warntype surprising_type_widening(3)
```

outputs

```
MethodInstance for surprising_type_widening(::Int64)
from surprising_type_widening(i) in Main at REPL[6]:1
Arguments
#self#::Core.Const(surprising_type_widening)
i::Int64
Body::Type{<:Tuple{Int64, Any}}
1 ─ %1 = Main.ValTypeof(i)::Type{ValType{Int64, _A}} where _A
│ %2 = Core.apply_type(Main.Tuple, Main.Int, %1)::Type{<:Tuple{Int64, Any}}
└── return %2
```

where you can see that despite it could have inferred `Type{<:Tuple{Int64, ValType{Int64}}}`

, it widens to `Type{<:Tuple{Int64, Any}}`

any help about why this happens and how to circumvent it is highly appreciated
(tested on julia version 1.8.1 and nightly 1.10.0-DEV.350)

jling
January 12, 2023, 3:13am
3
I mean this is the classical type instability right? your output type depends on value of `v`

, not type of `v`

you can workaround this by using `Val()`

```
julia> ValTypeof(::Val{v}) where v = ValType{typeof(v), v}
ValTypeof (generic function with 2 methods)
julia> ValTypeof(Val(3))
ValType{Int64, 3}
julia> @code_warntype ValTypeof(Val(3))
MethodInstance for ValTypeof(::Val{3})
from ValTypeof(::Val{v}) where v @ Main REPL[15]:1
Static Parameters
v = 3
Arguments
#self#::Core.Const(ValTypeof)
_::Core.Const(Val{3}())
Body::Type{ValType{Int64, 3}}
1 ─ %1 = Main.ValType::Core.Const(ValType)
│ %2 = Main.typeof($(Expr(:static_parameter, 1)))::Core.Const(Int64)
│ %3 = Core.apply_type(%1, %2, $(Expr(:static_parameter, 1)))::Core.Const(ValType{Int64, 3})
└── return %3
```

1 Like

yes, I agree this is a type instability. Such instabilities occur in my code.

What I would like to improve is the widening strategy. Currently my instable ValTypes are widened to `Any`

, while I would like them to be widened to `ValType{Int}`

, which at least seems intuitively possible.