Skip to content

Commit

Permalink
add another tuple subtyping fast path (#34065)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JeffBezanson authored and KristofferC committed Apr 11, 2020
1 parent aa6a6c2 commit ff2e1b4
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 1 deletion.
2 changes: 1 addition & 1 deletion base/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ regex_opts_str(opts) = (isassigned(_regex_opts_str) ? _regex_opts_str[] : init_r
# UInt32 to String mapping for some compile options
const _regex_opts_str = Ref{ImmutableDict{UInt32,String}}()

init_regex() = _regex_opts_str[] = foldl(0:15, init=ImmutableDict{UInt32,String}()) do d, o
@noinline init_regex() = _regex_opts_str[] = foldl(0:15, init=ImmutableDict{UInt32,String}()) do d, o
opt = UInt32(0)
str = ""
if o & 1 != 0
Expand Down
27 changes: 27 additions & 0 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1346,10 +1346,37 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
return x == y || jl_egal(x, y);
}

static int is_indefinite_length_tuple_type(jl_value_t *x)
{
x = jl_unwrap_unionall(x);
if (!jl_is_tuple_type(x))
return 0;
size_t n = jl_nparams(x);
return n > 0 && jl_vararg_kind(jl_tparam(x, n-1)) == JL_VARARG_UNBOUND;
}

static int is_definite_length_tuple_type(jl_value_t *x)
{
if (jl_is_typevar(x))
x = ((jl_tvar_t*)x)->ub;
x = jl_unwrap_unionall(x);
if (!jl_is_tuple_type(x))
return 0;
size_t n = jl_nparams(x);
if (n == 0)
return 1;
jl_vararg_kind_t k = jl_vararg_kind(jl_tparam(x, n-1));
return k == JL_VARARG_NONE || k == JL_VARARG_INT;
}

static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
{
if (obviously_egal(x, y)) return 1;

if ((is_indefinite_length_tuple_type(x) && is_definite_length_tuple_type(y)) ||
(is_definite_length_tuple_type(x) && is_indefinite_length_tuple_type(y)))
return 0;

jl_unionstate_t oldLunions = e->Lunions;
memset(e->Lunions.stack, 0, sizeof(e->Lunions.stack));
int sub;
Expand Down
11 changes: 11 additions & 0 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,17 @@ end
@test "a" * 'b' * 'c' == "abc"
end

# this tests a possible issue in subtyping with long argument lists to `string(...)`
getString(dic, key) = haskey(dic,key) ? "$(dic[key])" : ""
function getData(dic)
val = getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"") *
"," * getString(dic,"") * "," * getString(dic,"") * "," * getString(dic,"")
end
@test getData(Dict()) == ",,,,,,,,,,,,,,,,,,"

@testset "unrecognized escapes in string/char literals" begin
@test_throws Meta.ParseError Meta.parse("\"\\.\"")
@test_throws Meta.ParseError Meta.parse("\'\\.\'")
Expand Down
3 changes: 3 additions & 0 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1698,3 +1698,6 @@ s26065 = Ref{Tuple{T,Ref{Union{Ref{Tuple{Ref{Union{Ref{Ref{Tuple{Ref{Tuple{Union
@testintersect(Tuple{:N,Vararg{Any,T}} where T,
Tuple{T,Vararg{Any,T}} where T,
Union{})

@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}},
Tuple{Type{Tuple{Vararg{V, N} where N}}, Tuple{Vararg{V, N} where N}} where V)

0 comments on commit ff2e1b4

Please sign in to comment.