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

fatal error in type inference (type bound) #43064

Closed
mcabbott opened this issue Nov 13, 2021 · 5 comments
Closed

fatal error in type inference (type bound) #43064

mcabbott opened this issue Nov 13, 2021 · 5 comments
Labels
bug Indicates an unexpected problem or unintended behavior types and dispatch Types, subtyping and method dispatch

Comments

@mcabbott
Copy link
Contributor

mcabbott commented Nov 13, 2021

I got the above error locally with #40996, which I have never seen before.

CI sees it too, here: https://build.julialang.org/#/builders/7/builds/5932/steps/5/logs/stdio (17f851b)

arrayops                           (5) |         failed at 2021-11-13T02:50:50.671
Error During Test at /buildworker/worker/tester_linuxaarch64/build/share/julia/test/arrayops.jl:1149
  Got exception outside of a @test
  fatal error in type inference (type bound)
  Stacktrace:
    [1] mapslices(f::Main.Test99Main_arrayops.var"#18#31", A::Matrix{Int64}; dims::Int64)
      @ Base ./abstractarray.jl:2803
    [2] macro expansion
      @ /buildworker/worker/tester_linuxaarch64/build/share/julia/test/arrayops.jl:1196 [inlined]
@vtjnash vtjnash added the types and dispatch Types, subtyping and method dispatch label Nov 13, 2021
Keno added a commit that referenced this issue Jan 25, 2022
When union splitting, we currently emit a fallback block that prints
`fatal error in type inference (type bound)`. This has always been an oddity,
because there are plenty of other places in the compiler that we
rely on the correctness of inference, but it has caught a number of
issues over the years and we do still have a few issues (e.g. #43064)
that show this error. Nevertheless, the occurrence of issues like
this has become less frequent, so it might be time to turn it off soon.
At the same time, we have downstream users of the compiler infrastructure
that get confused by having extra `throw` calls inserted into functions
that (post-#43852) were inferred as `:nothrow`.

Here we add an optimization param (defaulted to on) to determine whether
or not to insert the unionsplit fallback block. Because of the conservative
default, we can decide later what the correct default is (maybe turn it on
in `debug` mode?), while letting downstream consumers play with the setting
for now to see if any issues crop up.
Keno added a commit that referenced this issue Feb 8, 2022
When union splitting, we currently emit a fallback block that prints
`fatal error in type inference (type bound)`. This has always been an oddity,
because there are plenty of other places in the compiler that we
rely on the correctness of inference, but it has caught a number of
issues over the years and we do still have a few issues (e.g. #43064)
that show this error. Nevertheless, the occurrence of issues like
this has become less frequent, so it might be time to turn it off soon.
At the same time, we have downstream users of the compiler infrastructure
that get confused by having extra `throw` calls inserted into functions
that (post-#43852) were inferred as `:nothrow`.

Here we add an optimization param (defaulted to on) to determine whether
or not to insert the unionsplit fallback block. Because of the conservative
default, we can decide later what the correct default is (maybe turn it on
in `debug` mode?), while letting downstream consumers play with the setting
for now to see if any issues crop up.
Keno added a commit that referenced this issue Feb 9, 2022
When union splitting, we currently emit a fallback block that prints
`fatal error in type inference (type bound)`. This has always been an oddity,
because there are plenty of other places in the compiler that we
rely on the correctness of inference, but it has caught a number of
issues over the years and we do still have a few issues (e.g. #43064)
that show this error. Nevertheless, the occurrence of issues like
this has become less frequent, so it might be time to turn it off soon.
At the same time, we have downstream users of the compiler infrastructure
that get confused by having extra `throw` calls inserted into functions
that (post-#43852) were inferred as `:nothrow`.

Here we add an optimization param (defaulted to on) to determine whether
or not to insert the unionsplit fallback block. Because of the conservative
default, we can decide later what the correct default is (maybe turn it on
in `debug` mode?), while letting downstream consumers play with the setting
for now to see if any issues crop up.
antoine-levitt pushed a commit to antoine-levitt/julia that referenced this issue Feb 17, 2022
When union splitting, we currently emit a fallback block that prints
`fatal error in type inference (type bound)`. This has always been an oddity,
because there are plenty of other places in the compiler that we
rely on the correctness of inference, but it has caught a number of
issues over the years and we do still have a few issues (e.g. JuliaLang#43064)
that show this error. Nevertheless, the occurrence of issues like
this has become less frequent, so it might be time to turn it off soon.
At the same time, we have downstream users of the compiler infrastructure
that get confused by having extra `throw` calls inserted into functions
that (post-JuliaLang#43852) were inferred as `:nothrow`.

Here we add an optimization param (defaulted to on) to determine whether
or not to insert the unionsplit fallback block. Because of the conservative
default, we can decide later what the correct default is (maybe turn it on
in `debug` mode?), while letting downstream consumers play with the setting
for now to see if any issues crop up.
LilithHafner pushed a commit to LilithHafner/julia that referenced this issue Feb 22, 2022
When union splitting, we currently emit a fallback block that prints
`fatal error in type inference (type bound)`. This has always been an oddity,
because there are plenty of other places in the compiler that we
rely on the correctness of inference, but it has caught a number of
issues over the years and we do still have a few issues (e.g. JuliaLang#43064)
that show this error. Nevertheless, the occurrence of issues like
this has become less frequent, so it might be time to turn it off soon.
At the same time, we have downstream users of the compiler infrastructure
that get confused by having extra `throw` calls inserted into functions
that (post-JuliaLang#43852) were inferred as `:nothrow`.

Here we add an optimization param (defaulted to on) to determine whether
or not to insert the unionsplit fallback block. Because of the conservative
default, we can decide later what the correct default is (maybe turn it on
in `debug` mode?), while letting downstream consumers play with the setting
for now to see if any issues crop up.
LilithHafner pushed a commit to LilithHafner/julia that referenced this issue Mar 8, 2022
When union splitting, we currently emit a fallback block that prints
`fatal error in type inference (type bound)`. This has always been an oddity,
because there are plenty of other places in the compiler that we
rely on the correctness of inference, but it has caught a number of
issues over the years and we do still have a few issues (e.g. JuliaLang#43064)
that show this error. Nevertheless, the occurrence of issues like
this has become less frequent, so it might be time to turn it off soon.
At the same time, we have downstream users of the compiler infrastructure
that get confused by having extra `throw` calls inserted into functions
that (post-JuliaLang#43852) were inferred as `:nothrow`.

Here we add an optimization param (defaulted to on) to determine whether
or not to insert the unionsplit fallback block. Because of the conservative
default, we can decide later what the correct default is (maybe turn it on
in `debug` mode?), while letting downstream consumers play with the setting
for now to see if any issues crop up.
@LilithHafner LilithHafner added bug Indicates an unexpected problem or unintended behavior regression Regression in behavior compared to a previous version labels Jul 13, 2022
@LilithHafner
Copy link
Member

Reproducers (first two from @mcabbott):

julia> mapslices(tuple, [1 2; 3 4], dims=1)
1×2 Matrix{Tuple{Vector{Int64}}}:
 ([1, 3],)  ([2, 4],)

julia> mapslices(x -> tuple(x), [1 2; 3 4], dims=1)
ERROR: fatal error in type inference (type bound)
Stacktrace:
 [1] mapslices(f::var"#5#6", A::Matrix{Int64}; dims::Int64)
   @ Base ./abstractarray.jl:2896
 [2] top-level scope
   @ REPL[13]:1

julia> mapslices(argmax, rand(10,10); dims=2)
ERROR: fatal error in type inference (type bound)
Stacktrace:
 [1] mapslices(f::typeof(argmax), A::Matrix{Float64}; dims::Int64)
   @ Base ./abstractarray.jl:2896
 [2] top-level scope
   @ REPL[14]:1

@mcabbott
Copy link
Contributor Author

One more example, in which ndims seems to change the regime?

julia> mapslices(findmin, rand(3); dims=1)  # works in 1D, and infers
1-element Vector{Tuple{Float64, Int64}}:
 (0.10724568875730223, 3)

julia> @code_warntype mapslices(findmin, rand(3); dims=1)
...
Body::Vector{Tuple{Float64, Int64}}

julia> mapslices(findmin, rand(3,3); dims=1)  # errors in 2D
ERROR: fatal error in type inference (type bound)

julia> mapslices(findmin, rand(3,3,3); dims=1) |> summary  # works in 3D, but does not infer
"1×3×3 Array{Tuple{Float64, Int64}, 3}"

julia> @code_warntype mapslices(findmin, rand(3,3,3); dims=1)
...
Body::Any

@martinholters
Copy link
Member

Reduction based on the x -> tuple(x) above:

julia> function f(dims)
           idx1 = ntuple(d -> d in dims ? (:) : 1, 2)
           Aslice = [1 2; 3 4][idx1...]
           r1 = (x -> tuple(x))(Aslice)
           _res1 = similar(Aslice, typeof(r1), Base.reduced_indices(Aslice, 1:ndims(Aslice)))
           _res1[begin] = r1
       end
f (generic function with 1 method)

julia> f(1)
ERROR: fatal error in type inference (type bound)

With @code_warntype one finds that the call to similar is inferred as VecOrMat{Tuple{Int64}}, but the element type should actually be Tuple{Vector{Int64}}. (Or, from the imprecise inference of the argument, I think it should be inferred as Union{VecOrMat{Tuple{Int64}}, VecOrMat{Tuple{Vector{Int64}}}}.)

Indeed, I find the following:

julia> T1 = Type{Tuple{Int64}};

julia> T2 = Type{Tuple{Vector{Int64}}};

julia> only(code_typed(similar, (Vector{Int64}, T1, Tuple{Base.OneTo{Int64}})))[2] # ok
Vector{Tuple{Int64}} (alias for Array{Tuple{Int64}, 1})

julia> only(code_typed(similar, (Vector{Int64}, T2, Tuple{Base.OneTo{Int64}})))[2] # ok
Vector{Tuple{Vector{Int64}}} (alias for Array{Tuple{Array{Int64, 1}}, 1})

julia> only(code_typed(similar, (Vector{Int64}, Union{T1, T2}, Tuple{Base.OneTo{Int64}})))[2] # should be the union of the above?
Vector{Tuple{Int64}} (alias for Array{Tuple{Int64}, 1})

And:

julia> code_warntype(similar, (Vector{Int64}, Union{T1, T2}, Tuple{Base.OneTo{Int64}}))
MethodInstance for similar(::Vector{Int64}, ::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}, ::Tuple{Base.OneTo{Int64}})
  from similar(a::AbstractArray, ::Type{T}, dims::Tuple{Union{Integer, Base.OneTo}, Vararg{Union{Integer, Base.OneTo}}}) where T
     @ Base abstractarray.jl:815
Static Parameters
  T = Tuple{Int64}
Arguments
  #self#::Core.Const(similar)
  a::Vector{Int64}
  _::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}
  dims::Tuple{Base.OneTo{Int64}}
Body::Vector{Tuple{Int64}}
1%1 = $(Expr(:static_parameter, 1))::Core.Const(Tuple{Int64})
│   %2 = Base.to_shape(dims)::Tuple{Int64}%3 = Base.similar(a, %1, %2)::Vector{Tuple{Int64}}
└──      return %3

Note the discrepancy between T/$(Expr(:static_parameter, 1)) and the type of _. Interestingly, a rather similar-looking similar method works as desired:

julia> code_warntype(similar, (Vector{Int64}, Union{T1, T2}, Int64))
MethodInstance for similar(::Vector{Int64}, ::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}, ::Int64)
  from similar(a::AbstractArray, ::Type{T}, dims::Union{Integer, AbstractUnitRange}...) where T
     @ Base abstractarray.jl:809
Static Parameters
  T <: Any
Arguments
  #self#::Core.Const(similar)
  a::Vector{Int64}
  _::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}
  dims::Tuple{Int64}
Body::Union{Vector{Tuple{Vector{Int64}}}, Vector{Tuple{Int64}}}
1%1 = $(Expr(:static_parameter, 1))::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}
│   %2 = Base.to_shape(dims)::Tuple{Int64}%3 = Base.similar(a, %1, %2)::Union{Vector{Tuple{Vector{Int64}}}, Vector{Tuple{Int64}}}
└──      return %3

Here $(Expr(:static_parameter, 1)) is indeed the union of the possible types of _.

@N5N3
Copy link
Member

N5N3 commented Aug 4, 2022

Looks like a bug in jl_matching_methods

f(::Type{T}, ::Union{Nothing,Int,Missing}) where {T} = T
tt = Tuple{typeof(f),Union{Type{Int},Type{Float16}},Nothing}
match = Base._methods_by_ftype(tt, -1, typemax(UInt))[1]
match.sparams # svec(Int64) wrong

g(::Type{T}, ::Any) where {T} = T
tt = Tuple{typeof(g),Union{Type{Int},Type{Float16}},Nothing}
match = Base._methods_by_ftype(tt, -1, Base.get_world_counter())[1]
match.sparams #svec(T) # correct

@vtjnash vtjnash removed the regression Regression in behavior compared to a previous version label Aug 5, 2022
@vtjnash
Copy link
Member

vtjnash commented Aug 5, 2022

Duplicate of #41096 (comment)

@vtjnash vtjnash marked this as a duplicate of #41096 Aug 5, 2022
@vtjnash vtjnash closed this as completed Aug 5, 2022
N5N3 added a commit to N5N3/julia that referenced this issue Aug 10, 2022
This commit fixes examples reported in JuliaLang#43064.
We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
N5N3 added a commit to N5N3/julia that referenced this issue Aug 10, 2022
This commit fixes examples reported in JuliaLang#43064.
We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
N5N3 added a commit to N5N3/julia that referenced this issue Aug 10, 2022
This commit fixes examples reported in JuliaLang#43064.
We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
N5N3 added a commit to N5N3/julia that referenced this issue Aug 10, 2022
This commit fixes examples reported in JuliaLang#43064.
We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
N5N3 added a commit to N5N3/julia that referenced this issue Aug 10, 2022
This commit fixes examples reported in JuliaLang#43064.
We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

No branches or pull requests

5 participants