Skip to content

Commit d89e619

Browse files
JeffBezansonKristofferC
authored andcommitted
fix part of #38936, getfield elim handling union of tuples (#39107)
This fixes the regression since 1.5 (cherry picked from commit c70a5bc)
1 parent d89cdec commit d89e619

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

base/compiler/ssair/passes.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,9 @@ function getfield_elim_pass!(ir::IRCode)
637637
isa(field, Union{Int, Symbol}) || continue
638638

639639
struct_typ = unwrap_unionall(widenconst(compact_exprtype(compact, stmt.args[2])))
640+
if isa(struct_typ, Union) && struct_typ <: Tuple
641+
struct_typ = unswitchtupleunion(struct_typ)
642+
end
640643
isa(struct_typ, DataType) || continue
641644

642645
def, typeconstraint = stmt.args[2], struct_typ

base/compiler/typeutils.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,21 @@ function improvable_via_constant_propagation(@nospecialize(t))
206206
end
207207
return false
208208
end
209+
210+
# convert a Union of Tuple types to a Tuple of Unions
211+
function unswitchtupleunion(u::Union)
212+
ts = uniontypes(u)
213+
n = -1
214+
for t in ts
215+
if t isa DataType && t.name === Tuple.name && !isvarargtype(t.parameters[end])
216+
if n == -1
217+
n = length(t.parameters)
218+
elseif n != length(t.parameters)
219+
return u
220+
end
221+
else
222+
return u
223+
end
224+
end
225+
Tuple{Any[ Union{Any[t.parameters[i] for t in ts]...} for i in 1:n ]...}
226+
end

test/compiler/irpasses.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,20 @@ let code = code_typed(pi_on_argument, Tuple{Any})[1].first.code,
342342
@test nisa == 1
343343
@test found_pi
344344
end
345+
346+
# issue #38936
347+
# check that getfield elim can handle unions of tuple types
348+
mutable struct S38936{T} content::T end
349+
struct PrintAll{T} <: Function
350+
parts::T
351+
end
352+
function (f::PrintAll)(io::IO)
353+
for x in f.parts
354+
print(io, x)
355+
end
356+
end
357+
let f = PrintAll((S38936("<span>"), "data", S38936("</span")))
358+
@test !any(code_typed(f, (IOBuffer,))[1][1].code) do stmt
359+
stmt isa Expr && stmt.head === :call && stmt.args[1] === GlobalRef(Core, :tuple)
360+
end
361+
end

0 commit comments

Comments
 (0)