Skip to content

Commit

Permalink
replace NULL with a innervar
Browse files Browse the repository at this point in the history
  • Loading branch information
N5N3 committed Mar 24, 2023
1 parent b745293 commit 508992c
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 49 deletions.
48 changes: 15 additions & 33 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -2389,8 +2389,16 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
return bb->lb;
return jl_box_long(blb - offset);
}
if (offset > 0)
return NULL;
if (offset > 0) {
if (bb->innervars == NULL)
bb->innervars = jl_alloc_array_1d(jl_array_any_type, 0);
jl_value_t *ntv = NULL;
JL_GC_PUSH1(&ntv);
ntv = (jl_value_t *)jl_new_typevar(tv->name, jl_bottom_type, (jl_value_t *)jl_any_type);
jl_array_ptr_1d_push(bb->innervars, ntv);
JL_GC_POP();
return ntv;
}
return (jl_value_t*)tv;
}

Expand Down Expand Up @@ -2520,26 +2528,6 @@ static int check_unsat_bound(jl_value_t *t, jl_tvar_t *v, jl_stenv_t *e) JL_NOTS
return 0;
}

//TODO: This doesn't work for nested `Tuple`.
static int has_free_vararg_length(jl_value_t *a, jl_stenv_t *e) {
if (jl_is_unionall(a))
a = jl_unwrap_unionall(a);
if (jl_is_datatype(a) && jl_is_tuple_type((jl_datatype_t *)a)) {
size_t lx = jl_nparams((jl_datatype_t *)a);
if (lx > 0) {
jl_value_t *la = jl_tparam((jl_datatype_t *)a, lx-1);
if (jl_is_vararg(la)) {
jl_value_t *len = jl_unwrap_vararg_num((jl_vararg_t *)la);
// return 1 if we meet a vararg with Null length
if (!len) return 1;
// or a typevar not in the current env.
if (jl_is_typevar(len))
return lookup(e, (jl_tvar_t *)len) == NULL;
}
}
}
return 0;
}

static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int8_t R, int param)
{
Expand Down Expand Up @@ -2583,11 +2571,6 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int
JL_GC_POP();
return jl_bottom_type;
}
if (jl_is_uniontype(ub) && !jl_is_uniontype(a)) {
bb->ub = ub;
bb->lb = jl_bottom_type;
ub = (jl_value_t*)b;
}
}
if (ub != (jl_value_t*)b) {
if (jl_has_free_typevars(ub)) {
Expand All @@ -2597,12 +2580,11 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int
}
}
bb->ub = ub;
// We get a imprecise Tuple here. Don't change `lb` and return the typevar directly.
if (has_free_vararg_length(ub, e) && !has_free_vararg_length(a, e)) {
JL_GC_POP();
return (jl_value_t*)b;
}
bb->lb = ub;
if ((jl_is_uniontype(ub) && !jl_is_uniontype(a)) ||
(jl_is_unionall(ub) && !jl_is_unionall(a)))
ub = (jl_value_t*)b;
else
bb->lb = ub;
}
JL_GC_POP();
return ub;
Expand Down
24 changes: 8 additions & 16 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1043,11 +1043,7 @@ function test_intersection()
Type{Tuple{Int,T}} where T<:Integer)
@testintersect(Type{<:Tuple{Any,Vararg{Any}}},
Type{Tuple{Vararg{Int,N}}} where N,
!Union{})

@test typeintersect(Type{<:Tuple{Any,Vararg{Any}}}, Type{Tuple{Vararg{Int,N}}} where N) != Type{Tuple{Int,Vararg{Int}}}
@test_broken typeintersect(Type{<:Tuple{Any,Vararg{Any}}}, Type{Tuple{Vararg{Int,N}}} where N) == Type{Tuple{Int,Vararg{Int,N}}} where N
@test_broken typeintersect(Type{<:Tuple{Any,Vararg{Any}}}, Type{Tuple{Vararg{Int,N}}} where N) != Type{<:Tuple{Int,Vararg{Int}}}
Type{Tuple{Int,Vararg{Int,N}}} where N)

@testintersect(Type{<:Array},
Type{AbstractArray{T}} where T,
Expand Down Expand Up @@ -2206,23 +2202,19 @@ let A = Pair{NTuple{N, Int}, NTuple{N, Int}} where N,
Bs = (Pair{<:Tuple{Int, Vararg{Int}}, <:Tuple{Int, Int, Vararg{Int}}},
Pair{Tuple{Int, Vararg{Int,N1}}, Tuple{Int, Int, Vararg{Int,N2}}} where {N1,N2},
Pair{<:Tuple{Int, Vararg{Int,N}} where {N}, <:Tuple{Int, Int, Vararg{Int,N}} where {N}})
Cerr = Pair{Tuple{Int, Vararg{Int, N}}, Tuple{Int, Int, Vararg{Int, N}}} where {N}
for B in Bs
C = typeintersect(A, B)
@test C == typeintersect(B, A) != Union{}
@test C != Cerr
@test_broken C != B
Cs = (Bs[2], Bs[2], Bs[3])
for (B, C) in zip(Bs, Cs)
# TODO: The ideal result is Pair{Tuple{Int, Int, Vararg{Int, N}}, Tuple{Int, Int, Vararg{Int, N}}} where {N}
@testintersect(A, B, C)
end
end

# Example from pr#39098
@testintersect(NTuple, Tuple{Any,Vararg}, Tuple{T, Vararg{T}} where {T})

let S = Val{T} where T<:Tuple{Tuple{Any, Vararg{Any}}}
T = Val{Tuple{Tuple{Vararg{Any, N}}}} where {N}
@testintersect(S, T, !Union{})
@test_broken typeintersect(S, T) != Val{Tuple{Tuple{Any, Vararg{Any}}}}
end
@testintersect(Val{T} where T<:Tuple{Tuple{Any, Vararg{Any}}},
Val{Tuple{Tuple{Vararg{Any, N}}}} where {N},
Val{Tuple{Tuple{Any, Vararg{Any, N}}}} where {N})

let A = Pair{NTuple{N, Int}, Val{N}} where N,
Bs = (Pair{<:Tuple{Int, Vararg{Int}}, <:Val},
Expand Down

0 comments on commit 508992c

Please sign in to comment.