Skip to content

Commit 4a38e79

Browse files
authored
Fix some vararg-related subtyping issues (#31698)
* Fix jl_obvious_subtype with INT vararg constraint * Fix a vararg-related non-transitivity in subtyping * Fix another vararg subtype issue * Take advantage of their being at most one UnionAll wrapped around a Vararg Upon construction, we normalize `Vararg{T, N} where {T,N}` to `Vararg{T where T, N} where N`, thus there can be at most one UnionAll wrapper around a Vararg. In subtyping we were already assuming that there can be at most two such wrappers, so simply adjust that and add an appropriate assertion to make sure we catch any cases where this ever goes wrong. * Rewrite subtype_tuple to fix extra cases * Put back the case for naked varargs * Update test/subtype.jl Co-Authored-By: Keno <keno@alumni.harvard.edu> * Add test for #31805 * Fix style review comments * Rename variable * In person review changes * Fix bug * Handle integer bounds on left arguments in the environment In subtyping proper, variables introduced on the left (i.e. forall variables) don't have any equality constraints, because we have no syntax for creating them. However, intersection does sometimes create such environments, so we need to handle it in subtyping.
1 parent b6f10cb commit 4a38e79

File tree

5 files changed

+410
-141
lines changed

5 files changed

+410
-141
lines changed

base/compiler/typelimits.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,13 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
9292
return t # easy case
9393
elseif isa(t, DataType) && isempty(t.parameters)
9494
return t # fast path: unparameterized are always simple
95-
elseif isa(unwrap_unionall(t), DataType) && isa(c, Type) && c !== Union{} && c <: t
96-
return t # t is already wider than the comparison in the type lattice
97-
elseif is_derived_type_from_any(unwrap_unionall(t), sources, depth)
98-
return t # t isn't something new
95+
else
96+
ut = unwrap_unionall(t)
97+
if isa(ut, DataType) && ut.name !== _va_typename && isa(c, Type) && c !== Union{} && c <: t
98+
return t # t is already wider than the comparison in the type lattice
99+
elseif is_derived_type_from_any(ut, sources, depth)
100+
return t # t isn't something new
101+
end
99102
end
100103
# peel off (and ignore) wrappers - they contribute no useful information, so we don't need to consider their size
101104
# first attempt to turn `c` into a type that contributes meaningful information

src/jltypes.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,10 +1082,19 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
10821082
continue;
10831083
if (jl_is_datatype(pi))
10841084
continue;
1085+
if (jl_is_vararg_type(pi)) {
1086+
pi = jl_unwrap_vararg(pi);
1087+
if (jl_has_free_typevars(pi))
1088+
continue;
1089+
}
10851090
// normalize types equal to wrappers (prepare for wrapper_id)
10861091
jl_value_t *tw = extract_wrapper(pi);
10871092
if (tw && tw != pi && (tn != jl_type_typename || jl_typeof(pi) == jl_typeof(tw)) &&
10881093
jl_types_equal(pi, tw)) {
1094+
if (jl_is_vararg_type(iparams[i])) {
1095+
tw = jl_wrap_vararg(tw, jl_tparam1(jl_unwrap_unionall(iparams[i])));
1096+
tw = jl_rewrap_unionall(tw, iparams[i]);
1097+
}
10891098
iparams[i] = tw;
10901099
if (p) jl_gc_wb(p, tw);
10911100
}
@@ -1138,6 +1147,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
11381147
}
11391148
int did_normalize = 0;
11401149
jl_value_t *last2 = normalize_vararg(last);
1150+
assert(!jl_is_unionall(last2) || !jl_is_unionall(((jl_unionall_t*)last2)->body));
11411151
if (last2 != last) {
11421152
last = last2;
11431153
did_normalize = 1;

src/julia.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,14 @@ STATIC_INLINE jl_value_t *jl_unwrap_vararg(jl_value_t *v) JL_NOTSAFEPOINT
12781278
return jl_tparam0(jl_unwrap_unionall(v));
12791279
}
12801280

1281+
STATIC_INLINE size_t jl_vararg_length(jl_value_t *v) JL_NOTSAFEPOINT
1282+
{
1283+
assert(jl_is_vararg_type(v));
1284+
jl_value_t *len = jl_tparam1(jl_unwrap_unionall(v));
1285+
assert(jl_is_long(len));
1286+
return jl_unbox_long(len);
1287+
}
1288+
12811289
STATIC_INLINE jl_vararg_kind_t jl_vararg_kind(jl_value_t *v) JL_NOTSAFEPOINT
12821290
{
12831291
if (!jl_is_vararg_type(v))

0 commit comments

Comments
 (0)