Skip to content

Commit 2c25fdd

Browse files
committed
allow external lattice to provide its own field-merge implementation
When merging `PartialStruct`, we are currently merging their fields a bit aggressively (#47307) in order to accelerate convergence. However, when `PartialStruct` wraps external lattice elements, this can be too aggressive since it does not use `tmerge(𝕃, fields...)` recursively and thus the external lattice elements are not merged as expected. This commit adds an additional lattice hook, `tmerge_field`, inside `tmerge(::PartialsLattice)` so that external lattice implementation can provide its own field-merge strategies.
1 parent b6f32bc commit 2c25fdd

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

β€Žbase/compiler/abstractlattice.jlβ€Ž

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,23 @@ remaining mostly associative and commutative.
131131
"""
132132
function tmerge end
133133

134+
"""
135+
tmerge_field(𝕃::AbstractLattice, a, b) -> nothing or lattice element
136+
137+
Compute a lattice join of elements `a` and `b` over the lattice `𝕃`,
138+
where `a` and `b` are fields of `PartialStruct` or `Const`.
139+
This is an opt-in interface to allow external lattice implementation to provide its own
140+
field-merge strategy. If it returns `nothing`, `tmerge(::PartialsLattice, ...)`
141+
will use the default aggressive type merge implementation that does not use `tmerge`
142+
recursively to accelerate convergence.
143+
"""
144+
function tmerge_field end
145+
146+
function tmerge_field(𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b))
147+
return tmerge_field(widenlattice(𝕃), a, b)
148+
end
149+
tmerge_field(::JLTypeLattice, @nospecialize(a), @nospecialize(b)) = nothing
150+
134151
"""
135152
βŠ‘(𝕃::AbstractLattice, a, b)
136153

β€Žbase/compiler/typelimits.jlβ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,10 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty
508508
for i = 1:type_nfields
509509
ai = getfield_tfunc(lattice, typea, Const(i))
510510
bi = getfield_tfunc(lattice, typeb, Const(i))
511+
# allow external lattice implementation to provide a custom field-merge strategy
512+
tyi = tmerge_field(lattice, ai, bi)
513+
tyi !== nothing && @goto field_computed
514+
# use the default aggressive field-merge implementation
511515
ft = fieldtype(aty, i)
512516
if is_lattice_equal(lattice, ai, bi) || is_lattice_equal(lattice, ai, ft)
513517
# Since ai===bi, the given type has no restrictions on complexity.
@@ -531,6 +535,7 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty
531535
tyi = ft
532536
end
533537
end
538+
@label field_computed
534539
fields[i] = tyi
535540
if !anyrefine
536541
anyrefine = has_nontrivial_extended_info(lattice, tyi) || # extended information

0 commit comments

Comments
Β (0)