Skip to content

Commit 4dcce49

Browse files
committed
Always return the shorter Vararg length.
The type `var` might be switched during intersection. Thus previous result looks order dependent. When we intersect 2 `Vararg`s' length, we should always return the shorter one. As we has consumed the extra elements in `intersect_tuple`. Also fix #37257
1 parent 652b040 commit 4dcce49

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/subtype.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,13 +2165,21 @@ static jl_value_t *set_var_to_const(jl_varbinding_t *bb, jl_value_t *v JL_MAYBE_
21652165
offset = -othervar->offset;
21662166
assert(!othervar || othervar->offset == -offset);
21672167
if (bb->lb == jl_bottom_type && bb->ub == (jl_value_t*)jl_any_type) {
2168-
if (jl_is_long(v))
2169-
v = jl_box_long(jl_unbox_long(v) + offset);
2170-
bb->lb = bb->ub = v;
2168+
if (jl_is_long(v)) {
2169+
size_t iv = jl_unbox_long(v);
2170+
v = jl_box_long(iv + offset);
2171+
bb->lb = bb->ub = v;
2172+
// Here we always return the shorter `Vararg`'s length.
2173+
if (offset > 0) return jl_box_long(iv);
2174+
}
2175+
else
2176+
bb->lb = bb->ub = v;
21712177
}
21722178
else if (jl_is_long(v) && jl_is_long(bb->lb)) {
21732179
if (jl_unbox_long(v) + offset != jl_unbox_long(bb->lb))
21742180
return jl_bottom_type;
2181+
// Here we always return the shorter `Vararg`'s length.
2182+
if (offset < 0) return bb->lb;
21752183
}
21762184
else if (!jl_egal(v, bb->lb)) {
21772185
return jl_bottom_type;
@@ -2186,11 +2194,13 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
21862194
return jl_bottom_type;
21872195
record_var_occurrence(bb, e, 2);
21882196
if (jl_is_long(bb->lb)) {
2189-
if (bb->offset == 0)
2190-
return bb->lb;
2191-
if (jl_unbox_long(bb->lb) < bb->offset)
2197+
ssize_t blb = jl_unbox_long(bb->lb);
2198+
if ((blb < bb->offset) || (blb < 0))
21922199
return jl_bottom_type;
2193-
return jl_box_long(jl_unbox_long(bb->lb) - bb->offset);
2200+
// Here we always return the shorter `Vararg`'s length.
2201+
if (bb->offset <= 0)
2202+
return bb->lb;
2203+
return jl_box_long(blb - bb->offset);
21942204
}
21952205
return (jl_value_t*)tv;
21962206
}
@@ -3045,6 +3055,9 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa
30453055
assert(xx->ub != x);
30463056
}
30473057
JL_GC_POP();
3058+
// Here we always return the shorter `Vararg`'s length.
3059+
if ((xx && xx->offset < 0) || (yy && yy->offset > 0))
3060+
return x;
30483061
return y;
30493062
}
30503063
record_var_occurrence(xx, e, param);

0 commit comments

Comments
 (0)