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.

In fact, we should always return the shorter `Vararg` length.
As former terms has been taken care by `intersect_tuple`.

Also fix JuliaLang#37257
  • Loading branch information
N5N3 committed Aug 23, 2022
1 parent 3eac8e2 commit 707fcdb
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 12 deletions.
13 changes: 9 additions & 4 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -2167,9 +2167,13 @@ 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;
jl_value_t *vnew = v;
if (bb->need_offset && jl_is_long(v)) {
vnew = jl_box_long(jl_unbox_long(v) + offset);
// Here we always return the smaller Varargs length.
if (offset < 0) v = vnew;
}
bb->lb = bb->ub = vnew;
}
else if (jl_is_long(v) && jl_is_long(bb->lb)) {
long lv = jl_unbox_long(v), llb = jl_unbox_long(bb->lb);
Expand All @@ -2194,7 +2198,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 smaller Varargs length.
if (bb->offset <= 0)
return bb->lb;
if (jl_unbox_long(bb->lb) < bb->offset)
return jl_bottom_type;
Expand Down
20 changes: 12 additions & 8 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2046,18 +2046,22 @@ let f36443(::NTuple{N}=[(f36443,),(1,2)][2],::Val{N}=Val(2)) where{N} = 0
end

let C = Tuple{Val{3},Int,Int,Int,Int},
Cerror = Tuple{Val{3},Int,Int,Int,Int,Int},
As = (Tuple{Val{N},Int,Vararg{T,N}} where {T,N},
Tuple{Val{N},Int,Vararg{T,N}} where {N,T}),
Bs = (Tuple{Val{3},Vararg{T,N}} where {T,N},
Tuple{Val{3},Vararg{T,N}} where {N,T},
Tuple{Val{3},Vararg{T}} where {T})
for A in As
@test_broken typeintersect(A, Bs[1]) != Cerror
@test_broken typeintersect(A, Bs[3]) != Cerror
@test_broken typeintersect(A, Bs[3]) != Cerror

@test typeintersect(Bs[1], A) == C # Union{} on master
@testintersect(A, Bs[2], C) # Union{} on master
for A in As, B in Bs
@testintersect(A, B, C)
end
end

#issue #36443
let T = Tuple{Val{N}, Any, Any, Vararg{Any,N}} where N,
C = Tuple{Val{1}, Any, Any, Any}
@testintersect(T, Tuple{Val{1}, Vararg{Any}}, C)
@testintersect(T, Tuple{Val{1}, Any, Vararg{Any}}, C)
@testintersect(T, Tuple{Val{1}, Any, Any, Vararg{Any}}, C)
@testintersect(T, Tuple{Val{1}, Any, Any, Any, Vararg{Any}}, C)
@testintersect(T, Tuple{Val{1}, Any, Any, Any, Any, Vararg{Any}}, Union{})
end

0 comments on commit 707fcdb

Please sign in to comment.