Skip to content

Commit bd7d3f5

Browse files
vtjnashJeffBezanson
authored andcommitted
improve handling of TypeConstructor Types in the generic function cache. fixes #11840
when TypeConstructors showed up as parameters of Type objects in the generic function cache, the type intersection result would trick inference into caching it in the wrong place and using it when it didn't apply. fix that by checking explicitly for arguments declared with ::TypeConstructor and ensuring they are matched and cached correctly also fix a similar issue for inserting/matching Type{T} in the gf cache
1 parent f42b222 commit bd7d3f5

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/gf.c

+17-3
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ static int cache_match_by_type(jl_value_t **types, size_t n, jl_tupletype_t *sig
7878
}
7979
}
8080
jl_value_t *a = types[i];
81-
if (jl_is_datatype(a) && jl_is_datatype(decl) &&
82-
((jl_datatype_t*)decl)->name == jl_type_type->name &&
83-
((jl_datatype_t*)a )->name == jl_type_type->name) {
81+
if (jl_is_type_type(a) && jl_is_type_type(decl)) {
8482
jl_value_t *tp0 = jl_tparam0(decl);
8583
if (tp0 == (jl_value_t*)jl_typetype_tvar) {
8684
// in the case of Type{T}, the types don't have
@@ -522,6 +520,22 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
522520
}
523521
if (set_to_any || isstaged) {
524522
}
523+
else if (jl_is_type_type(elt) && jl_is_typector(jl_tparam0(elt)) &&
524+
decl_i == (jl_value_t*)jl_typector_type) {
525+
// TypeConstructors are problematic because they can be alternate
526+
// representations of any type. If we matched this method because
527+
// it matched the leaf type TypeConstructor, then don't
528+
// cache something different since that doesn't necessarily actually apply
529+
jl_svecset(newparams, i, jl_typector_type);
530+
}
531+
else if (jl_is_type_type(elt) && decl_i == (jl_value_t*)jl_datatype_type) {
532+
// similarly, if we matched Type{T<:Any}::DataType,
533+
// then we don't want to cache it that way
534+
// since lookup will think we matched ::Type{T}
535+
// and that is quite a different thing
536+
jl_svecset(newparams, i, jl_datatype_type);
537+
need_guard_entries = 1; // DataType has a UID so its precedence in the cache may be too high
538+
}
525539
else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt)) &&
526540
// give up on specializing static parameters for Type{Type{Type{...}}}
527541
(jl_is_type_type(jl_tparam0(jl_tparam0(elt))) ||

test/core.jl

+19
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,25 @@ let T = TypeVar(:T, Tuple{Vararg{RangeIndex}}, true)
174174
@test args_morespecific(t2, t1)
175175
end
176176

177+
# issue #11840
178+
f11840(::Type) = "Type"
179+
f11840(::DataType) = "DataType"
180+
@test f11840(Type) == "DataType"
181+
@test f11840(AbstractVector) == "Type"
182+
183+
g11840(::DataType) = 1
184+
g11840(::Type) = 2
185+
@test g11840(Vector.body) == 1
186+
@test g11840(Vector) == 2
187+
@test g11840(Vector.body) == 1
188+
189+
h11840(::DataType) = '1'
190+
h11840(::Type) = '2'
191+
h11840(::TypeConstructor) = '3'
192+
@test h11840(Vector) == '3'
193+
@test h11840(Vector.body) == '1'
194+
@test h11840(Vector) == '3'
195+
177196
# join
178197
@test typejoin(Int8,Int16) === Signed
179198
@test typejoin(Int,AbstractString) === Any

0 commit comments

Comments
 (0)