Inference: propagate struct initialization info on `setfield!` (#57222)
When a variable has a field set with `setfield!(var, field, value)`,
inference now assumes that this specific field is defined and may for
example constant-propagate `isdefined(var, field)` as `true`.
`PartialStruct`, the lattice element used to encode this information,
still has a few limitations in terms of what it may represent (it cannot
represent mutable structs with non-contiguously defined fields yet),
further work on extending it would increase the impact of this change.
Consider the following function:
```julia
julia> function f()
a = A(1)
setfield!(a, :y, 2)
invokelatest(identity, a)
isdefined(a, :y) && return 1.0
a
end
f (generic function with 1 method)
```
Here is before on `master`:
```julia
julia> @code_typed f()
CodeInfo(
1 ─ %1 = %new(Main.A, 1)::A
│ builtin Main.setfield!(%1, :y, 2)::Int64
│ dynamic builtin (Core._call_latest)(identity, %1)::Any
│ %4 = builtin Main.isdefined(%1, :y)::Bool
└── goto #3 if not %4
2 ─ return 1.0
3 ─ return %1
) => Union{Float64, A}
```
And after this PR:
```julia
julia> @code_typed f()
CodeInfo(
1 ─ %1 = %new(Main.A, 1)::A
│ builtin Main.setfield!(%1, :y, 2)::Int64
│ dynamic builtin (Core._call_latest)(identity, %1)::Any
└── return 1.0
) => Float64
```
---------
Co-authored-by: Cédric Belmant <cedric.belmant@juliahub.com>