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

Unreachable reached at 0x7fb1e395276a, Illegal instruction #52168

Closed
nsajko opened this issue Nov 14, 2023 · 8 comments · Fixed by #52228
Closed

Unreachable reached at 0x7fb1e395276a, Illegal instruction #52168

nsajko opened this issue Nov 14, 2023 · 8 comments · Fixed by #52228
Labels
compiler:inference Type inference regression Regression in behavior compared to a previous version

Comments

@nsajko
Copy link
Contributor

nsajko commented Nov 14, 2023

Testing an in-development version of my package reproducibly reaches unreachable. RR trace obtained with julia --bug-report=rr: https://julialang-dumps.s3.amazonaws.com/reports/2023-11-14T18-13-29-nsajko.tar.zst

As far as I understand the source of my package isn't necessary given the RR trace? In any case, I think this is a type inference issue because the stack trace point to a line that includes a type assertion.

I'm not sure if the Rr trace contains the relevant info, considering that unreachable gets reached during testing. Inform me if another Rr trace is needed.

This is with nightly Julia:

julia> versioninfo()
Julia Version 1.11.0-DEV.894
Commit 9754dbbde5c (2023-11-13 18:40 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × AMD Ryzen 3 5300U with Radeon Graphics
  WORD_SIZE: 64
  LLVM: libLLVM-15.0.7 (ORCJIT, znver2)
  Threads: 1 on 8 virtual cores
Environment:
  JULIA_NUM_PRECOMPILE_TASKS = 3
  JULIA_PKG_PRECOMPILE_AUTO = 0

Stack trace:

Unreachable reached at 0x7fb1e395276a

[40752] signal 4 (2): Illegal instruction
in expression starting at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:60
merge_oblivious_sd at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Merging.jl:121
merge_oblivious_impl at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Merging.jl:124
merge_oblivious at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Merging.jl:140
merge at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Merging.jl:165
sorted_impl at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Sorting.jl:83
sorted_impl at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Sorting.jl:81
sorted at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/src/Sorting.jl:128
macro expansion at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:34 [inlined]
macro expansion at /cache/build/builder-amdci4-2/julialang/julia-master/usr/share/julia/stdlib/v1.11/Test/src/Test.jl:676 [inlined]
test_sorting_shared at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:34
test_sorting at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:38
unknown function (ip: 0x7fb1e3953901)
_jl_invoke at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:3092
test_sorting at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:57
unknown function (ip: 0x7fb1e3951fc5)
_jl_invoke at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:3092
macro expansion at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:66 [inlined]
macro expansion at /cache/build/builder-amdci4-2/julialang/julia-master/usr/share/julia/stdlib/v1.11/Test/src/Test.jl:1687 [inlined]
macro expansion at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:65 [inlined]
macro expansion at /cache/build/builder-amdci4-2/julialang/julia-master/usr/share/julia/stdlib/v1.11/Test/src/Test.jl:1598 [inlined]
top-level scope at /home/nsajko/src/gitlab.com/nsajko/TupleSorting/test/runtests.jl:61
jl_toplevel_eval_flex at /cache/build/builder-amdci4-2/julialang/julia-master/src/toplevel.c:932
jl_toplevel_eval_flex at /cache/build/builder-amdci4-2/julialang/julia-master/src/toplevel.c:884
ijl_toplevel_eval_in at /cache/build/builder-amdci4-2/julialang/julia-master/src/toplevel.c:992
eval at ./boot.jl:425 [inlined]
include_string at ./loading.jl:2133
_jl_invoke at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:3092
_include at ./loading.jl:2193
include at ./sysimg.jl:38
unknown function (ip: 0x7fb2086fa7c5)
_jl_invoke at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:3092
jl_apply at /cache/build/builder-amdci4-2/julialang/julia-master/src/julia.h:2130 [inlined]
do_call at /cache/build/builder-amdci4-2/julialang/julia-master/src/interpreter.c:126
eval_value at /cache/build/builder-amdci4-2/julialang/julia-master/src/interpreter.c:223
eval_stmt_value at /cache/build/builder-amdci4-2/julialang/julia-master/src/interpreter.c:174 [inlined]
eval_body at /cache/build/builder-amdci4-2/julialang/julia-master/src/interpreter.c:641
jl_interpret_toplevel_thunk at /cache/build/builder-amdci4-2/julialang/julia-master/src/interpreter.c:795
jl_toplevel_eval_flex at /cache/build/builder-amdci4-2/julialang/julia-master/src/toplevel.c:941
jl_toplevel_eval_flex at /cache/build/builder-amdci4-2/julialang/julia-master/src/toplevel.c:884
ijl_toplevel_eval_in at /cache/build/builder-amdci4-2/julialang/julia-master/src/toplevel.c:992
eval at ./boot.jl:425 [inlined]
exec_options at ./client.jl:291
_start at ./client.jl:525
jfptr__start_65686.1 at /home/nsajko/tmp/jl/jl/julia-9754dbbde5/lib/julia/sys.so (unknown line)
_jl_invoke at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci4-2/julialang/julia-master/src/gf.c:3092
jl_apply at /cache/build/builder-amdci4-2/julialang/julia-master/src/julia.h:2130 [inlined]
true_main at /cache/build/builder-amdci4-2/julialang/julia-master/src/jlapi.c:586
jl_repl_entrypoint at /cache/build/builder-amdci4-2/julialang/julia-master/src/jlapi.c:738
main at /cache/build/builder-amdci4-2/julialang/julia-master/cli/loader_exe.c:58
unknown function (ip: 0x7fb214e91ccf)
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
unknown function (ip: 0x4010b8)
Allocations: 231262030 (Pool: 231256281; Big: 5749); GC: 59
ERROR: Package TupleSorting errored during testing (received signal: 4)
@nsajko
Copy link
Contributor Author

nsajko commented Nov 14, 2023

Reproduced outside of testing, the trace should be much smaller:

https://julialang-dumps.s3.amazonaws.com/reports/2023-11-14T18-43-57-nsajko.tar.zst

@nsajko
Copy link
Contributor Author

nsajko commented Nov 14, 2023

Also reproduces on Julia v1.10.0-rc1, but not not v1.9.

@JeffBezanson JeffBezanson added the regression Regression in behavior compared to a previous version label Nov 15, 2023
@nsajko
Copy link
Contributor Author

nsajko commented Nov 16, 2023

No-dependency reproducer:

module Repro

module TupleUtils

const NT = NTuple{n,Any} where {n}
const OneAndUp = Tuple{Any,Vararg{Any,n}} where {n}
const TwoAndUp = Tuple{Any,Any,Vararg{Any,n}} where {n}

rt(::T) where {n, T<:NT{n}} = NTuple{n,eltype(T)}
rt(::L, ::R) where {m, n, L<:NT{m}, R<:NT{n}} = NTuple{m + n, Union{eltype(L), eltype(R)}}

function concat(l::L, r::R) where {m, n, L<:NT{m}, R<:NT{n}}
  f = let l = l, r = r
    (i::Int) -> (i  m) ? l[i] : r[i - m]
  end
  ntuple(f, Val(m + n))::rt(l, r)
end

function flatten(t::NTuple{n,NT{2}}) where {n}
  f = let t = t
    function(i::Int)
      j = i - firstindex(t)
      k = j >>> true
      l = j % Bool
      t[begin + k][begin + l]
    end
  end
  ntuple(f, Val(2*n))
end

function tuple_slice(
  t::OneAndUp{nm1}, ::Val{first}, ::Val{last},
) where {nm1, first, last}
  m = last - first + 1
  (m < 0) && error("expected nonnegative, got $m")
  let n = nm1 + 1
    (m  n) || error("expected ordered, got ($m, $n)")
  end
  f = let t = t
    (i::Int) -> t[first + i - 1]
  end
  ntuple(f, Val(m))
end

function interleave(l::L, r::R) where {m, L<:NT{m}, R<:NT{m}}
  f = let l = l, r = r
    function(i::Int)
      j = i - 1
      k = j >>> true
      iseven(j) ? l[begin + k] : r[begin + k]
    end
  end
  ntuple(f, Val(2*m))::rt(l, r)
end

function interleave_impl(l::L, r::R, ::Val{false}) where {m, n, L<:NT{m}, R<:NT{n}}
  (m  n) && error("internal error")
  x = lastindex(l) - (m - n)
  l_core = tuple_slice(l, Val(firstindex(l)), Val(x))::NT{n}
  l_rest = tuple_slice(l, Val(x + 1), Val(lastindex(l)))::NT{m - n}
  concat(interleave(l_core, r), l_rest)
end

function interleave_impl(l::L, r::R, ::Val{true}) where {m, n, L<:NT{m}, R<:NT{n}}
  (n  m) && error("internal error")
  x = lastindex(r) - (n - m)
  r_core = tuple_slice(r, Val(firstindex(r)), Val(x))::NT{m}
  r_rest = tuple_slice(r, Val(x + 1), Val(lastindex(r)))::NT{n - m}
  concat(interleave(l, r_core), r_rest)
end

interleave(l::L, r::R) where {m, n, L<:NT{m}, R<:NT{n}} = interleave_impl(l, r, Val(m < n))

function deinterleave_half(t::T) where {n, T<:OneAndUp{n}}
  m = n + 1
  t::NT{m}
  h = m >>> true
  g = m - h

  f = let t = t
    (i::Int) -> t[begin + 2*(i - 1)]
  end

  ntuple(f, Val(g))
end

deinterleave(          t::Tuple{T}) where {T} = (t, ())
deinterleave_backwards(t::Tuple{T}) where {T} = ((), t)

deinterleave(t::T) where {T<:TwoAndUp} = (
  deinterleave_half(t),
  deinterleave_half(tuple_slice(t, Val(2), Val(lastindex(t)))),
)

deinterleave_backwards(t::T, ::Val{false}) where {T<:TwoAndUp} = deinterleave(t)

deinterleave_backwards(t::T, ::Val{true}) where {T<:TwoAndUp} = (
  deinterleave_half(tuple_slice(t, Val(2), Val(lastindex(t)))),
  deinterleave_half(t),
)

deinterleave_backwards(t::T) where {T<:TwoAndUp} =
  deinterleave_backwards(t, Val(length(t) % Bool))

end

module Merging

import ..TupleUtils

const Ord = Base.Order

const NT           = TupleUtils.NT
const OneAndUp     = TupleUtils.OneAndUp
const tuple_slice  = TupleUtils.tuple_slice
const rt           = TupleUtils.rt
const deinterleave = TupleUtils.deinterleave
const   interleave = TupleUtils.interleave

function even_odd_clean(mm::Mm, t::NT{n}) where {Mm, n}
  iseven(n) || error("expected even, got $n")
  f = let mm = mm, t = t
    function(i::Int)
      j = i - firstindex(t)
      k = 2 * j
      mm(t[begin + k], t[begin + k + 1])
    end
  end
  TupleUtils.flatten(ntuple(f, Val(n >>> true)))::rt(t)
end

function even_odd_clean_abs(
  mm::Mm, t::NT{n}, ::First, ::Last,
) where {Mm, n, first, last, First<:Val{first}, Last<:Val{last}}
  s = tuple_slice(t, First(), Last())
  f = let x = even_odd_clean(mm, s), t = t
    i -> (first  i  last) ? x[i - first + 1] : t[i]
  end
  ntuple(f, Val(n))::rt(t)
end

function even_odd_clean_rel(mm::Mm, t::NT{n}, ::Val{f}, ::Val{b}) where {Mm, n, f, b}
  k = Val(firstindex(t) + f)
  l = Val( lastindex(t) - b)
  even_odd_clean_abs(mm, t, k, l)::rt(t)
end

merge_oblivious_sd(::Tuple{}, ::Tuple{}, ::Any) = ()
merge_oblivious_sd(::Tuple{}, t::OneAndUp, ::Any) = t
merge_oblivious_sd(t::OneAndUp, ::Tuple{}, ::Any) = t

merge_oblivious_sd(l::Tuple{L}, r::Tuple{R}, mm::Mm) where {L, R, Mm} =
  mm(only(l), only(r))::rt(l, r)

comparator_count_check(::V, ::V) where {V<:Val} = nothing

comparator_count_check(::Val{e}, ::Val{g}) where {e, g} =
  error("wrong comparator count, expected $e, got $g")

conditionally_split_single_from_end(::Val{false}, x::T) where {T<:Tuple} = (x, ())
conditionally_split_single_from_end(::Val{true},  x::T) where {T<:OneAndUp} =
  (tuple_slice(x, Val(firstindex(x)), Val(lastindex(x) - 1)), (last(x),))

function merge_oblivious_sd(
  l::L, r::R, mm::Mm,
) where {m, n, L<:OneAndUp{m}, R<:OneAndUp{n}, Mm}
  (s, t) = TupleUtils.deinterleave_backwards(l)
  (u, v) = deinterleave(r)
  x = merge_oblivious_sd(s, u, mm)
  y = merge_oblivious_sd(t, v, mm)
  total = 2 + m + n
  (start, fin) = map(iseven, (m + 1, n + 1))
  cld = n -> n - (n >>> true)
  let exp = cld(m + 1) + cld(n + 1) - 1, got = (total - (start + fin)) >>> true
    comparator_count_check(Val(exp), Val(got))
  end
  T = rt(l, r)
  (y1, y2) = conditionally_split_single_from_end(Val(fin), y)
  i = interleave(x, y1)
  res = even_odd_clean_rel(mm, i, Val(start), Val(0))
  ret = TupleUtils.concat(res, y2)
  ret::T
end

end

repro(l, r) = Merging.merge_oblivious_sd(l, r, minmax)

end

l = (1,2,3,4,missing)
r = (1,2,3,4,5)
Repro.repro(l, r)

Calling it:

julia> versioninfo()
Julia Version 1.11.0-DEV.918
Commit 2fb06a7c25f (2023-11-16 07:19 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × AMD Ryzen 3 5300U with Radeon Graphics
  WORD_SIZE: 64
  LLVM: libLLVM-15.0.7 (ORCJIT, znver2)
  Threads: 1 on 8 virtual cores
Environment:
  JULIA_NUM_PRECOMPILE_TASKS = 3
  JULIA_PKG_PRECOMPILE_AUTO = 0

julia> include("/home/nsajko/julia_issue_52168/julia_issue_52168.jl")
Unreachable reached at 0x7f4f42d0cae6

[75173] signal 4 (2): Illegal instruction
in expression starting at /home/nsajko/julia_issue_52168/julia_issue_52168.jl:193
merge_oblivious_sd at /home/nsajko/julia_issue_52168/julia_issue_52168.jl:181
repro at /home/nsajko/julia_issue_52168/julia_issue_52168.jl:187
unknown function (ip: 0x7f4f42d0cb79)
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
jl_apply at /cache/build/builder-amdci5-1/julialang/julia-master/src/julia.h:2130 [inlined]
do_call at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:126
eval_value at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:223
eval_stmt_value at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:174 [inlined]
eval_body at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:641
jl_interpret_toplevel_thunk at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:795
jl_toplevel_eval_flex at /cache/build/builder-amdci5-1/julialang/julia-master/src/toplevel.c:941
jl_toplevel_eval_flex at /cache/build/builder-amdci5-1/julialang/julia-master/src/toplevel.c:884
ijl_toplevel_eval_in at /cache/build/builder-amdci5-1/julialang/julia-master/src/toplevel.c:992
eval at ./boot.jl:425 [inlined]
include_string at ./loading.jl:2133
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
_include at ./loading.jl:2193
include at ./sysimg.jl:38
unknown function (ip: 0x7f4f42d0ba55)
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
jl_apply at /cache/build/builder-amdci5-1/julialang/julia-master/src/julia.h:2130 [inlined]
do_call at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:126
eval_value at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:223
eval_stmt_value at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:174 [inlined]
eval_body at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:641
jl_interpret_toplevel_thunk at /cache/build/builder-amdci5-1/julialang/julia-master/src/interpreter.c:795
jl_toplevel_eval_flex at /cache/build/builder-amdci5-1/julialang/julia-master/src/toplevel.c:941
jl_toplevel_eval_flex at /cache/build/builder-amdci5-1/julialang/julia-master/src/toplevel.c:884
ijl_toplevel_eval_in at /cache/build/builder-amdci5-1/julialang/julia-master/src/toplevel.c:992
eval at ./boot.jl:425 [inlined]
eval_user_input at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/share/julia/stdlib/v1.11/REPL/src/REPL.jl:167
repl_backend_loop at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/share/julia/stdlib/v1.11/REPL/src/REPL.jl:263
#start_repl_backend#48 at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/share/julia/stdlib/v1.11/REPL/src/REPL.jl:248
start_repl_backend at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/share/julia/stdlib/v1.11/REPL/src/REPL.jl:245
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
#run_repl#61 at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/share/julia/stdlib/v1.11/REPL/src/REPL.jl:404
run_repl at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/share/julia/stdlib/v1.11/REPL/src/REPL.jl:390
jfptr_run_repl_12730 at /home/nsajko/.julia/compiled/v1.11/REPL/u0gqU_YU6QH.so (unknown line)
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
#1078 at ./client.jl:440
jfptr_YY.1078_17045 at /home/nsajko/.julia/compiled/v1.11/REPL/u0gqU_YU6QH.so (unknown line)
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
jl_apply at /cache/build/builder-amdci5-1/julialang/julia-master/src/julia.h:2130 [inlined]
jl_f__call_latest at /cache/build/builder-amdci5-1/julialang/julia-master/src/builtins.c:868
#invokelatest#2 at ./essentials.jl:928 [inlined]
invokelatest at ./essentials.jl:925 [inlined]
run_main_repl at ./client.jl:424
repl_main at ./client.jl:561 [inlined]
_start at ./client.jl:535
jfptr__start_65700.1 at /home/nsajko/tmp/jl/jl/julia-2fb06a7c25/lib/julia/sys.so (unknown line)
_jl_invoke at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:2910 [inlined]
ijl_apply_generic at /cache/build/builder-amdci5-1/julialang/julia-master/src/gf.c:3092
jl_apply at /cache/build/builder-amdci5-1/julialang/julia-master/src/julia.h:2130 [inlined]
true_main at /cache/build/builder-amdci5-1/julialang/julia-master/src/jlapi.c:586
jl_repl_entrypoint at /cache/build/builder-amdci5-1/julialang/julia-master/src/jlapi.c:738
main at /cache/build/builder-amdci5-1/julialang/julia-master/cli/loader_exe.c:58
unknown function (ip: 0x7f4f49671ccf)
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
unknown function (ip: 0x4010b8)
Allocations: 2039268 (Pool: 2039171; Big: 97); GC: 3
Illegal instruction (core dumped)

@N5N3
Copy link
Member

N5N3 commented Nov 16, 2023

MWE

julia> f(x, t::Type) = x::NTuple{2, Base.inferencebarrier(t)::Type}
f (generic function with 1 method)

julia> f((1, 2.), Any)

Unreachable reached at 000001f3c3460974

@N5N3 N5N3 added the compiler:inference Type inference label Nov 16, 2023
@gbaraldi
Copy link
Member

gbaraldi commented Nov 16, 2023

This function asserts a Union{} return that doesn't seem to trigger an exception

julia> @code_typed f((1,2.),Any)
CodeInfo(
1%1 = Base.compilerbarrier(:type, t)::Any
│        Core.typeassert(%1, Main.Type)::Type%3 = π (%1, Type)
│   %4 = Core.apply_type(Main.NTuple, 2, %3)::Type{Tuple{T, T}} where T
│        Core.typeassert(x, %4)::Union{}
│        π (x, Union{})
└──      unreachable
) => Union{}

This then gets compiled to just a trap/unreachable.

@vtjnash
Copy link
Member

vtjnash commented Nov 16, 2023

The mistake here is that apply_type_tfunc assumes that apply_type preserves subtyping relationships. That assumption is false. As seen here, NTuple{2, Any} is not a subtype of NTuple, but is well-formed.

@N5N3
Copy link
Member

N5N3 commented Nov 16, 2023

But the result of apply_type_tfunc seems acceptable?

julia> NTuple{2,Any} isa Type{Tuple{T, T}} where T
true

Edit: in fact we can reproduce this on 1.9 with

julia> f(x, @nospecialize t::Type{Tuple{T,T}} where {T}) = Core.typeassert(x, t)
f (generic function with 1 method)

julia> f((1, 1.), NTuple{2,Any})

Unreachable reached at 000001f34e590e38

@vtjnash
Copy link
Member

vtjnash commented Nov 16, 2023

That is fair. It looks like this is a peculiar corner case of when the diagonal rule doesn't apply because the where bounds are moved outside of Type:

julia> Type{Tuple{Any,Any}} <: Type{Tuple{T, T}} where T
true

julia> Type{Tuple{Any,Any}} <: Type{Tuple{T, T} where T<:S} where S
false

However the implementation of typeassert_tfunc tries to simply move the where bounds:

julia> Core.Compiler.instanceof_tfunc(Type{Tuple{T, T}} where T)[1]
Tuple{T, T} where T

We have a variety of similar issues, such as: #24582 and #27031 (and included there is a link to a possible "diagonalize_unionall" helper function that might help solve that conundrum vtjnash@fa2f102#diff-18f6a8f71bb7339fa2e860328beeaaffaa7675ef7125dd5f6005dc65f91b5b3eR386)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:inference Type inference regression Regression in behavior compared to a previous version
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants