@@ -1837,6 +1837,14 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
1837
1837
end
1838
1838
rt = abstract_call_builtin (interp, f, arginfo, sv, max_methods)
1839
1839
effects = builtin_effects (typeinf_lattice (interp), f, argtypes[2 : end ], rt)
1840
+ if f === getfield && (fargs != = nothing && isexpr (fargs[end ], :boundscheck )) && ! is_nothrow (effects) && isa (sv, InferenceState)
1841
+ # As a special case, we delayed tainting `noinbounds` for getfield calls in case we can prove
1842
+ # in-boundedness indepedently. Here we need to put that back in other cases.
1843
+ # N.B.: This isn't about the effects of the call itself, but a delayed contribution of the :boundscheck
1844
+ # statement, so we need to merge this directly into sv, rather than modifying thte effects.
1845
+ merge_effects! (interp, sv, Effects (EFFECTS_TOTAL; noinbounds= false ,
1846
+ consistent = (get_curr_ssaflag (sv) & IR_FLAG_INBOUNDS) != 0 ? ALWAYS_FALSE : ALWAYS_TRUE))
1847
+ end
1840
1848
return CallMeta (rt, effects, NoCallInfo ())
1841
1849
elseif isa (f, Core. OpaqueClosure)
1842
1850
# calling an OpaqueClosure about which we have no information returns no information
@@ -2045,6 +2053,15 @@ function abstract_eval_value_expr(interp::AbstractInterpreter, e::Expr, vtypes::
2045
2053
end
2046
2054
elseif head === :boundscheck
2047
2055
if isa (sv, InferenceState)
2056
+ stmt = sv. src. code[sv. currpc]
2057
+ if isexpr (stmt, :call )
2058
+ f = abstract_eval_value (interp, stmt. args[1 ], vtypes, sv)
2059
+ if f isa Const && f. val === getfield
2060
+ # boundscheck of `getfield` call is analyzed by tfunc potentially without
2061
+ # tainting :inbounds or :consistent when it's known to be nothrow
2062
+ @goto delay_effects_analysis
2063
+ end
2064
+ end
2048
2065
# If there is no particular `@inbounds` for this function, then we only taint `:noinbounds`,
2049
2066
# which will subsequently taint `:consistent`-cy if this function is called from another
2050
2067
# function that uses `@inbounds`. However, if this `:boundscheck` is itself within an
@@ -2053,6 +2070,7 @@ function abstract_eval_value_expr(interp::AbstractInterpreter, e::Expr, vtypes::
2053
2070
merge_effects! (interp, sv, Effects (EFFECTS_TOTAL; noinbounds= false ,
2054
2071
consistent = (get_curr_ssaflag (sv) & IR_FLAG_INBOUNDS) != 0 ? ALWAYS_FALSE : ALWAYS_TRUE))
2055
2072
end
2073
+ @label delay_effects_analysis
2056
2074
rt = Bool
2057
2075
elseif head === :inbounds
2058
2076
@assert false && " Expected this to have been moved into flags"
0 commit comments