Skip to content

Commit

Permalink
allow external lattice to provide its own field-merge implementation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aviatesk committed Dec 16, 2022
1 parent b6f32bc commit 2c25fdd
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
17 changes: 17 additions & 0 deletions base/compiler/abstractlattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ remaining mostly associative and commutative.
"""
function tmerge end

"""
tmerge_field(𝕃::AbstractLattice, a, b) -> nothing or lattice element
Compute a lattice join of elements `a` and `b` over the lattice `𝕃`,
where `a` and `b` are fields of `PartialStruct` or `Const`.
This is an opt-in interface to allow external lattice implementation to provide its own
field-merge strategy. If it returns `nothing`, `tmerge(::PartialsLattice, ...)`
will use the default aggressive type merge implementation that does not use `tmerge`
recursively to accelerate convergence.
"""
function tmerge_field end

function tmerge_field(𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b))
return tmerge_field(widenlattice(𝕃), a, b)
end
tmerge_field(::JLTypeLattice, @nospecialize(a), @nospecialize(b)) = nothing

"""
βŠ‘(𝕃::AbstractLattice, a, b)
Expand Down
5 changes: 5 additions & 0 deletions base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,10 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty
for i = 1:type_nfields
ai = getfield_tfunc(lattice, typea, Const(i))
bi = getfield_tfunc(lattice, typeb, Const(i))
# allow external lattice implementation to provide a custom field-merge strategy
tyi = tmerge_field(lattice, ai, bi)
tyi !== nothing && @goto field_computed
# use the default aggressive field-merge implementation
ft = fieldtype(aty, i)
if is_lattice_equal(lattice, ai, bi) || is_lattice_equal(lattice, ai, ft)
# Since ai===bi, the given type has no restrictions on complexity.
Expand All @@ -531,6 +535,7 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty
tyi = ft
end
end
@label field_computed
fields[i] = tyi
if !anyrefine
anyrefine = has_nontrivial_extended_info(lattice, tyi) || # extended information
Expand Down

0 comments on commit 2c25fdd

Please sign in to comment.