@@ -348,23 +348,100 @@ function InferenceState(result::InferenceResult, cache::Symbol, interp::Abstract
348348 return InferenceState (result, src, cache, interp)
349349end
350350
351+ """
352+ constrains_param(var::TypeVar, sig, covariant::Bool)
353+
354+ Check if `var` will be constrained to have a definite value
355+ in any concrete leaftype subtype of `sig`.
356+
357+ It is used as a helper to determine whether type intersection is guaranteed to be able to
358+ find a value for a particular type parameter.
359+ A necessary condition for type intersection to not assign a parameter is that it only
360+ appears in a `Union[All]` and during subtyping some other union component (that does not
361+ constrain the type parameter) is selected.
362+ """
363+ function constrains_param (var:: TypeVar , @nospecialize (typ), covariant:: Bool )
364+ typ === var && return true
365+ while typ isa UnionAll
366+ covariant && constrains_param (var, typ. var. ub, covariant) && return true
367+ # typ.var.lb doesn't constrain var
368+ typ = typ. body
369+ end
370+ if typ isa Union
371+ # for unions, verify that both options would constrain var
372+ ba = constrains_param (var, typ. a, covariant)
373+ bb = constrains_param (var, typ. b, covariant)
374+ (ba && bb) && return true
375+ elseif typ isa DataType
376+ # return true if any param constrains var
377+ fc = length (typ. parameters)
378+ if fc > 0
379+ if typ. name === Tuple. name
380+ # vararg tuple needs special handling
381+ for i in 1 : (fc - 1 )
382+ p = typ. parameters[i]
383+ constrains_param (var, p, covariant) && return true
384+ end
385+ lastp = typ. parameters[fc]
386+ vararg = unwrap_unionall (lastp)
387+ if vararg isa Core. TypeofVararg && isdefined (vararg, :N )
388+ constrains_param (var, vararg. N, covariant) && return true
389+ # T = vararg.parameters[1] doesn't constrain var
390+ else
391+ constrains_param (var, lastp, covariant) && return true
392+ end
393+ else
394+ for i in 1 : fc
395+ p = typ. parameters[i]
396+ constrains_param (var, p, false ) && return true
397+ end
398+ end
399+ end
400+ end
401+ return false
402+ end
403+
404+ """
405+ MaybeUndefSP(typ)
406+ is_maybeundefsp(typ) -> Bool
407+ unwrap_maybeundefsp(typ) -> Any
408+
409+ A special wrapper that represents a static parameter that could be undefined at runtime.
410+ This does not participate in the native type system nor the inference lattice,
411+ and it thus should be always unwrapped when performing any type or lattice operations on it.
412+ """
413+ struct MaybeUndefSP
414+ typ
415+ MaybeUndefSP (@nospecialize typ) = new (typ)
416+ end
417+ is_maybeundefsp (@nospecialize typ) = isa (typ, MaybeUndefSP)
418+ unwrap_maybeundefsp (@nospecialize typ) = isa (typ, MaybeUndefSP) ? typ. typ : typ
419+ is_maybeundefsp (sptypes:: Vector{Any} , idx:: Int ) = is_maybeundefsp (sptypes[idx])
420+ unwrap_maybeundefsp (sptypes:: Vector{Any} , idx:: Int ) = unwrap_maybeundefsp (sptypes[idx])
421+
422+ const EMPTY_SPTYPES = Any[]
423+
351424function sptypes_from_meth_instance (linfo:: MethodInstance )
352- toplevel = ! isa (linfo. def, Method)
353- if ! toplevel && isempty (linfo. sparam_vals) && isa (linfo. def. sig, UnionAll)
425+ def = linfo. def
426+ isa (def, Method) || return EMPTY_SPTYPES # toplevel
427+ sig = def. sig
428+ if isempty (linfo. sparam_vals)
429+ isa (sig, UnionAll) || return EMPTY_SPTYPES
354430 # linfo is unspecialized
355431 sp = Any[]
356- sig = linfo . def . sig
357- while isa (sig, UnionAll)
358- push! (sp, sig. var)
359- sig = sig. body
432+ sig′ = sig
433+ while isa (sig′ , UnionAll)
434+ push! (sp, sig′ . var)
435+ sig′ = sig′ . body
360436 end
361437 else
362438 sp = collect (Any, linfo. sparam_vals)
363439 end
364440 for i = 1 : length (sp)
365441 v = sp[i]
366442 if v isa TypeVar
367- temp = linfo. def. sig
443+ maybe_undef = ! constrains_param (v, linfo. specTypes, true )
444+ temp = sig
368445 for j = 1 : i- 1
369446 temp = temp. body
370447 end
@@ -402,12 +479,13 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
402479 tv = TypeVar (v. name, lb, ub)
403480 ty = UnionAll (tv, Type{tv})
404481 end
482+ @label ty_computed
483+ maybe_undef && (ty = MaybeUndefSP (ty))
405484 elseif isvarargtype (v)
406485 ty = Int
407486 else
408487 ty = Const (v)
409488 end
410- @label ty_computed
411489 sp[i] = ty
412490 end
413491 return sp
0 commit comments