Skip to content

Commit 9a6774c

Browse files
committed
Improve precision of tmeet for vararg PartialStruct
1 parent 5cd1e3e commit 9a6774c

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

base/compiler/typelimits.jl

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -559,17 +559,24 @@ function tmeet(@nospecialize(v), @nospecialize(t))
559559
return Bottom
560560
end
561561
@assert widev <: Tuple
562-
new_fields = Vector{Any}(undef, length(v.fields))
563-
for i = 1:length(new_fields)
564-
if isa(v.fields[i], Core.TypeofVararg)
565-
new_fields[i] = v.fields[i]
566-
else
567-
new_fields[i] = tmeet(v.fields[i], widenconst(getfield_tfunc(t, Const(i))))
568-
if new_fields[i] === Bottom
569-
return Bottom
570-
end
562+
if isa(ti, DataType) && ti.name === Tuple.name
563+
num_fields = length(ti.parameters)
564+
isva = isvatuple(ti)
565+
else
566+
nfields_ti = nfields_tfunc(ti)
567+
isva = !isa(nfields_ti, Const)
568+
num_fields = isva ? length(v.fields) : (nfields_ti::Const).val
569+
end
570+
new_fields = Vector{Any}(undef, num_fields)
571+
for i = 1:num_fields
572+
new_fields[i] = tmeet(getfield_tfunc(v, Const(i)), widenconst(getfield_tfunc(ti, Const(i))))
573+
if new_fields[i] === Bottom
574+
return Bottom
571575
end
572576
end
577+
if isva && isvarargtype(v.fields[end])
578+
new_fields[end] = Vararg{new_fields[end]}
579+
end
573580
return tuple_tfunc(new_fields)
574581
elseif isa(v, Conditional)
575582
if !(Bool <: t)

test/compiler/inference.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,3 +3021,15 @@ function splat_lotta_unions()
30213021
(a...,b...,c...)
30223022
end
30233023
@test Core.Compiler.return_type(splat_lotta_unions, Tuple{}) >: Tuple{Int,Int,Int}
3024+
3025+
# issue #38971 and related precision issues
3026+
f28971() = (1, [2,3]...)::Tuple{Int,Int,Int}
3027+
@test @inferred(f28971()) == (1, 2, 3)
3028+
g28971(::Type{T}) where {T} = (1, Number[2,3]...)::T
3029+
@test Base.return_types(g28971, Tuple{Type{Tuple{Vararg{Int}}}})[1] == Tuple{Int,Vararg{Int}}
3030+
@test Base.return_types(g28971, Tuple{Type{Tuple{Int,Vararg{Int}}}})[1] == Tuple{Int,Vararg{Int}}
3031+
@test Base.return_types(g28971, Tuple{Type{Tuple{Int,Int,Vararg{Int}}}})[1] == Tuple{Int,Int,Vararg{Int}}
3032+
@test Base.return_types(g28971, Tuple{Type{Union{Tuple{Int,Int,Int},Tuple{Vararg{Float64}}}}})[1] == Tuple{Int,Int,Int}
3033+
let T = Union{Tuple{Int,Int,Int},Tuple{Int,Vararg{Float64}}}
3034+
@test T <: Base.return_types(g28971, Tuple{Type{T}})[1] <: Tuple{Int,Vararg{Union{Int,Float64}}}
3035+
end

0 commit comments

Comments
 (0)