Skip to content

Commit 29b509d

Browse files
authored
inference: fix [modifyfield!|replacefield!]_tfuncs (#56310)
Currently the following code snippet results in an internal error: ```julia julia> func(x) = @atomic :monotonic x[].count += 1; julia> let;Base.Experimental.@force_compile x = Ref(nothing) func(x) end Internal error: during type inference of ... ``` This issue is caused by the incorrect use of `_fieldtype_tfunc(𝕃, o, f)` within `modifyfield!_tfunc`, specifically because `o` should be `widenconst`ed, but it isn’t. By using `_fieldtype_tfunc` correctly, we can avoid the error through error-catching in `abstract_modifyop!`. This commit also includes a similar fix for `replacefield!_tfunc` as well.
1 parent ac5bb66 commit 29b509d

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,13 +1347,15 @@ end
13471347
return getfield_tfunc(𝕃, o, f)
13481348
end
13491349
@nospecs function modifyfield!_tfunc(𝕃::AbstractLattice, o, f, op, v, order=Symbol)
1350-
T = _fieldtype_tfunc(𝕃, o, f, isconcretetype(o))
1350+
oβ€² = widenconst(o)
1351+
T = _fieldtype_tfunc(𝕃, oβ€², f, isconcretetype(oβ€²))
13511352
T === Bottom && return Bottom
13521353
PT = Const(Pair)
13531354
return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T, T), true)[1]
13541355
end
13551356
@nospecs function replacefield!_tfunc(𝕃::AbstractLattice, o, f, x, v, success_order=Symbol, failure_order=Symbol)
1356-
T = _fieldtype_tfunc(𝕃, o, f, isconcretetype(o))
1357+
oβ€² = widenconst(o)
1358+
T = _fieldtype_tfunc(𝕃, oβ€², f, isconcretetype(oβ€²))
13571359
T === Bottom && return Bottom
13581360
PT = Const(ccall(:jl_apply_cmpswap_type, Any, (Any,), T) where T)
13591361
return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T), true)[1]

β€Žtest/compiler/inference.jlβ€Ž

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6063,3 +6063,18 @@ end === Union{}
60636063
@test Base.infer_return_type() do
60646064
TypeVar(:Issue56248, Any, 1)
60656065
end === Union{}
6066+
6067+
@test Base.infer_return_type((Nothing,)) do x
6068+
@atomic x.count += 1
6069+
end == Union{}
6070+
@test Base.infer_return_type((Nothing,)) do x
6071+
@atomicreplace x.count 0 => 1
6072+
end == Union{}
6073+
mutable struct AtomicModifySafety
6074+
@atomic count::Int
6075+
end
6076+
let src = code_typed((Union{Nothing,AtomicModifySafety},)) do x
6077+
@atomic x.count += 1
6078+
end |> only |> first
6079+
@test any(@nospecialize(x)->Meta.isexpr(x, :invoke_modify), src.code)
6080+
end

0 commit comments

Comments
Β (0)