@@ -637,13 +637,14 @@ static void jl_compilation_sig(
637
637
for (i = 0 ; i < np ; i ++ ) {
638
638
jl_value_t * elt = jl_tparam (tt , i );
639
639
jl_value_t * decl_i = jl_nth_slot_type (decl , i );
640
+ jl_value_t * type_i = jl_rewrap_unionall (decl_i , decl );
640
641
size_t i_arg = (i < nargs - 1 ? i : nargs - 1 );
641
642
642
- if (jl_is_kind (decl_i )) {
643
+ if (jl_is_kind (type_i )) {
643
644
// if we can prove the match was against the kind (not a Type)
644
645
// we want to put that in the cache instead
645
646
if (!* newparams ) * newparams = jl_svec_copy (tt -> parameters );
646
- elt = decl_i ;
647
+ elt = type_i ;
647
648
jl_svecset (* newparams , i , elt );
648
649
}
649
650
else if (jl_is_type_type (elt )) {
@@ -652,7 +653,7 @@ static void jl_compilation_sig(
652
653
// and the result of matching the type signature
653
654
// needs to be restricted to the concrete type 'kind'
654
655
jl_value_t * kind = jl_typeof (jl_tparam0 (elt ));
655
- if (jl_subtype (kind , decl_i ) && !jl_subtype ((jl_value_t * )jl_type_type , decl_i )) {
656
+ if (jl_subtype (kind , type_i ) && !jl_subtype ((jl_value_t * )jl_type_type , type_i )) {
656
657
// if we can prove the match was against the kind (not a Type)
657
658
// it's simpler (and thus better) to put that cache instead
658
659
if (!* newparams ) * newparams = jl_svec_copy (tt -> parameters );
@@ -664,7 +665,7 @@ static void jl_compilation_sig(
664
665
// not triggered for isdispatchtuple(tt), this attempts to handle
665
666
// some cases of adapting a random signature into a compilation signature
666
667
// if we get a kind, where we don't expect to accept one, widen it to something more expected (Type{T})
667
- if (!(jl_subtype (elt , decl_i ) && !jl_subtype ((jl_value_t * )jl_type_type , decl_i ))) {
668
+ if (!(jl_subtype (elt , type_i ) && !jl_subtype ((jl_value_t * )jl_type_type , type_i ))) {
668
669
if (!* newparams ) * newparams = jl_svec_copy (tt -> parameters );
669
670
elt = (jl_value_t * )jl_type_type ;
670
671
jl_svecset (* newparams , i , elt );
@@ -703,7 +704,7 @@ static void jl_compilation_sig(
703
704
jl_svecset (* newparams , i , jl_type_type );
704
705
}
705
706
else if (jl_is_type_type (elt )) { // elt isa Type{T}
706
- if (very_general_type (decl_i )) {
707
+ if (! jl_has_free_typevars (decl_i ) && very_general_type ( type_i )) {
707
708
/*
708
709
Here's a fairly simple heuristic: if this argument slot's
709
710
declared type is general (Type or Any),
@@ -742,15 +743,13 @@ static void jl_compilation_sig(
742
743
*/
743
744
if (!* newparams ) * newparams = jl_svec_copy (tt -> parameters );
744
745
if (i < nargs || !definition -> isva ) {
745
- jl_value_t * di = jl_type_intersection (decl_i , (jl_value_t * )jl_type_type );
746
+ jl_value_t * di = jl_type_intersection (type_i , (jl_value_t * )jl_type_type );
746
747
assert (di != (jl_value_t * )jl_bottom_type );
747
748
// issue #11355: DataType has a UID and so would take precedence in the cache
748
749
if (jl_is_kind (di ))
749
750
jl_svecset (* newparams , i , (jl_value_t * )jl_type_type );
750
751
else
751
752
jl_svecset (* newparams , i , di );
752
- // TODO: recompute static parameter values, so in extreme cases we
753
- // can give `T=Type` instead of `T=Type{Type{Type{...`. /* make editors happy:}}} */
754
753
}
755
754
else {
756
755
jl_svecset (* newparams , i , (jl_value_t * )jl_type_type );
@@ -759,14 +758,15 @@ static void jl_compilation_sig(
759
758
}
760
759
761
760
int notcalled_func = (i_arg > 0 && i_arg <= 8 && !(definition -> called & (1 << (i_arg - 1 ))) &&
761
+ !jl_has_free_typevars (decl_i ) &&
762
762
jl_subtype (elt , (jl_value_t * )jl_function_type ));
763
- if (notcalled_func && (decl_i == (jl_value_t * )jl_any_type ||
764
- decl_i == (jl_value_t * )jl_function_type ||
765
- (jl_is_uniontype (decl_i ) && // Base.Callable
766
- ((((jl_uniontype_t * )decl_i )-> a == (jl_value_t * )jl_function_type &&
767
- ((jl_uniontype_t * )decl_i )-> b == (jl_value_t * )jl_type_type ) ||
768
- (((jl_uniontype_t * )decl_i )-> b == (jl_value_t * )jl_function_type &&
769
- ((jl_uniontype_t * )decl_i )-> a == (jl_value_t * )jl_type_type ))))) {
763
+ if (notcalled_func && (type_i == (jl_value_t * )jl_any_type ||
764
+ type_i == (jl_value_t * )jl_function_type ||
765
+ (jl_is_uniontype (type_i ) && // Base.Callable
766
+ ((((jl_uniontype_t * )type_i )-> a == (jl_value_t * )jl_function_type &&
767
+ ((jl_uniontype_t * )type_i )-> b == (jl_value_t * )jl_type_type ) ||
768
+ (((jl_uniontype_t * )type_i )-> b == (jl_value_t * )jl_function_type &&
769
+ ((jl_uniontype_t * )type_i )-> a == (jl_value_t * )jl_type_type ))))) {
770
770
// and attempt to despecialize types marked Function, Callable, or Any
771
771
// when called with a subtype of Function but is not called
772
772
if (!* newparams ) * newparams = jl_svec_copy (tt -> parameters );
@@ -833,6 +833,7 @@ static void jl_compilation_sig(
833
833
// compute whether this type signature is a possible return value from jl_compilation_sig given a concrete-type for `tt`
834
834
JL_DLLEXPORT int jl_isa_compileable_sig (
835
835
jl_tupletype_t * type ,
836
+ jl_svec_t * sparams ,
836
837
jl_method_t * definition )
837
838
{
838
839
jl_value_t * decl = definition -> sig ;
@@ -886,6 +887,7 @@ JL_DLLEXPORT int jl_isa_compileable_sig(
886
887
for (i = 0 ; i < np ; i ++ ) {
887
888
jl_value_t * elt = jl_tparam (type , i );
888
889
jl_value_t * decl_i = jl_nth_slot_type ((jl_value_t * )decl , i );
890
+ jl_value_t * type_i = jl_rewrap_unionall (decl_i , decl );
889
891
size_t i_arg = (i < nargs - 1 ? i : nargs - 1 );
890
892
891
893
if (jl_is_vararg (elt )) {
@@ -919,25 +921,26 @@ JL_DLLEXPORT int jl_isa_compileable_sig(
919
921
920
922
if (jl_is_kind (elt )) {
921
923
// kind slots always get guard entries (checking for subtypes of Type)
922
- if (jl_subtype (elt , decl_i ) && !jl_subtype ((jl_value_t * )jl_type_type , decl_i ))
924
+ if (jl_subtype (elt , type_i ) && !jl_subtype ((jl_value_t * )jl_type_type , type_i ))
923
925
continue ;
924
926
// TODO: other code paths that could reach here
925
927
return 0 ;
926
928
}
927
- else if (jl_is_kind (decl_i )) {
929
+ else if (jl_is_kind (type_i )) {
928
930
return 0 ;
929
931
}
930
932
931
933
if (jl_is_type_type (jl_unwrap_unionall (elt ))) {
932
- int iscalled = i_arg > 0 && i_arg <= 8 && (definition -> called & (1 << (i_arg - 1 )));
934
+ int iscalled = (i_arg > 0 && i_arg <= 8 && (definition -> called & (1 << (i_arg - 1 )))) ||
935
+ jl_has_free_typevars (decl_i );
933
936
if (jl_types_equal (elt , (jl_value_t * )jl_type_type )) {
934
- if (!iscalled && very_general_type (decl_i ))
937
+ if (!iscalled && very_general_type (type_i ))
935
938
continue ;
936
939
if (i >= nargs && definition -> isva )
937
940
continue ;
938
941
return 0 ;
939
942
}
940
- if (!iscalled && very_general_type (decl_i ))
943
+ if (!iscalled && very_general_type (type_i ))
941
944
return 0 ;
942
945
if (!jl_is_datatype (elt ))
943
946
return 0 ;
@@ -949,7 +952,7 @@ JL_DLLEXPORT int jl_isa_compileable_sig(
949
952
jl_value_t * kind = jl_typeof (jl_tparam0 (elt ));
950
953
if (kind == jl_bottom_type )
951
954
return 0 ; // Type{Union{}} gets normalized to typeof(Union{})
952
- if (jl_subtype (kind , decl_i ) && !jl_subtype ((jl_value_t * )jl_type_type , decl_i ))
955
+ if (jl_subtype (kind , type_i ) && !jl_subtype ((jl_value_t * )jl_type_type , type_i ))
953
956
return 0 ; // gets turned into a kind
954
957
955
958
else if (jl_is_type_type (jl_tparam0 (elt )) &&
@@ -963,7 +966,7 @@ JL_DLLEXPORT int jl_isa_compileable_sig(
963
966
this can be determined using a type intersection.
964
967
*/
965
968
if (i < nargs || !definition -> isva ) {
966
- jl_value_t * di = jl_type_intersection (decl_i , (jl_value_t * )jl_type_type );
969
+ jl_value_t * di = jl_type_intersection (type_i , (jl_value_t * )jl_type_type );
967
970
JL_GC_PUSH1 (& di );
968
971
assert (di != (jl_value_t * )jl_bottom_type );
969
972
if (jl_is_kind (di )) {
@@ -984,14 +987,15 @@ JL_DLLEXPORT int jl_isa_compileable_sig(
984
987
}
985
988
986
989
int notcalled_func = (i_arg > 0 && i_arg <= 8 && !(definition -> called & (1 << (i_arg - 1 ))) &&
990
+ !jl_has_free_typevars (decl_i ) &&
987
991
jl_subtype (elt , (jl_value_t * )jl_function_type ));
988
- if (notcalled_func && (decl_i == (jl_value_t * )jl_any_type ||
989
- decl_i == (jl_value_t * )jl_function_type ||
990
- (jl_is_uniontype (decl_i ) && // Base.Callable
991
- ((((jl_uniontype_t * )decl_i )-> a == (jl_value_t * )jl_function_type &&
992
- ((jl_uniontype_t * )decl_i )-> b == (jl_value_t * )jl_type_type ) ||
993
- (((jl_uniontype_t * )decl_i )-> b == (jl_value_t * )jl_function_type &&
994
- ((jl_uniontype_t * )decl_i )-> a == (jl_value_t * )jl_type_type ))))) {
992
+ if (notcalled_func && (type_i == (jl_value_t * )jl_any_type ||
993
+ type_i == (jl_value_t * )jl_function_type ||
994
+ (jl_is_uniontype (type_i ) && // Base.Callable
995
+ ((((jl_uniontype_t * )type_i )-> a == (jl_value_t * )jl_function_type &&
996
+ ((jl_uniontype_t * )type_i )-> b == (jl_value_t * )jl_type_type ) ||
997
+ (((jl_uniontype_t * )type_i )-> b == (jl_value_t * )jl_function_type &&
998
+ ((jl_uniontype_t * )type_i )-> a == (jl_value_t * )jl_type_type ))))) {
995
999
// and attempt to despecialize types marked Function, Callable, or Any
996
1000
// when called with a subtype of Function but is not called
997
1001
if (elt == (jl_value_t * )jl_function_type )
@@ -1087,7 +1091,7 @@ static jl_method_instance_t *cache_method(
1087
1091
// cache miss. Alternatively, we may use the original signature in the
1088
1092
// cache, but use this return for compilation.
1089
1093
//
1090
- // In most cases `!jl_isa_compileable_sig(tt, definition)`,
1094
+ // In most cases `!jl_isa_compileable_sig(tt, sparams, definition)`,
1091
1095
// although for some cases, (notably Varargs)
1092
1096
// we might choose a replacement type that's preferable but not strictly better
1093
1097
int issubty ;
@@ -1099,7 +1103,7 @@ static jl_method_instance_t *cache_method(
1099
1103
}
1100
1104
newparams = NULL ;
1101
1105
}
1102
- // TODO: maybe assert(jl_isa_compileable_sig(compilationsig, definition));
1106
+ // TODO: maybe assert(jl_isa_compileable_sig(compilationsig, sparams, definition));
1103
1107
newmeth = jl_specializations_get_linfo (definition , (jl_value_t * )compilationsig , sparams );
1104
1108
1105
1109
jl_tupletype_t * cachett = tt ;
@@ -2281,9 +2285,21 @@ JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_methtable_t *mt, jl_t
2281
2285
jl_methtable_t * kwmt = mt == jl_kwcall_mt ? jl_kwmethod_table_for (m -> sig ) : mt ;
2282
2286
intptr_t nspec = (kwmt == NULL || kwmt == jl_type_type_mt || kwmt == jl_nonfunction_mt || kwmt == jl_kwcall_mt ? m -> nargs + 1 : jl_atomic_load_relaxed (& kwmt -> max_args ) + 2 + 2 * (mt == jl_kwcall_mt ));
2283
2287
jl_compilation_sig (ti , env , m , nspec , & newparams );
2284
- tt = (newparams ? jl_apply_tuple_type (newparams ) : ti );
2285
- int is_compileable = ((jl_datatype_t * )ti )-> isdispatchtuple ||
2286
- jl_isa_compileable_sig (tt , m );
2288
+ int is_compileable = ((jl_datatype_t * )ti )-> isdispatchtuple ;
2289
+ if (newparams ) {
2290
+ tt = jl_apply_tuple_type (newparams );
2291
+ if (!is_compileable ) {
2292
+ // compute new env, if used below
2293
+ jl_value_t * ti = jl_type_intersection_env ((jl_value_t * )tt , (jl_value_t * )m -> sig , & newparams );
2294
+ assert (ti != jl_bottom_type ); (void )ti ;
2295
+ env = newparams ;
2296
+ }
2297
+ }
2298
+ else {
2299
+ tt = ti ;
2300
+ }
2301
+ if (!is_compileable )
2302
+ is_compileable = jl_isa_compileable_sig (tt , env , m );
2287
2303
JL_GC_POP ();
2288
2304
return is_compileable ? (jl_value_t * )tt : jl_nothing ;
2289
2305
}
@@ -2301,7 +2317,7 @@ jl_method_instance_t *jl_normalize_to_compilable_mi(jl_method_instance_t *mi JL_
2301
2317
return mi ;
2302
2318
jl_svec_t * env = NULL ;
2303
2319
JL_GC_PUSH2 (& compilationsig , & env );
2304
- jl_value_t * ti = jl_type_intersection_env ((jl_value_t * )mi -> specTypes , (jl_value_t * )def -> sig , & env );
2320
+ jl_value_t * ti = jl_type_intersection_env ((jl_value_t * )compilationsig , (jl_value_t * )def -> sig , & env );
2305
2321
assert (ti != jl_bottom_type ); (void )ti ;
2306
2322
mi = jl_specializations_get_linfo (def , (jl_value_t * )compilationsig , env );
2307
2323
JL_GC_POP ();
@@ -2318,7 +2334,7 @@ jl_method_instance_t *jl_method_match_to_mi(jl_method_match_t *match, size_t wor
2318
2334
if (jl_is_datatype (ti )) {
2319
2335
jl_methtable_t * mt = jl_method_get_table (m );
2320
2336
if ((jl_value_t * )mt != jl_nothing ) {
2321
- // get the specialization without caching it
2337
+ // get the specialization, possibly also caching it
2322
2338
if (mt_cache && ((jl_datatype_t * )ti )-> isdispatchtuple ) {
2323
2339
// Since we also use this presence in the cache
2324
2340
// to trigger compilation when producing `.ji` files,
@@ -2330,11 +2346,15 @@ jl_method_instance_t *jl_method_match_to_mi(jl_method_match_t *match, size_t wor
2330
2346
}
2331
2347
else {
2332
2348
jl_value_t * tt = jl_normalize_to_compilable_sig (mt , ti , env , m );
2333
- JL_GC_PUSH1 (& tt );
2334
2349
if (tt != jl_nothing ) {
2350
+ JL_GC_PUSH2 (& tt , & env );
2351
+ if (!jl_egal (tt , (jl_value_t * )ti )) {
2352
+ jl_value_t * ti = jl_type_intersection_env ((jl_value_t * )tt , (jl_value_t * )m -> sig , & env );
2353
+ assert (ti != jl_bottom_type ); (void )ti ;
2354
+ }
2335
2355
mi = jl_specializations_get_linfo (m , (jl_value_t * )tt , env );
2356
+ JL_GC_POP ();
2336
2357
}
2337
- JL_GC_POP ();
2338
2358
}
2339
2359
}
2340
2360
}
@@ -2397,7 +2417,7 @@ jl_method_instance_t *jl_get_compile_hint_specialization(jl_tupletype_t *types J
2397
2417
size_t count = 0 ;
2398
2418
for (i = 0 ; i < n ; i ++ ) {
2399
2419
jl_method_match_t * match1 = (jl_method_match_t * )jl_array_ptr_ref (matches , i );
2400
- if (jl_isa_compileable_sig (types , match1 -> method ))
2420
+ if (jl_isa_compileable_sig (types , match1 -> sparams , match1 -> method ))
2401
2421
jl_array_ptr_set (matches , count ++ , (jl_value_t * )match1 );
2402
2422
}
2403
2423
jl_array_del_end ((jl_array_t * )matches , n - count );
0 commit comments