@@ -149,6 +149,21 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
149149 return rettype
150150end
151151
152+
153+ function const_prop_profitable (arg)
154+ # have new information from argtypes that wasn't available from the signature
155+ if isa (arg, PartialStruct)
156+ for b in arg. fields
157+ isconstType (b) && return true
158+ const_prop_profitable (b) && return true
159+ end
160+ elseif ! isa (arg, Const) || (isa (arg. val, Symbol) || isa (arg. val, Type) || (! isa (arg. val, String) && isimmutable (arg. val)))
161+ # don't consider mutable values or Strings useful constants
162+ return true
163+ end
164+ return false
165+ end
166+
152167function abstract_call_method_with_const_args (@nospecialize (rettype), @nospecialize (f), argtypes:: Vector{Any} , match:: SimpleVector , sv:: InferenceState )
153168 method = match[3 ]:: Method
154169 nargs:: Int = method. nargs
@@ -158,12 +173,8 @@ function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecial
158173 for a in argtypes
159174 a = widenconditional (a)
160175 if has_nontrivial_const_info (a)
161- # have new information from argtypes that wasn't available from the signature
162- if ! isa (a, Const) || (isa (a. val, Symbol) || isa (a. val, Type) || (! isa (a. val, String) && isimmutable (a. val)))
163- # don't consider mutable values or Strings useful constants
164- haveconst = true
165- break
166- end
176+ haveconst = const_prop_profitable (a)
177+ haveconst && break
167178 end
168179 end
169180 haveconst || improvable_via_constant_propagation (rettype) || return Any
@@ -189,7 +200,7 @@ function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecial
189200 # in this case, see if all of the arguments are constants
190201 for a in argtypes
191202 a = widenconditional (a)
192- if ! isa (a, Const) && ! isconstType (a)
203+ if ! isa (a, Const) && ! isconstType (a) && ! isa (a, PartialStruct)
193204 return Any
194205 end
195206 end
384395# Union of Tuples of the same length is converted to Tuple of Unions.
385396# returns an array of types
386397function precise_container_type (@nospecialize (typ), vtypes:: VarTable , sv:: InferenceState )
387- if isa (typ, PartialTuple)
398+ if isa (typ, PartialStruct) && typ . typ . name === Tuple . name
388399 return typ. fields
389400 end
390401
498509# do apply(af, fargs...), where af is a function value
499510function abstract_apply (@nospecialize (aft), aargtypes:: Vector{Any} , vtypes:: VarTable , sv:: InferenceState ,
500511 max_methods = sv. params. MAX_METHODS)
501- if ! isa (aft, Const) && (! isType (aft) || has_free_typevars (aft))
502- if ! isconcretetype (aft) || (aft <: Builtin )
512+ aftw = widenconst (aft)
513+ if ! isa (aft, Const) && (! isType (aftw) || has_free_typevars (aftw))
514+ if ! isconcretetype (aftw) || (aftw <: Builtin )
503515 # non-constant function of unknown type: bail now,
504516 # since it seems unlikely that abstract_call will be able to do any better after splitting
505517 # this also ensures we don't call abstract_call_gf_by_type below on an IntrinsicFunction or Builtin
@@ -891,26 +903,37 @@ function abstract_eval(@nospecialize(e), vtypes::VarTable, sv::InferenceState)
891903 t = instanceof_tfunc (abstract_eval (e. args[1 ], vtypes, sv))[1 ]
892904 if isconcretetype (t) && ! t. mutable
893905 args = Vector {Any} (undef, length (e. args)- 1 )
894- isconst = true
906+ ats = Vector {Any} (undef, length (e. args)- 1 )
907+ anyconst = false
908+ allconst = true
895909 for i = 2 : length (e. args)
896910 at = abstract_eval (e. args[i], vtypes, sv)
911+ if ! anyconst
912+ anyconst = has_nontrivial_const_info (at)
913+ end
914+ ats[i- 1 ] = at
897915 if at === Bottom
898916 t = Bottom
899- isconst = false
917+ allconst = anyconst = false
900918 break
901919 elseif at isa Const
902920 if ! (at. val isa fieldtype (t, i - 1 ))
903921 t = Bottom
904- isconst = false
922+ allconst = anyconst = false
905923 break
906924 end
907925 args[i- 1 ] = at. val
908926 else
909- isconst = false
927+ allconst = false
910928 end
911929 end
912- if isconst
913- t = Const (ccall (:jl_new_structv , Any, (Any, Ptr{Cvoid}, UInt32), t, args, length (args)))
930+ # For now, don't allow partially initialized Const/PartialStruct
931+ if t != = Bottom && fieldcount (t) == length (ats)
932+ if allconst
933+ t = Const (ccall (:jl_new_structv , Any, (Any, Ptr{Cvoid}, UInt32), t, args, length (args)))
934+ elseif anyconst
935+ t = PartialStruct (t, ats)
936+ end
914937 end
915938 end
916939 elseif e. head === :splatnew
@@ -1077,7 +1100,7 @@ function typeinf_local(frame::InferenceState)
10771100 elseif hd === :return
10781101 pc´ = n + 1
10791102 rt = widenconditional (abstract_eval (stmt. args[1 ], s[pc], frame))
1080- if ! isa (rt, Const) && ! isa (rt, Type) && ! isa (rt, PartialTuple )
1103+ if ! isa (rt, Const) && ! isa (rt, Type) && ! isa (rt, PartialStruct )
10811104 # only propagate information we know we can store
10821105 # and is valid inter-procedurally
10831106 rt = widenconst (rt)
0 commit comments