-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Unreachable Reached signal (4): Illegal instruction: 4 #35698
Comments
|
thank you @maleadt for trying it out I pushed now DataTypesBasic - there have been some local changes which are now upstream too. |
I successfully minimized the example, now it no longer includes any of my packages and is only about 10 lines long. :) Happy inspecting! Base.@kwdef struct UnreachableReached{T}
type::Type{T}
end
type1 = Tuple{Array{T1,1} where T1}
UnreachableReached{type1}(type = type1)
type2 = Tuple{Array{T2,1}} where T2
UnreachableReached{type2}(type = type2) again, you can actually reverse the order of The unreachable is reached for both Julia 1.4.1 and Julia 1.3.1 for me
Actually this also indicated a workaround - instead of using keyword arguments, you can use positional arguments and it will just work. |
Thanks for reducing, that's very helpful. Looks like another relative of #35130. |
Interestingly, normalization does work in this case: julia> UnreachableReached{type1}
UnreachableReached{Tuple{Array{T1,1} where T1}}
julia> UnreachableReached{type2}
UnreachableReached{Tuple{Array{T1,1} where T1}} From what it is not surprising that when changing the second constructor call to Base.@kwdef struct UnreachableReached{T}
type::Type{T}
end
type1 = Tuple{Array{T1,1} where T1}
type2 = Tuple{Array{T2,1}} where T2
UnreachableReached{type1}(type = type2) So let's look at julia> @code_typed UnreachableReached{type1}(type = type2)
CodeInfo(
1 ── %1 = Base.getfield(@_2, :type)::UnionAll
│ %2 = Base.sle_int(1, 1)::Bool
└─── goto #3 if not %2
2 ── %4 = Base.sle_int(1, 0)::Bool
└─── goto #4
3 ── nothing::Nothing
4 ┄─ %7 = φ (#2 => %4, #3 => false)::Bool
└─── goto #6 if not %7
5 ── invoke Base.getindex(()::Tuple, 1::Int64)::Union{}
└─── $(Expr(:unreachable))::Union{}
6 ┄─ goto #7
7 ── goto #8
8 ── goto #9
9 ── goto #10
10 ─ nothing::Nothing
│ invoke Main.:(var"#_#1")(%1::Type{T} where T, _3::Type{UnreachableReached{Tuple{Array{T1,1} where T1}}})::Union{}
└─── $(Expr(:unreachable))::Union{}
) => Union{} Hm, why does the julia> code_typed(var"#_#1", Tuple{Type{T} where T, Type{UnreachableReached{Tuple{Array{T1,1} where T1}}}})
1-element Array{Any,1}:
CodeInfo(
1 ─ %1 = invoke UnreachableReached{Tuple{Array{T1,1} where T1}}(_2::Type{T} where T)::UnreachableReached{Tuple{Array{T1,1} where T1}}
└── return %1
) => UnreachableReached{Tuple{Array{T1,1} where T1}} Um? |
Ah, I should have known better: The argument type is julia> code_typed(var"#_#1", Tuple{UnionAll, Type{UnreachableReached{Tuple{Array{T1,1} where T1}}}})
1-element Array{Any,1}:
CodeInfo(
1 ─ invoke UnreachableReached{Tuple{Array{T1,1} where T1}}(_2::Type{T} where T)::Union{}
└── $(Expr(:unreachable))::Union{}
) => Union{} From there: julia> code_typed(UnreachableReached{Tuple{Array{T1,1} where T1}}, Tuple{UnionAll})
1-element Array{Any,1}:
CodeInfo(
1 ─ %1 = Core.fieldtype(UnreachableReached{Tuple{Array{T1,1} where T1}}, 1)::Type{Type{Tuple{Array{T1,1} where T1}}}
│ Base.convert(%1, type)::Union{}
└── $(Expr(:unreachable))::Union{}
) => Union{} Aha, it's the foo() = convert(Type{Tuple{Array{T1,1} where T1}}, UnionAll[Tuple{Array{T2,1}} where T2][1])
foo() And we may note the following: julia> methods(convert, Tuple{Type{Type{Tuple{Array{T,1} where T}}}, UnionAll})
# 0 methods for generic function "convert":
julia> methods(convert, Tuple{Type{Type{Tuple{Array{T,1} where T}}}, Type{Tuple{Array{T2,1}} where T2}})
# 1 method for generic function "convert":
[1] convert(::Type{T}, x::T) where T in Base at essentials.jl:171
julia> Type{Tuple{Array{T2,1}} where T2} <: UnionAll
true So it boils down to this tircky type intersection problem: julia> typeintersect(Tuple{Type{T}, T} where T, Tuple{Type{Type{Tuple{Array{T,1} where T}}}, UnionAll})
Union{} Which shoud give |
Or a simplified version of the type intersection problem: julia> T = Type{Tuple{Array{T,1} where T}}
Type{Tuple{Array{T,1} where T}}
julia> typeintersect(T, UnionAll)
Union{}
julia> R = Type{Tuple{Array{T,1}} where T}
Type{Tuple{Array{T2,1}} where T2}
julia> R <: T && R <: UnionAll
true |
Just to say, this crash is (unsurprisingly) still present in Julia 1.5.2 and 1.6.0-DEV.1399. |
Still present on 1.9-dev. |
Dear Core Team,
I was motivated to raise a Bug report by the small discourse discussion about the same Unreachable Reached.
I can share reproducible piece of code, but please bear with me that it reproduces my current development setup and is not minified yet (I expect it to be quite hard to minify it actually). Still, at least you can trigger it now yourself:
The second
@traits
line will trigger the Unreachable Reached. You can also execute f2 before f1, and then, surprisingly, f1 will trigger the Unreachable Reached. This indicates that some state-keeping is not working correctly within Julia.Good thing is that this way one can actually inspect both macros using
macroexpand
.@traits
itself also has a state, however each function has its own state (at least this is the intention, I am not yet 100% sure that it currently is still the case, as this hit me in the middle of some refactoring). So my best guess is that it is some julia internal state-keeping.Here the unreachable reached error:
I hope this can already enable some others to help inspecting the issue further.
With best wishes
The text was updated successfully, but these errors were encountered: