Skip to content

Commit

Permalink
Always return the shorter Vararg length.
Browse files Browse the repository at this point in the history
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 JuliaLang#37257
  • Loading branch information
N5N3 committed Aug 24, 2022
1 parent 9c49e12 commit 2903135
Showing 1 changed file with 18 additions and 4 deletions.
22 changes: 18 additions & 4 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -2165,13 +2165,21 @@ static jl_value_t *set_var_to_const(jl_varbinding_t *bb, jl_value_t *v JL_MAYBE_
offset = -othervar->offset;
assert(!othervar || othervar->offset == -offset);
if (bb->lb == jl_bottom_type && bb->ub == (jl_value_t*)jl_any_type) {
if (jl_is_long(v))
v = jl_box_long(jl_unbox_long(v) + offset);
bb->lb = bb->ub = v;
if (jl_is_long(v)) {
size_t iv = jl_unbox_long(v);
v = jl_box_long(iv + offset);
bb->lb = bb->ub = v;
// Here we always return the shorter `Vararg`'s length.
if (offset > 0) return jl_box_long(iv);
}
else
bb->lb = bb->ub = v;
}
else if (jl_is_long(v) && jl_is_long(bb->lb)) {
if (jl_unbox_long(v) + offset != jl_unbox_long(bb->lb))
return jl_bottom_type;
// Here we always return the shorter `Vararg`'s length.
if (offset < 0) return bb->lb;
}
else if (!jl_egal(v, bb->lb)) {
return jl_bottom_type;
Expand All @@ -2186,7 +2194,8 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
return jl_bottom_type;
record_var_occurrence(bb, e, 2);
if (jl_is_long(bb->lb)) {
if (bb->offset == 0)
// Here we always return the shorter `Vararg`'s length.
if (bb->offset <= 0)
return bb->lb;
if (jl_unbox_long(bb->lb) < bb->offset)
return jl_bottom_type;
Expand Down Expand Up @@ -3045,6 +3054,11 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa
assert(xx->ub != x);
}
JL_GC_POP();
// Here we always return the shorter `Vararg`'s length.
if ((xx && xx->offset < 0) || (yy && yy->offset > 0))
return x;
if ((xx && xx->offset > 0) || (yy && yy->offset < 0))
return y;
return y;
}
record_var_occurrence(xx, e, param);
Expand Down

0 comments on commit 2903135

Please sign in to comment.