@@ -749,6 +749,7 @@ function getfield_boundscheck(argtypes::Vector{Any}) # ::Union{Bool, Nothing, Ty
749
749
else
750
750
return nothing
751
751
end
752
+ isvarargtype (boundscheck) && return nothing
752
753
widenconst (boundscheck) != = Bool && return nothing
753
754
boundscheck = widenconditional (boundscheck)
754
755
if isa (boundscheck, Const)
@@ -1850,67 +1851,82 @@ const _SPECIAL_BUILTINS = Any[
1850
1851
Core. _apply_iterate
1851
1852
]
1852
1853
1854
+ function isdefined_effects (argtypes:: Vector{Any} )
1855
+ # consistent if the first arg is immutable
1856
+ isempty (argtypes) && return EFFECTS_THROWS
1857
+ obj = argtypes[1 ]
1858
+ isvarargtype (obj) && return Effects (EFFECTS_THROWS; consistent= ALWAYS_FALSE)
1859
+ consistent = is_immutable_argtype (obj) ? ALWAYS_TRUE : ALWAYS_FALSE
1860
+ nothrow = isdefined_nothrow (argtypes) ? ALWAYS_TRUE : ALWAYS_FALSE
1861
+ return Effects (EFFECTS_TOTAL; consistent, nothrow)
1862
+ end
1863
+
1864
+ function getfield_effects (argtypes:: Vector{Any} , @nospecialize (rt))
1865
+ # consistent if the argtype is immutable
1866
+ isempty (argtypes) && return EFFECTS_THROWS
1867
+ obj = argtypes[1 ]
1868
+ isvarargtype (obj) && return Effects (EFFECTS_THROWS; consistent= ALWAYS_FALSE)
1869
+ consistent = is_immutable_argtype (obj) ? ALWAYS_TRUE : ALWAYS_FALSE
1870
+ # access to `isbitstype`-field initialized with undefined value leads to undefined behavior
1871
+ # so should taint `:consistent`-cy while access to uninitialized non-`isbitstype` field
1872
+ # throws `UndefRefError` so doesn't need to taint it
1873
+ # NOTE `getfield_notundefined` conservatively checks if this field is never initialized
1874
+ # with undefined value so that we don't taint `:consistent`-cy too aggressively here
1875
+ if ! (length (argtypes) ≥ 2 && getfield_notundefined (widenconst (obj), argtypes[2 ]))
1876
+ consistent = ALWAYS_FALSE
1877
+ end
1878
+ if getfield_boundscheck (argtypes) != = true
1879
+ # If we cannot independently prove inboundsness, taint consistency.
1880
+ # The inbounds-ness assertion requires dynamic reachability, while
1881
+ # :consistent needs to be true for all input values.
1882
+ # N.B. We do not taint for `--check-bounds=no` here -that happens in
1883
+ # InferenceState.
1884
+ if length (argtypes) ≥ 2 && getfield_nothrow (argtypes[1 ], argtypes[2 ], true )
1885
+ nothrow = ALWAYS_TRUE
1886
+ else
1887
+ consistent = nothrow = ALWAYS_FALSE
1888
+ end
1889
+ else
1890
+ nothrow = getfield_nothrow (argtypes) ? ALWAYS_TRUE : ALWAYS_FALSE
1891
+ end
1892
+ return Effects (EFFECTS_TOTAL; consistent, nothrow)
1893
+ end
1894
+
1895
+ function getglobal_effects (argtypes:: Vector{Any} , @nospecialize (rt))
1896
+ consistent = nothrow = ALWAYS_FALSE
1897
+ if getglobal_nothrow (argtypes)
1898
+ # typeasserts below are already checked in `getglobal_nothrow`
1899
+ M, s = (argtypes[1 ]:: Const ). val:: Module , (argtypes[2 ]:: Const ). val:: Symbol
1900
+ if isconst (M, s)
1901
+ consistent = nothrow = ALWAYS_TRUE
1902
+ else
1903
+ nothrow = ALWAYS_TRUE
1904
+ end
1905
+ end
1906
+ return Effects (EFFECTS_TOTAL; consistent, nothrow)
1907
+ end
1908
+
1853
1909
function builtin_effects (f:: Builtin , argtypes:: Vector{Any} , @nospecialize (rt))
1854
1910
if isa (f, IntrinsicFunction)
1855
1911
return intrinsic_effects (f, argtypes)
1856
1912
end
1857
1913
1858
1914
@assert ! contains_is (_SPECIAL_BUILTINS, f)
1859
1915
1860
- if (f === Core. getfield || f === Core. isdefined) && length (argtypes) >= 2
1861
- # consistent if the argtype is immutable
1862
- if isvarargtype (argtypes[1 ])
1863
- return Effects (; effect_free= ALWAYS_TRUE, terminates= ALWAYS_TRUE, nonoverlayed= true )
1864
- end
1865
- s = widenconst (argtypes[1 ])
1866
- if isType (s) || ! isa (s, DataType) || isabstracttype (s)
1867
- return Effects (; effect_free= ALWAYS_TRUE, terminates= ALWAYS_TRUE, nonoverlayed= true )
1868
- end
1869
- s = s:: DataType
1870
- consistent = ! ismutabletype (s) ? ALWAYS_TRUE : ALWAYS_FALSE
1871
- # access to `isbitstype`-field initialized with undefined value leads to undefined behavior
1872
- # so should taint `:consistent`-cy while access to uninitialized non-`isbitstype` field
1873
- # throws `UndefRefError` so doesn't need to taint it
1874
- # NOTE `getfield_notundefined` conservatively checks if this field is never initialized
1875
- # with undefined value so that we don't taint `:consistent`-cy too aggressively here
1876
- if f === Core. getfield && ! getfield_notundefined (s, argtypes[2 ])
1877
- consistent = ALWAYS_FALSE
1878
- end
1879
- if f === Core. getfield && ! isvarargtype (argtypes[end ]) && getfield_boundscheck (argtypes) != = true
1880
- # If we cannot independently prove inboundsness, taint consistency.
1881
- # The inbounds-ness assertion requires dynamic reachability, while
1882
- # :consistent needs to be true for all input values.
1883
- # N.B. We do not taint for `--check-bounds=no` here -that happens in
1884
- # InferenceState.
1885
- if getfield_nothrow (argtypes[1 ], argtypes[2 ], true )
1886
- nothrow = ALWAYS_TRUE
1887
- else
1888
- consistent = nothrow = ALWAYS_FALSE
1889
- end
1890
- else
1891
- nothrow = (! isvarargtype (argtypes[end ]) && builtin_nothrow (f, argtypes, rt)) ?
1892
- ALWAYS_TRUE : ALWAYS_FALSE
1893
- end
1894
- effect_free = ALWAYS_TRUE
1916
+ if f === isdefined
1917
+ return isdefined_effects (argtypes)
1918
+ elseif f === getfield
1919
+ return getfield_effects (argtypes, rt)
1895
1920
elseif f === getglobal
1896
- if getglobal_nothrow (argtypes)
1897
- consistent = isconst ( # types are already checked in `getglobal_nothrow`
1898
- (argtypes[1 ]:: Const ). val:: Module , (argtypes[2 ]:: Const ). val:: Symbol ) ?
1899
- ALWAYS_TRUE : ALWAYS_FALSE
1900
- nothrow = ALWAYS_TRUE
1901
- else
1902
- consistent = nothrow = ALWAYS_FALSE
1903
- end
1904
- effect_free = ALWAYS_TRUE
1921
+ return getglobal_effects (argtypes, rt)
1905
1922
else
1906
1923
consistent = contains_is (_CONSISTENT_BUILTINS, f) ? ALWAYS_TRUE : ALWAYS_FALSE
1907
1924
effect_free = (contains_is (_EFFECT_FREE_BUILTINS, f) || contains_is (_PURE_BUILTINS, f)) ?
1908
1925
ALWAYS_TRUE : ALWAYS_FALSE
1909
1926
nothrow = (! (! isempty (argtypes) && isvarargtype (argtypes[end ])) && builtin_nothrow (f, argtypes, rt)) ?
1910
1927
ALWAYS_TRUE : ALWAYS_FALSE
1928
+ return Effects (EFFECTS_TOTAL; consistent, effect_free, nothrow)
1911
1929
end
1912
-
1913
- return Effects (EFFECTS_TOTAL; consistent, effect_free, nothrow)
1914
1930
end
1915
1931
1916
1932
function builtin_nothrow (@nospecialize (f), argtypes:: Vector{Any} , @nospecialize (rt))
0 commit comments