Skip to content

Commit c70a5bc

Browse files
authored
fix part of #38936, getfield elim handling union of tuples (#39107)
This fixes the regression since 1.5
1 parent f5c8e67 commit c70a5bc

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
@@ -634,6 +634,9 @@ function getfield_elim_pass!(ir::IRCode)
634634
isa(field, Union{Int, Symbol}) || continue
635635

636636
struct_typ = unwrap_unionall(widenconst(compact_exprtype(compact, stmt.args[2])))
637+
if isa(struct_typ, Union) && struct_typ <: Tuple
638+
struct_typ = unswitchtupleunion(struct_typ)
639+
end
637640
isa(struct_typ, DataType) || continue
638641

639642
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
@@ -222,3 +222,21 @@ function improvable_via_constant_propagation(@nospecialize(t))
222222
end
223223
return false
224224
end
225+
226+
# convert a Union of Tuple types to a Tuple of Unions
227+
function unswitchtupleunion(u::Union)
228+
ts = uniontypes(u)
229+
n = -1
230+
for t in ts
231+
if t isa DataType && t.name === Tuple.name && !isvarargtype(t.parameters[end])
232+
if n == -1
233+
n = length(t.parameters)
234+
elseif n != length(t.parameters)
235+
return u
236+
end
237+
else
238+
return u
239+
end
240+
end
241+
Tuple{Any[ Union{Any[t.parameters[i] for t in ts]...} for i in 1:n ]...}
242+
end

test/compiler/irpasses.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,20 @@ let code = code_typed(pi_on_argument, Tuple{Any})[1].first.code,
352352
@test nisa == 1
353353
@test found_pi
354354
end
355+
356+
# issue #38936
357+
# check that getfield elim can handle unions of tuple types
358+
mutable struct S38936{T} content::T end
359+
struct PrintAll{T} <: Function
360+
parts::T
361+
end
362+
function (f::PrintAll)(io::IO)
363+
for x in f.parts
364+
print(io, x)
365+
end
366+
end
367+
let f = PrintAll((S38936("<span>"), "data", S38936("</span")))
368+
@test !any(code_typed(f, (IOBuffer,))[1][1].code) do stmt
369+
stmt isa Expr && stmt.head === :call && stmt.args[1] === GlobalRef(Core, :tuple)
370+
end
371+
end

0 commit comments

Comments
 (0)