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
…47910)

When merging `PartialStruct`, we are currently merging their fields a
bit aggressively (#44404) in order to accelerate (or rather, guarantee) 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 authored Dec 20, 2022
1 parent 9be3c85 commit e976206
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
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 reach 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
6 changes: 5 additions & 1 deletion base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,12 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty
tyi = ai
elseif is_lattice_equal(lattice, bi, ft)
tyi = bi
elseif (tyi′ = tmerge_field(lattice, ai, bi); tyi′ !== nothing)
# allow external lattice implementation to provide a custom field-merge strategy
tyi = tyi′
else
# Otherwise choose between using the fieldtype or some other simple merged type.
# Otherwise use the default aggressive field-merge implementation, and
# choose between using the fieldtype or some other simple merged type.
# The wrapper type never has restrictions on complexity,
# so try to use that to refine the estimated type too.
tni = _typename(widenconst(ai))
Expand Down

0 comments on commit e976206

Please sign in to comment.