effects: improve `:consistent`-cy analysis on `getfield` (#46199)
This commit improves the accuracy of the `:consistent`-cy effect analysis
by handling `getfield` accessing local mutable objects.
The existing analysis taints `:consistent`-cy upon any `getfield` call
accessing mutable object because we really don't have a knowledge about
the object lifetime and so we need to conservatively take into account a
possibility of the mutable object being a global variable.
However we can "recover" `:consistent`-cy tainted by `getfield` on mutable
object when the newly added `:noglobal` helper effect has been proven
because in that case we can conclude that all mutable objects accessed
within the method are purely local and thus `:consistent` (more
precisely we also need to confirm that all the call arguments are known
not to be mutable global objects to derive this conclusion).
For example now we can prove `:consistent`-cy of the function below and
it will be concrete-evaluated:
```julia
julia> @noinline function mutable_consistent(s)
broadcast(identity, Ref(s))
end
mutable_consistent (generic function with 1 method)
julia> Base.infer_effects(mutable_consistent, (String,))
(+c,+e,!n,+t,+s,+g)
julia> code_typed() do
mutable_consistent(:foo)
end
1-element Vector{Any}:
CodeInfo(
1 ─ return :foo
) => Symbol
```