@@ -221,14 +221,23 @@ is_effect_overridden(override::EffectsOverride, effect::Symbol) = getfield(overr
221
221
222
222
add_remark! (:: AbstractInterpreter , sv:: Union{InferenceState, IRCode} , remark) = return
223
223
224
- function bail_out_toplevel_call (:: AbstractInterpreter , @nospecialize (callsig), sv:: Union{InferenceState, IRCode} )
225
- return isa (sv, InferenceState) && sv. restrict_abstract_call_sites && ! isdispatchtuple (callsig)
224
+ struct InferenceLoopState
225
+ sig
226
+ rt
227
+ effects:: Effects
228
+ function InferenceLoopState (@nospecialize (sig), @nospecialize (rt), effects:: Effects )
229
+ new (sig, rt, effects)
230
+ end
231
+ end
232
+
233
+ function bail_out_toplevel_call (:: AbstractInterpreter , state:: InferenceLoopState , sv:: Union{InferenceState, IRCode} )
234
+ return isa (sv, InferenceState) && sv. restrict_abstract_call_sites && ! isdispatchtuple (state. sig)
226
235
end
227
- function bail_out_call (:: AbstractInterpreter , @nospecialize (rt) , sv:: Union{InferenceState, IRCode} )
228
- return rt === Any
236
+ function bail_out_call (:: AbstractInterpreter , state :: InferenceLoopState , sv:: Union{InferenceState, IRCode} )
237
+ return state . rt === Any
229
238
end
230
- function bail_out_apply (:: AbstractInterpreter , @nospecialize (rt) , sv:: Union{InferenceState, IRCode} )
231
- return rt === Any
239
+ function bail_out_apply (:: AbstractInterpreter , state :: InferenceLoopState , sv:: Union{InferenceState, IRCode} )
240
+ return state . rt === Any
232
241
end
233
242
234
243
was_reached (sv:: InferenceState , pc:: Int ) = sv. ssavaluetypes[pc] != = NOT_FOUND
@@ -348,15 +357,100 @@ function InferenceState(result::InferenceResult, cache::Symbol, interp::Abstract
348
357
return InferenceState (result, src, cache, interp)
349
358
end
350
359
360
+ """
361
+ constrains_param(var::TypeVar, sig, covariant::Bool, type_constrains::Bool)
362
+
363
+ Check if `var` will be constrained to have a definite value
364
+ in any concrete leaftype subtype of `sig`.
365
+
366
+ It is used as a helper to determine whether type intersection is guaranteed to be able to
367
+ find a value for a particular type parameter.
368
+ A necessary condition for type intersection to not assign a parameter is that it only
369
+ appears in a `Union[All]` and during subtyping some other union component (that does not
370
+ constrain the type parameter) is selected.
371
+
372
+ The `type_constrains` flag determines whether Type{T} is considered to be constraining
373
+ `T`. This is not true in general, because of the existence of types with free type
374
+ parameters, however, some callers would like to ignore this corner case.
375
+ """
376
+ function constrains_param (var:: TypeVar , @nospecialize (typ), covariant:: Bool , type_constrains:: Bool = false )
377
+ typ === var && return true
378
+ while typ isa UnionAll
379
+ covariant && constrains_param (var, typ. var. ub, covariant, type_constrains) && return true
380
+ # typ.var.lb doesn't constrain var
381
+ typ = typ. body
382
+ end
383
+ if typ isa Union
384
+ # for unions, verify that both options would constrain var
385
+ ba = constrains_param (var, typ. a, covariant, type_constrains)
386
+ bb = constrains_param (var, typ. b, covariant, type_constrains)
387
+ (ba && bb) && return true
388
+ elseif typ isa DataType
389
+ # return true if any param constrains var
390
+ fc = length (typ. parameters)
391
+ if fc > 0
392
+ if typ. name === Tuple. name
393
+ # vararg tuple needs special handling
394
+ for i in 1 : (fc - 1 )
395
+ p = typ. parameters[i]
396
+ constrains_param (var, p, covariant, type_constrains) && return true
397
+ end
398
+ lastp = typ. parameters[fc]
399
+ vararg = unwrap_unionall (lastp)
400
+ if vararg isa Core. TypeofVararg && isdefined (vararg, :N )
401
+ constrains_param (var, vararg. N, covariant, type_constrains) && return true
402
+ # T = vararg.parameters[1] doesn't constrain var
403
+ else
404
+ constrains_param (var, lastp, covariant, type_constrains) && return true
405
+ end
406
+ else
407
+ if typ. name === typename (Type) && typ. parameters[1 ] === var && var. ub === Any
408
+ # Types with free type parameters are <: Type cause the typevar
409
+ # to be unconstrained because Type{T} with free typevars is illegal
410
+ return type_constrains
411
+ end
412
+ for i in 1 : fc
413
+ p = typ. parameters[i]
414
+ constrains_param (var, p, false , type_constrains) && return true
415
+ end
416
+ end
417
+ end
418
+ end
419
+ return false
420
+ end
421
+
422
+ """
423
+ MaybeUndefSP(typ)
424
+ is_maybeundefsp(typ) -> Bool
425
+ unwrap_maybeundefsp(typ) -> Any
426
+
427
+ A special wrapper that represents a static parameter that could be undefined at runtime.
428
+ This does not participate in the native type system nor the inference lattice,
429
+ and it thus should be always unwrapped when performing any type or lattice operations on it.
430
+ """
431
+ struct MaybeUndefSP
432
+ typ
433
+ MaybeUndefSP (@nospecialize typ) = new (typ)
434
+ end
435
+ is_maybeundefsp (@nospecialize typ) = isa (typ, MaybeUndefSP)
436
+ unwrap_maybeundefsp (@nospecialize typ) = isa (typ, MaybeUndefSP) ? typ. typ : typ
437
+ is_maybeundefsp (sptypes:: Vector{Any} , idx:: Int ) = is_maybeundefsp (sptypes[idx])
438
+ unwrap_maybeundefsp (sptypes:: Vector{Any} , idx:: Int ) = unwrap_maybeundefsp (sptypes[idx])
439
+
440
+ const EMPTY_SPTYPES = Any[]
441
+
351
442
function sptypes_from_meth_instance (linfo:: MethodInstance )
352
- toplevel = ! isa (linfo. def, Method)
353
- if ! toplevel && isempty (linfo. sparam_vals) && isa (linfo. def. sig, UnionAll)
443
+ def = linfo. def
444
+ isa (def, Method) || return EMPTY_SPTYPES # toplevel
445
+ sig = def. sig
446
+ if isempty (linfo. sparam_vals)
447
+ isa (sig, UnionAll) || return EMPTY_SPTYPES
354
448
# linfo is unspecialized
355
449
sp = Any[]
356
- sig = linfo . def . sig
357
- while isa (sig, UnionAll)
358
- push! (sp, sig. var)
359
- sig = sig. body
450
+ sig′ = sig
451
+ while isa (sig′ , UnionAll)
452
+ push! (sp, sig′ . var)
453
+ sig′ = sig′ . body
360
454
end
361
455
else
362
456
sp = collect (Any, linfo. sparam_vals)
@@ -365,9 +459,7 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
365
459
v = sp[i]
366
460
if v isa TypeVar
367
461
fromArg = 0
368
- # if this parameter came from arg::Type{T}, then `arg` is more precise than
369
- # Type{T} where lb<:T<:ub
370
- sig = linfo. def. sig
462
+ maybe_undef = ! constrains_param (v, linfo. specTypes, #= covariant=# true )
371
463
temp = sig
372
464
for j = 1 : i- 1
373
465
temp = temp. body
@@ -408,6 +500,8 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
408
500
ty = UnionAll (tv, Type{tv})
409
501
end
410
502
end
503
+ @label ty_computed
504
+ maybe_undef && (ty = MaybeUndefSP (ty))
411
505
elseif isvarargtype (v)
412
506
ty = Int
413
507
else
@@ -429,14 +523,14 @@ end
429
523
430
524
update_valid_age! (edge:: InferenceState , sv:: InferenceState ) = update_valid_age! (sv, edge. valid_worlds)
431
525
432
- function record_ssa_assign! (ssa_id:: Int , @nospecialize (new), frame:: InferenceState )
526
+ function record_ssa_assign! (𝕃ᵢ :: AbstractLattice , ssa_id:: Int , @nospecialize (new), frame:: InferenceState )
433
527
ssavaluetypes = frame. ssavaluetypes
434
528
old = ssavaluetypes[ssa_id]
435
- if old === NOT_FOUND || ! (new ⊑ old)
529
+ if old === NOT_FOUND || ! ⊑ (𝕃ᵢ, new, old)
436
530
# typically, we expect that old ⊑ new (that output information only
437
531
# gets less precise with worse input information), but to actually
438
532
# guarantee convergence we need to use tmerge here to ensure that is true
439
- ssavaluetypes[ssa_id] = old === NOT_FOUND ? new : tmerge (old, new)
533
+ ssavaluetypes[ssa_id] = old === NOT_FOUND ? new : tmerge (𝕃ᵢ, old, new)
440
534
W = frame. ip
441
535
for r in frame. ssavalue_uses[ssa_id]
442
536
if was_reached (frame, r)
519
613
520
614
get_curr_ssaflag (sv:: InferenceState ) = sv. src. ssaflags[sv. currpc]
521
615
522
- function narguments (sv:: InferenceState )
616
+ function narguments (sv:: InferenceState , include_va :: Bool = true )
523
617
def = sv. linfo. def
524
- isva = isa (def, Method) && def. isva
525
- nargs = length (sv. result. argtypes) - isva
618
+ nargs = length (sv. result. argtypes)
619
+ if ! include_va
620
+ nargs -= isa (def, Method) && def. isva
621
+ end
526
622
return nargs
527
623
end
0 commit comments