Skip to content

Commit aa07c1c

Browse files
authored
add another tuple subtyping fast path (#34065)
This handles cases like `Type{<:Tuple{A}} <: Type{Tuple{Vararg{_,N} where N}}`, i.e. where a fixed-length tuple type cannot ever equal an indefinite-length tuple type.
1 parent d295d35 commit aa07c1c

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

base/regex.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ regex_opts_str(opts) = (isassigned(_regex_opts_str) ? _regex_opts_str[] : init_r
669669
# UInt32 to String mapping for some compile options
670670
const _regex_opts_str = Ref{ImmutableDict{UInt32,String}}()
671671

672-
init_regex() = _regex_opts_str[] = foldl(0:15, init=ImmutableDict{UInt32,String}()) do d, o
672+
@noinline init_regex() = _regex_opts_str[] = foldl(0:15, init=ImmutableDict{UInt32,String}()) do d, o
673673
opt = UInt32(0)
674674
str = ""
675675
if o & 1 != 0

src/subtype.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,10 +1346,37 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
13461346
return x == y || jl_egal(x, y);
13471347
}
13481348

1349+
static int is_indefinite_length_tuple_type(jl_value_t *x)
1350+
{
1351+
x = jl_unwrap_unionall(x);
1352+
if (!jl_is_tuple_type(x))
1353+
return 0;
1354+
size_t n = jl_nparams(x);
1355+
return n > 0 && jl_vararg_kind(jl_tparam(x, n-1)) == JL_VARARG_UNBOUND;
1356+
}
1357+
1358+
static int is_definite_length_tuple_type(jl_value_t *x)
1359+
{
1360+
if (jl_is_typevar(x))
1361+
x = ((jl_tvar_t*)x)->ub;
1362+
x = jl_unwrap_unionall(x);
1363+
if (!jl_is_tuple_type(x))
1364+
return 0;
1365+
size_t n = jl_nparams(x);
1366+
if (n == 0)
1367+
return 1;
1368+
jl_vararg_kind_t k = jl_vararg_kind(jl_tparam(x, n-1));
1369+
return k == JL_VARARG_NONE || k == JL_VARARG_INT;
1370+
}
1371+
13491372
static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
13501373
{
13511374
if (obviously_egal(x, y)) return 1;
13521375

1376+
if ((is_indefinite_length_tuple_type(x) && is_definite_length_tuple_type(y)) ||
1377+
(is_definite_length_tuple_type(x) && is_indefinite_length_tuple_type(y)))
1378+
return 0;
1379+
13531380
jl_unionstate_t oldLunions = e->Lunions;
13541381
memset(e->Lunions.stack, 0, sizeof(e->Lunions.stack));
13551382
int sub;

test/strings/basic.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,17 @@ end
647647
@test "a" * 'b' * 'c' == "abc"
648648
end
649649

650+
# this tests a possible issue in subtyping with long argument lists to `string(...)`
651+
getString(dic, key) = haskey(dic,key) ? "$(dic[key])" : ""
652+
function getData(dic)
653+
val = getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
654+
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
655+
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
656+
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
657+
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"")
658+
end
659+
@test getData(Dict()) == ",,,,,,,,,,,,,,,,,,"
660+
650661
@testset "unrecognized escapes in string/char literals" begin
651662
@test_throws Meta.ParseError Meta.parse("\"\\.\"")
652663
@test_throws Meta.ParseError Meta.parse("\'\\.\'")

test/subtype.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,3 +1698,6 @@ s26065 = Ref{Tuple{T,Ref{Union{Ref{Tuple{Ref{Union{Ref{Ref{Tuple{Ref{Tuple{Union
16981698
@testintersect(Tuple{:N,Vararg{Any,T}} where T,
16991699
Tuple{T,Vararg{Any,T}} where T,
17001700
Union{})
1701+
1702+
@test !issub(Tuple{Type{T}, T} where T<:Tuple{String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}, String, Union{Base.Regex, AbstractChar, AbstractString}},
1703+
Tuple{Type{Tuple{Vararg{V, N} where N}}, Tuple{Vararg{V, N} where N}} where V)

0 commit comments

Comments
 (0)