@@ -67,7 +67,7 @@ add_tfunc(throw, 1, 1, (@nospecialize(x)) -> Bottom, 0)
6767# if istype is true, the actual runtime value will definitely be a type (e.g. this is false for Union{Type{Int}, Int})
6868function instanceof_tfunc (@nospecialize (t))
6969 if isa (t, Const)
70- if isa (t. val, Type)
70+ if isa (t. val, Type) && valid_as_lattice (t . val)
7171 return t. val, true , isconcretetype (t. val), true
7272 end
7373 return Bottom, true , false , false # runtime throws on non-Type
@@ -79,6 +79,7 @@ function instanceof_tfunc(@nospecialize(t))
7979 return Bottom, true , false , false # literal Bottom or non-Type
8080 elseif isType (t)
8181 tp = t. parameters[1 ]
82+ valid_as_lattice (tp) || return Bottom, true , false , false # runtime unreachable / throws on non-Type
8283 return tp, ! has_free_typevars (tp), isconcretetype (tp), true
8384 elseif isa (t, UnionAll)
8485 t′ = unwrap_unionall (t)
@@ -473,7 +474,8 @@ function pointer_eltype(@nospecialize(ptr))
473474 unw = unwrap_unionall (a)
474475 if isa (unw, DataType) && unw. name === Ptr. body. name
475476 T = unw. parameters[1 ]
476- T isa Type && return rewrap_unionall (T, a)
477+ valid_as_lattice (T) || return Bottom
478+ return rewrap_unionall (T, a)
477479 end
478480 end
479481 return Any
@@ -486,7 +488,8 @@ function atomic_pointermodify_tfunc(ptr, op, v, order)
486488 if isa (unw, DataType) && unw. name === Ptr. body. name
487489 T = unw. parameters[1 ]
488490 # note: we could sometimes refine this to a PartialStruct if we analyzed `op(T, T)::T`
489- T isa Type && return rewrap_unionall (Pair{T, T}, a)
491+ valid_as_lattice (T) || return Bottom
492+ return rewrap_unionall (Pair{T, T}, a)
490493 end
491494 end
492495 return Pair
@@ -498,7 +501,8 @@ function atomic_pointerreplace_tfunc(ptr, x, v, success_order, failure_order)
498501 unw = unwrap_unionall (a)
499502 if isa (unw, DataType) && unw. name === Ptr. body. name
500503 T = unw. parameters[1 ]
501- T isa Type && return rewrap_unionall (ccall (:jl_apply_cmpswap_type , Any, (Any,), T), a)
504+ valid_as_lattice (T) || return Bottom
505+ return rewrap_unionall (ccall (:jl_apply_cmpswap_type , Any, (Any,), T), a)
502506 end
503507 end
504508 return ccall (:jl_apply_cmpswap_type , Any, (Any,), T) where T
@@ -754,8 +758,8 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), boundscheck::
754758 s0 = widenconst (s00)
755759 s = unwrap_unionall (s0)
756760 if isa (s, Union)
757- return getfield_nothrow (rewrap (s. a, s00), name, boundscheck) &&
758- getfield_nothrow (rewrap (s. b, s00), name, boundscheck)
761+ return getfield_nothrow (rewrap_unionall (s. a, s00), name, boundscheck) &&
762+ getfield_nothrow (rewrap_unionall (s. b, s00), name, boundscheck)
759763 elseif isa (s, DataType)
760764 # Can't say anything about abstract types
761765 isabstracttype (s) && return false
@@ -782,8 +786,8 @@ getfield_tfunc(s00, name, order, boundscheck) = (@nospecialize; getfield_tfunc(s
782786function getfield_tfunc (@nospecialize (s00), @nospecialize (name))
783787 s = unwrap_unionall (s00)
784788 if isa (s, Union)
785- return tmerge (getfield_tfunc (rewrap (s. a,s00), name),
786- getfield_tfunc (rewrap (s. b,s00), name))
789+ return tmerge (getfield_tfunc (rewrap_unionall (s. a, s00), name),
790+ getfield_tfunc (rewrap_unionall (s. b, s00), name))
787791 elseif isa (s, Conditional)
788792 return Bottom # Bool has no fields
789793 elseif isa (s, Const) || isconstType (s)
@@ -857,9 +861,6 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
857861 end
858862 return Any
859863 end
860- # If no value has this type, then this statement should be unreachable.
861- # Bail quickly now.
862- has_concrete_subtype (s) || return Union{}
863864 if s. name === _NAMEDTUPLE_NAME && ! isconcretetype (s)
864865 if isa (name, Const) && isa (name. val, Symbol)
865866 if isa (s. parameters[1 ], Tuple)
@@ -878,7 +879,9 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
878879 return getfield_tfunc (_ts, name)
879880 end
880881 ftypes = datatype_fieldtypes (s)
881- if isempty (ftypes)
882+ # If no value has this type, then this statement should be unreachable.
883+ # Bail quickly now.
884+ if ! has_concrete_subtype (s) || isempty (ftypes)
882885 return Bottom
883886 end
884887 if isa (name, Conditional)
@@ -1072,8 +1075,8 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
10721075
10731076 su = unwrap_unionall (s0)
10741077 if isa (su, Union)
1075- return tmerge (fieldtype_tfunc (rewrap (su. a, s0), name),
1076- fieldtype_tfunc (rewrap (su. b, s0), name))
1078+ return tmerge (fieldtype_tfunc (rewrap_unionall (su. a, s0), name),
1079+ fieldtype_tfunc (rewrap_unionall (su. b, s0), name))
10771080 end
10781081
10791082 s, exact = instanceof_tfunc (s0)
@@ -1085,8 +1088,8 @@ function _fieldtype_tfunc(@nospecialize(s), exact::Bool, @nospecialize(name))
10851088 exact = exact && ! has_free_typevars (s)
10861089 u = unwrap_unionall (s)
10871090 if isa (u, Union)
1088- ta0 = _fieldtype_tfunc (rewrap (u. a, s), exact, name)
1089- tb0 = _fieldtype_tfunc (rewrap (u. b, s), exact, name)
1091+ ta0 = _fieldtype_tfunc (rewrap_unionall (u. a, s), exact, name)
1092+ tb0 = _fieldtype_tfunc (rewrap_unionall (u. b, s), exact, name)
10901093 ta0 ⊑ tb0 && return tb0
10911094 tb0 ⊑ ta0 && return ta0
10921095 ta, exacta, _, istypea = instanceof_tfunc (ta0)
@@ -1296,7 +1299,11 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
12961299 end
12971300 end
12981301 end
1299- largs == 1 && return isa (args[1 ], Type) ? typeintersect (args[1 ], Type) : Type
1302+ if largs == 1 # Union{T} --> T
1303+ u1 = typeintersect (widenconst (args[1 ]), Type)
1304+ valid_as_lattice (u1) || return Bottom
1305+ return u1
1306+ end
13001307 hasnonType && return Type
13011308 ty = Union{}
13021309 allconst = true
@@ -1471,21 +1478,26 @@ end
14711478
14721479function arrayref_tfunc (@nospecialize (boundscheck), @nospecialize (a), @nospecialize i... )
14731480 a = widenconst (a)
1474- if a <: Array
1475- if isa (a, DataType) && isa (a. parameters[1 ], Type)
1476- return a. parameters[1 ]
1477- elseif isa (a, UnionAll) && ! has_free_typevars (a)
1478- unw = unwrap_unionall (a)
1479- if isa (unw, DataType)
1480- return rewrap_unionall (unw. parameters[1 ], a)
1481- end
1481+ if ! has_free_typevars (a) && a <: Array
1482+ a0 = a
1483+ if isa (a, UnionAll)
1484+ a = unwrap_unionall (a0)
1485+ end
1486+ if isa (a, DataType)
1487+ T = a. parameters[1 ]
1488+ valid_as_lattice (T) || return Bottom
1489+ return rewrap_unionall (T, a0)
14821490 end
14831491 end
14841492 return Any
14851493end
14861494add_tfunc (arrayref, 3 , INT_INF, arrayref_tfunc, 20 )
14871495add_tfunc (const_arrayref, 3 , INT_INF, arrayref_tfunc, 20 )
1488- add_tfunc (arrayset, 4 , INT_INF, (@nospecialize (boundscheck), @nospecialize (a), @nospecialize (v), @nospecialize i... )-> a, 20 )
1496+ function arrayset_tfunc (@nospecialize (boundscheck), @nospecialize (a), @nospecialize (v), @nospecialize i... )
1497+ # TODO : we could check that the type-intersect of arrayref_tfunc and v is non-empty or always throws
1498+ return a
1499+ end
1500+ add_tfunc (arrayset, 4 , INT_INF, arrayset_tfunc, 20 )
14891501
14901502function _opaque_closure_tfunc (@nospecialize (arg), @nospecialize (isva),
14911503 @nospecialize (lb), @nospecialize (ub), @nospecialize (source), env:: Vector{Any} ,
@@ -1508,6 +1520,7 @@ function _opaque_closure_tfunc(@nospecialize(arg), @nospecialize(isva),
15081520 return PartialOpaque (t, tuple_tfunc (env), isva. val, linfo, source. val)
15091521end
15101522
1523+ # whether getindex for the elements can potentially throw UndefRef
15111524function array_type_undefable (@nospecialize (a))
15121525 if isa (a, Union)
15131526 return array_type_undefable (a. a) || array_type_undefable (a. b)
@@ -1550,7 +1563,7 @@ function _builtin_nothrow(@nospecialize(f), argtypes::Array{Any,1}, @nospecializ
15501563 # Check that we can determine the element type
15511564 (isa (a, DataType) && isa (a. parameters[1 ], Type)) || return false
15521565 # Check that the element type is compatible with the element we're assigning
1553- (argtypes[3 ] ⊑ a. parameters[1 ]:: Type ) || return false
1566+ (argtypes[3 ] ⊑ a. parameters[1 ]) || return false
15541567 return true
15551568 elseif f === arrayref || f === const_arrayref
15561569 return array_builtin_common_nothrow (argtypes, 3 )
0 commit comments