@@ -292,10 +292,17 @@ union_count_abstract(x::Union) = union_count_abstract(x.a) + union_count_abstrac
292
292
union_count_abstract (@nospecialize (x)) = ! isdispatchelem (x)
293
293
294
294
function issimpleenoughtype (@nospecialize t)
295
+ ut = unwrap_unionall (t)
296
+ ut isa DataType && ut. name. wrapper == t && return true
295
297
return unionlen (t) + union_count_abstract (t) <= MAX_TYPEUNION_LENGTH &&
296
298
unioncomplexity (t) <= MAX_TYPEUNION_COMPLEXITY
297
299
end
298
300
301
+ # We may want to apply a stricter limit than issimpleenoughtype to
302
+ # tupleelements individually, to try to keep the whole tuple under the limit,
303
+ # even after complicated recursion and other operations on it elsewhere
304
+ const issimpleenoughtupleelem = issimpleenoughtype
305
+
299
306
# A simplified type_more_complex query over the extended lattice
300
307
# (assumes typeb ⊑ typea)
301
308
@nospecializeinfer function issimplertype (𝕃:: AbstractLattice , @nospecialize (typea), @nospecialize (typeb))
679
686
return tmerge_types_slow (typea, typeb)
680
687
end
681
688
689
+ @nospecializeinfer @noinline function tname_intersect (aname:: Core.TypeName , bname:: Core.TypeName )
690
+ aname === bname && return aname
691
+ if ! isabstracttype (aname. wrapper) && ! isabstracttype (bname. wrapper)
692
+ return nothing # fast path
693
+ end
694
+ Any. name === aname && return aname
695
+ a = unwrap_unionall (aname. wrapper)
696
+ heighta = 0
697
+ while a != = Any
698
+ heighta += 1
699
+ a = a. super
700
+ end
701
+ b = unwrap_unionall (bname. wrapper)
702
+ heightb = 0
703
+ while b != = Any
704
+ b. name === aname && return aname
705
+ heightb += 1
706
+ b = b. super
707
+ end
708
+ a = unwrap_unionall (aname. wrapper)
709
+ while heighta > heightb
710
+ a = a. super
711
+ heighta -= 1
712
+ end
713
+ return a. name === bname ? bname : nothing
714
+ end
715
+
682
716
@nospecializeinfer @noinline function tmerge_types_slow (@nospecialize (typea:: Type ), @nospecialize (typeb:: Type ))
683
717
# collect the list of types from past tmerge calls returning Union
684
718
# and then reduce over that list
@@ -702,74 +736,95 @@ end
702
736
# see if any of the union elements have the same TypeName
703
737
# in which case, simplify this tmerge by replacing it with
704
738
# the widest possible version of itself (the wrapper)
739
+ simplify = falses (length (types))
705
740
for i in 1 : length (types)
741
+ typenames[i] === Any. name && continue
706
742
ti = types[i]
707
743
for j in (i + 1 ): length (types)
708
- if typenames[i] === typenames[j]
744
+ typenames[j] === Any. name && continue
745
+ ijname = tname_intersect (typenames[i], typenames[j])
746
+ if ! (ijname === nothing )
709
747
tj = types[j]
710
748
if ti <: tj
711
749
types[i] = Union{}
712
750
typenames[i] = Any. name
751
+ simplify[i] = false
752
+ simplify[j] = true
713
753
break
714
754
elseif tj <: ti
715
755
types[j] = Union{}
716
756
typenames[j] = Any. name
757
+ simplify[j] = false
758
+ simplify[i] = true
717
759
else
718
- if typenames[i] === Tuple. name
760
+ if ijname === Tuple. name
719
761
# try to widen Tuple slower: make a single non-concrete Tuple containing both
720
762
# converge the Tuple element-wise if they are the same length
721
763
# see 4ee2b41552a6bc95465c12ca66146d69b354317b, be59686f7613a2ccfd63491c7b354d0b16a95c05,
722
764
widen = tuplemerge (unwrap_unionall (ti):: DataType , unwrap_unionall (tj):: DataType )
723
765
widen = rewrap_unionall (rewrap_unionall (widen, ti), tj)
766
+ simplify[j] = false
724
767
else
725
- wr = typenames[i] . wrapper
768
+ wr = ijname . wrapper
726
769
uw = unwrap_unionall (wr):: DataType
727
770
ui = unwrap_unionall (ti):: DataType
771
+ while ui. name != = ijname
772
+ ui = ui. super
773
+ end
728
774
uj = unwrap_unionall (tj):: DataType
729
- merged = wr
775
+ while uj. name != = ijname
776
+ uj = uj. super
777
+ end
778
+ p = Vector {Any} (undef, length (uw. parameters))
779
+ usep = true
780
+ widen = wr
730
781
for k = 1 : length (uw. parameters)
731
782
ui_k = ui. parameters[k]
732
783
if ui_k === uj. parameters[k] && ! has_free_typevars (ui_k)
733
- merged = merged{ui_k}
784
+ p[k] = ui_k
785
+ usep = true
734
786
else
735
- merged = merged{ uw. parameters[k]}
787
+ p[k] = uw. parameters[k]
736
788
end
737
789
end
738
- widen = rewrap_unionall (merged, wr)
790
+ if usep
791
+ widen = rewrap_unionall (wr{p... }, wr)
792
+ end
793
+ simplify[j] = ! usep
739
794
end
740
795
types[i] = Union{}
741
796
typenames[i] = Any. name
797
+ simplify[i] = false
742
798
types[j] = widen
743
799
break
744
800
end
745
801
end
746
802
end
747
803
end
748
- u = Union{types... }
749
- # don't let type unions get too big, if the above didn't reduce it enough
750
- if issimpleenoughtype (u)
751
- return u
752
- end
753
- # don't let the slow widening of Tuple cause the whole type to grow too fast
804
+ # don't let elements of the union get too big, if the above didn't reduce something enough
754
805
# Specifically widen Tuple{..., Union{lots of stuff}...} to Tuple{..., Any, ...}
806
+ # Don't let Val{<:Val{<:Val}} keep nesting abstract levels either
755
807
for i in 1 : length (types)
808
+ simplify[i] || continue
809
+ ti = types[i]
810
+ issimpleenoughtype (ti) && continue
756
811
if typenames[i] === Tuple. name
757
- ti = types[i]
758
- tip = (unwrap_unionall (types[i] ):: DataType ). parameters
812
+ # otherwise we need to do a simple version of tuplemerge for one element now
813
+ tip = (unwrap_unionall (ti ):: DataType ). parameters
759
814
lt = length (tip)
760
815
p = Vector {Any} (undef, lt)
761
816
for j = 1 : lt
762
817
ui = tip[j]
763
- p[j] = ( unioncomplexity (ui)== 0 ) ? ui : isvarargtype (ui) ? Vararg : Any
818
+ p[j] = issimpleenoughtupleelem ( unwrapva (ui)) ? ui : isvarargtype (ui) ? Vararg : Any
764
819
end
765
820
types[i] = rewrap_unionall (Tuple{p... }, ti)
821
+ else
822
+ # this element is not simple enough yet, make it so now
823
+ types[i] = typenames[i]. wrapper
766
824
end
767
825
end
768
826
u = Union{types... }
769
- if issimpleenoughtype (u)
770
- return u
771
- end
772
- return Any
827
+ return u
773
828
end
774
829
775
830
# the inverse of switchtupleunion, with limits on max element union size
@@ -791,7 +846,7 @@ function tuplemerge(a::DataType, b::DataType)
791
846
p = Vector {Any} (undef, lt + vt)
792
847
for i = 1 : lt
793
848
ui = Union{ap[i], bp[i]}
794
- p[i] = issimpleenoughtype (ui) ? ui : Any
849
+ p[i] = issimpleenoughtupleelem (ui) ? ui : Any
795
850
end
796
851
# merge the remaining tail into a single, simple Tuple{Vararg{T}} (#22120)
797
852
if vt
@@ -809,8 +864,10 @@ function tuplemerge(a::DataType, b::DataType)
809
864
# or (equivalently?) iteratively took super-types until reaching a common wrapper
810
865
# e.g. consider the results of `tuplemerge(Tuple{Complex}, Tuple{Number, Int})` and of
811
866
# `tuplemerge(Tuple{Int}, Tuple{String}, Tuple{Int, String})`
812
- if ! (ti <: tail )
813
- if tail <: ti
867
+ # c.f. tname_intersect in the algorithm above
868
+ hasfree = has_free_typevars (ti)
869
+ if hasfree || ! (ti <: tail )
870
+ if ! hasfree && tail <: ti
814
871
tail = ti # widen to ti
815
872
else
816
873
uw = unwrap_unionall (tail)
@@ -838,11 +895,16 @@ function tuplemerge(a::DataType, b::DataType)
838
895
end
839
896
end
840
897
end
841
- tail === Any && return Tuple # short-circuit loop
898
+ tail === Any && return Tuple # short-circuit loops
842
899
end
843
900
end
844
901
@assert ! (tail === Union{})
845
- p[lt + 1 ] = Vararg{tail}
902
+ if ! issimpleenoughtupleelem (tail) || tail === Any
903
+ p[lt + 1 ] = Vararg
904
+ lt == 0 && return Tuple
905
+ else
906
+ p[lt + 1 ] = Vararg{tail}
907
+ end
846
908
end
847
909
return Tuple{p... }
848
910
end
0 commit comments