diff --git a/src/subtype.c b/src/subtype.c index c67beecae9dbd..2a24ee2811176 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -4167,6 +4167,34 @@ static int might_intersect_concrete(jl_value_t *a) return 0; } +static jl_value_t *widen_sparam_bound(jl_value_t *t) +{ + if (!jl_has_free_typevars(t)) + return t; + if (jl_is_datatype(t)) + return ((jl_datatype_t*)t)->name->wrapper; + return (jl_value_t*)jl_any_type; +} + +static jl_value_t *narrow_sparam_bound(jl_value_t *t) +{ + if (!jl_has_free_typevars(t)) + return t; + return jl_bottom_type; +} + +static jl_value_t *widen_sparam_estimate(jl_value_t *t) +{ + if (!jl_is_typevar(t)) + return t; + jl_tvar_t *v = (jl_tvar_t*)t; + jl_value_t *wlb = narrow_sparam_bound(v->lb); + jl_value_t *wub = widen_sparam_bound(v->ub); + if (wlb != v->lb || wub != v->ub) + return (jl_value_t*)jl_new_typevar(v->name, wlb, wub); + return t; +} + // sets *issubty to 1 iff `a` is a subtype of `b` jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, int *issubty) { @@ -4251,7 +4279,7 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * jl_svec_t *e = jl_alloc_svec(sz); for (i = 0; i < sz; i++) { assert(env[i]); - jl_svecset(e, i, env[i]); + jl_svecset(e, i, widen_sparam_estimate(env[i])); } *penv = e; } diff --git a/test/subtype.jl b/test/subtype.jl index a57ee2f23cb9b..94c10b44c513a 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2565,3 +2565,9 @@ let a = Tuple{Union{Nothing, Type{Pair{T1}} where T1}} b = Tuple{Type{X2} where X2<:(Pair{T2, Y2} where {Src, Z2<:Src, Y2<:Union{Val{Z2}, Z2}})} where T2 @test !Base.has_free_typevars(typeintersect(a, b)) end + +# issue #50709 +let (t, (tv,)) = intersection_env(Type{Vector{S}} where {T, S<:AbstractVector{T}}, Type{Vector{T}} where T) + @test tv isa TypeVar + @test !Base.has_free_typevars(tv.ub) +end