@@ -2014,59 +2014,88 @@ function intrinsic_effects(f::IntrinsicFunction, argtypes::Vector{Any})
20142014        nothrow =  nothrow ?  ALWAYS_TRUE :  TRISTATE_UNKNOWN)
20152015end 
20162016
2017- #  TODO : this function is a very buggy and poor model of the return_type function
2018- #  since abstract_call_gf_by_type is a very inaccurate model of _method and of typeinf_type,
2017+ #  TODO : this function is a very buggy and poor model of the ` return_type`  function
2018+ #  since ` abstract_call_gf_by_type`  is a very inaccurate model of ` _method`  and of ` typeinf_type` ,
20192019#  while this assumes that it is an absolutely precise and accurate and exact model of both
20202020function  return_type_tfunc (interp:: AbstractInterpreter , argtypes:: Vector{Any} , sv:: InferenceState )
2021-     if  length (argtypes) ==  3 
2022-         tt =  argtypes[3 ]
2023-         if  isa (tt, Const) ||  (isType (tt) &&  ! has_free_typevars (tt))
2024-             aft =  argtypes[2 ]
2025-             if  isa (aft, Const) ||  (isType (aft) &&  ! has_free_typevars (aft)) || 
2026-                    (isconcretetype (aft) &&  ! (aft <:  Builtin ))
2027-                 af_argtype =  isa (tt, Const) ?  tt. val :  (tt:: DataType ). parameters[1 ]
2028-                 if  isa (af_argtype, DataType) &&  af_argtype <:  Tuple 
2029-                     argtypes_vec =  Any[aft, af_argtype. parameters... ]
2030-                     if  contains_is (argtypes_vec, Union{})
2031-                         return  CallMeta (Const (Union{}), false )
2032-                     end 
2033-                     #  Run the abstract_call without restricting abstract call
2034-                     #  sites. Otherwise, our behavior model of abstract_call
2035-                     #  below will be wrong.
2036-                     old_restrict =  sv. restrict_abstract_call_sites
2037-                     sv. restrict_abstract_call_sites =  false 
2038-                     call =  abstract_call (interp, ArgInfo (nothing , argtypes_vec), sv, - 1 )
2039-                     sv. restrict_abstract_call_sites =  old_restrict
2040-                     info =  verbose_stmt_info (interp) ?  ReturnTypeCallInfo (call. info) :  false 
2041-                     rt =  widenconditional (call. rt)
2042-                     if  isa (rt, Const)
2043-                         #  output was computed to be constant
2044-                         return  CallMeta (Const (typeof (rt. val)), info)
2045-                     end 
2046-                     rt =  widenconst (rt)
2047-                     if  rt ===  Bottom ||  (isconcretetype (rt) &&  ! iskindtype (rt))
2048-                         #  output cannot be improved so it is known for certain
2049-                         return  CallMeta (Const (rt), info)
2050-                     elseif  ! isempty (sv. pclimitations)
2051-                         #  conservatively express uncertainty of this result
2052-                         #  in two ways: both as being a subtype of this, and
2053-                         #  because of LimitedAccuracy causes
2054-                         return  CallMeta (Type{<: rt }, info)
2055-                     elseif  (isa (tt, Const) ||  isconstType (tt)) && 
2056-                         (isa (aft, Const) ||  isconstType (aft))
2057-                         #  input arguments were known for certain
2058-                         #  XXX : this doesn't imply we know anything about rt
2059-                         return  CallMeta (Const (rt), info)
2060-                     elseif  isType (rt)
2061-                         return  CallMeta (Type{rt}, info)
2062-                     else 
2063-                         return  CallMeta (Type{<: rt }, info)
2064-                     end 
2065-                 end 
2066-             end 
2067-         end 
2068-     end 
2069-     return  CallMeta (Type, false )
2021+     length (argtypes) ==  3  ||  return  CallMeta (Type, false )
2022+     aft =  argtypes[2 ]
2023+     if  ! (isa (aft, Const) || 
2024+          (isType (aft) &&  ! has_free_typevars (aft)) || 
2025+          (isconcretetype (aft) &&  ! (aft <:  Builtin )))
2026+         return  CallMeta (Type, false )
2027+     end 
2028+     tt =  argtypes[3 ]
2029+     isa (tt, Const) ||  (isType (tt) &&  ! has_free_typevars (tt)) ||  return  CallMeta (Type, false )
2030+     af_argtype =  isa (tt, Const) ?  tt. val :  (tt:: DataType ). parameters[1 ]
2031+     (isa (af_argtype, DataType) &&  af_argtype <:  Tuple ) ||  return  CallMeta (Type, false )
2032+     argtypes_vec =  Any[aft, af_argtype. parameters... ]
2033+     if  contains_is (argtypes_vec, Union{})
2034+         return  CallMeta (Const (Union{}), false )
2035+     end 
2036+     call, _ =  virtual_abstract_call (interp, argtypes_vec, sv)
2037+     rt =  widenconditional (call. rt)
2038+     info =  verbose_stmt_info (interp) ?  VirtualCallInfo (call. info) :  false 
2039+     if  isa (rt, Const)
2040+         #  output was computed to be constant
2041+         return  CallMeta (Const (typeof (rt. val)), info)
2042+     end 
2043+     rt =  widenconst (rt)
2044+     if  rt ===  Bottom ||  (isconcretetype (rt) &&  ! iskindtype (rt))
2045+         #  output cannot be improved so it is known for certain
2046+         return  CallMeta (Const (rt), info)
2047+     elseif  ! isempty (sv. pclimitations)
2048+         #  conservatively express uncertainty of this result in two ways:
2049+         #  both as being a subtype of this, and because of LimitedAccuracy causes
2050+         return  CallMeta (Type{<: rt }, info)
2051+     end 
2052+     aft =  argtypes[2 ]
2053+     tt =  argtypes[3 ]
2054+     if  (isa (tt, Const) ||  isconstType (tt)) &&  (isa (aft, Const) ||  isconstType (aft))
2055+         #  input arguments were known for certain
2056+         #  XXX : this doesn't imply we know anything about rt
2057+         return  CallMeta (Const (rt), info)
2058+     elseif  isType (rt)
2059+         return  CallMeta (Type{rt}, info)
2060+     end 
2061+     return  CallMeta (Type{<: rt }, info)
2062+ end 
2063+ 
2064+ #  XXX  this tfunc has the same unreliability as `return_type_tfunc`, and also some duplications with it
2065+ function  infer_effects_tfunc (interp:: AbstractInterpreter , argtypes:: Vector{Any} , sv:: InferenceState )
2066+     length (argtypes) ==  3  ||  return  CallMeta (Effects, false )
2067+     aft =  argtypes[2 ]
2068+     tt =  argtypes[3 ]
2069+     #  models the infer_effects function only when the input arguments are fully known
2070+     if  ! ((isa (tt, Const) ||  isconstType (tt)) &&  (isa (aft, Const) ||  isconstType (aft)))
2071+         return  CallMeta (Effects, false )
2072+     end 
2073+     af_argtype =  isa (tt, Const) ?  tt. val :  (tt:: DataType ). parameters[1 ]
2074+     (isa (af_argtype, DataType) &&  af_argtype <:  Tuple ) ||  return  CallMeta (Effects, false )
2075+     argtypes_vec =  Any[aft, af_argtype. parameters... ]
2076+     call, effects =  virtual_abstract_call (interp, argtypes_vec, sv)
2077+     info =  verbose_stmt_info (interp) ?  VirtualCallInfo (call. info) :  false 
2078+     if  ! isempty (sv. pclimitations)
2079+         #  conservatively express uncertainty of this result
2080+         return  CallMeta (Effects, false )
2081+     end 
2082+     return  CallMeta (Const (effects), info)
2083+ end 
2084+ 
2085+ #  first set temporal states, then model inference on this call with the virtual `abstract_call`,
2086+ #  and finally reset to the original states
2087+ function  virtual_abstract_call (interp:: AbstractInterpreter , argtypes:: Vector{Any} , sv:: InferenceState )
2088+     old_restrict =  sv. restrict_abstract_call_sites
2089+     old_effects =  sv. ipo_effects
2090+     #  Run the `abstract_call` without restricting abstract call sites.
2091+     #  Otherwise, our behavior model of `abstract_call` below will be wrong.
2092+     sv. restrict_abstract_call_sites =  false 
2093+     sv. ipo_effects =  EFFECTS_TOTAL #  XXX  respect inbounds_taints_consistency?
2094+     call =  abstract_call (interp, ArgInfo (nothing , argtypes), sv, - 1 )
2095+     effects =  sv. ipo_effects
2096+     sv. restrict_abstract_call_sites =  old_restrict
2097+     sv. ipo_effects =  old_effects
2098+     return  call, effects
20702099end 
20712100
20722101#  N.B.: typename maps type equivalence classes to a single value
0 commit comments