@@ -529,11 +529,81 @@ function show(io::IO, @nospecialize(x::Type))
529
529
end
530
530
end
531
531
532
+ # The `:unionall_tvs` io context records typevar naming data, i.e. whether
533
+ # the typevar needs a corresponding `where` being printed or not.
534
+ # It is being filled recursively here first before printing the typevar
535
+ # itself.
536
+ io = IOContext (io, :unionall_tvs => _unionall_tvs (io))
537
+ _unionall_name_tvs (io, x)
538
+
539
+ # The `:unionall_env => tv::TypeVar` io context is used to signify that
540
+ # io is happening within the unionall environment of `tv`.
532
541
show (IOContext (io, :unionall_env => x. var), x. body)
533
- print (io, " where " )
534
- show (io, x. var)
542
+
543
+ if isnamed (io, x. var)
544
+ print (io, " where " )
545
+ show (io, x. var)
546
+ end
535
547
end
536
548
549
+ """
550
+ isgensym(x::Symbol)
551
+
552
+ Return whether `x` is an generated symbol, as generated by e.g.
553
+ [`gensym`](@ref).
554
+ """
555
+ isgensym (x:: Symbol ) = first (String (x)) == ' #'
556
+
557
+ _unionall_tvs (io:: IO ) = get (io, :unionall_tvs , IdDict {TypeVar,Int} ())
558
+ isnamed (io:: IO , tv:: TypeVar ) = get (_unionall_tvs (io), tv, 0 ) > 1
559
+ setnamed (io:: IO , tv:: TypeVar ) = setindex! (_unionall_tvs (io), 2 , tv)
560
+
561
+ function _unionall_name_tvs (io:: IO , @nospecialize x:: UnionAll )
562
+ # collect typevar naming candidates
563
+ tvs = TypeVar[]
564
+ y = x
565
+ while y isa UnionAll
566
+ # if it is named then this method was called already on a parent
567
+ isnamed (io, y. var) && return io
568
+ push! (tvs, y. var)
569
+ y = y. body
570
+ end
571
+
572
+ if y isa DataType
573
+ # count typevar occurrences within the body recursively
574
+ isempty (_unionall_tvs (io)) && _count_tvs! (_unionall_tvs (io), y)
575
+
576
+ for tv in reverse (collect (y. parameters))
577
+ tv isa TypeVar || continue
578
+ # might have been named above or earlier in the printing hierarchy
579
+ isnamed (io, tv) && continue
580
+
581
+ if last (tvs) == tv && (tv. lb == Bottom || tv. ub == Any)
582
+ # safe for elision
583
+ pop! (tvs)
584
+ isempty (tvs) && return io
585
+ else
586
+ setnamed (io, tv)
587
+ end
588
+ end
589
+ end
590
+
591
+ # remaining ones need to be named, since anonymizing further nested
592
+ # occurences is disallowed, includes e.g. y::Union
593
+ foreach (tv -> isnamed (io, tv) || setnamed (io, tv), tvs)
594
+ end
595
+
596
+ @nospecialize
597
+ _count_tvs! (counts) = counts
598
+ _count_tvs! (counts, x) = counts
599
+ _count_tvs! (counts, x:: TypeVar ) =
600
+ (setindex! (counts, get (counts, x, 0 ) + 1 , x); _count_tvs! (counts, x. lb, x. ub))
601
+ _count_tvs! (counts, x:: UnionAll ) = _count_tvs! (counts, x. var. lb, x. var. ub, x. body)
602
+ _count_tvs! (counts, x:: Union ) = _count_tvs! (counts, x. a, x. b)
603
+ _count_tvs! (counts, x:: DataType ) = _count_tvs! (counts, x. parameters... )
604
+ _count_tvs! (counts, x1, x2, x... ) = (_count_tvs! (counts, x1); _count_tvs! (counts, x2, x... ))
605
+ @specialize
606
+
537
607
# Check whether 'sym' (defined in module 'parent') is visible from module 'from'
538
608
# If an object with this name exists in 'from', we need to check that it's the same binding
539
609
# and that it's not deprecated.
@@ -596,12 +666,29 @@ function show_datatype(io::IO, x::DataType)
596
666
print (io, " NTuple{" , n, ' ,' , x. parameters[1 ], " }" )
597
667
else
598
668
show_type_name (io, x. name)
599
- # Do not print the type parameters for the primary type if we are
600
- # printing a method signature or type parameter.
601
- # Always print the type parameter if we are printing the type directly
602
- # since this information is still useful.
669
+
670
+ if ! istuple
671
+ # find out up until which parameter we need to print typevars
672
+ y = x. name. wrapper
673
+ n, j = 0 , 0
674
+ while y isa UnionAll
675
+ j += 1
676
+ tv = x. parameters[j]
677
+ if ! isa (tv, TypeVar) || isnamed (io, tv) ||
678
+ in (:tv_standalone => tv, io) || ! in (:unionall_env => tv, io) ||
679
+ # can only elide when typevar constraints are
680
+ # the same as defined in the parametric type itself
681
+ isa (tv. lb, TypeVar) || isa (tv. ub, TypeVar) ||
682
+ ! (tv. lb == y. var. lb) || ! (tv. ub == y. var. ub)
683
+ n = j
684
+ end
685
+ y = y. body
686
+ end
687
+ n == 0 && return
688
+ end
689
+
603
690
print (io, ' {' )
604
- for (i, p) in enumerate (x. parameters)
691
+ for (i, p) in enumerate (x. parameters[ 1 : n] )
605
692
show (io, p)
606
693
i < n && print (io, ' ,' )
607
694
end
@@ -1780,7 +1867,7 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwa
1780
1867
env_io = io
1781
1868
while isa (sig, UnionAll)
1782
1869
push! (tv, sig. var)
1783
- env_io = IOContext (env_io, :unionall_env => sig. var)
1870
+ env_io = IOContext (env_io, :tv_standalone => sig. var)
1784
1871
sig = sig. body
1785
1872
end
1786
1873
sig = sig. parameters
@@ -1837,37 +1924,48 @@ function ismodulecall(ex::Expr)
1837
1924
end
1838
1925
1839
1926
function show (io:: IO , tv:: TypeVar )
1840
- # If we are in the `unionall_env`, the type-variable is bound
1841
- # and the type constraints are already printed.
1842
- # We don't need to print it again.
1843
- # Otherwise, the lower bound should be printed if it is not `Bottom`
1844
- # and the upper bound should be printed if it is not `Any`.
1845
- in_env = (:unionall_env => tv) in io
1846
1927
function show_bound (io:: IO , @nospecialize (b))
1847
1928
parens = isa (b,UnionAll) && ! print_without_params (b)
1848
1929
parens && print (io, " (" )
1849
1930
show (io, b)
1850
1931
parens && print (io, " )" )
1851
1932
end
1852
1933
lb, ub = tv. lb, tv. ub
1853
- if ! in_env && lb != = Bottom
1854
- if ub === Any
1855
- show_unquoted (io, tv. name)
1856
- print (io, " >:" )
1857
- show_bound (io, lb)
1858
- else
1934
+
1935
+ # the `:tv_standalone => tv::TypeVar` io context tells to print the typevar
1936
+ # `tv` without any typebounds, this is not necessarily related to being
1937
+ # within a unionall environment
1938
+ (:tv_standalone => tv) in io && return show_unquoted (io, tv. name)
1939
+
1940
+ if (:unionall_env => tv) in io
1941
+ # within unionall type argument for `tv`
1942
+ if isnamed (io, tv)
1943
+ # named typevars get their constraints printed after `where`
1944
+ return show_unquoted (io, tv. name)
1945
+ elseif lb == Bottom
1946
+ # anonymous upper bound, need to show `<:Any` even if trivial
1947
+ return print (io, " <:" , ub)
1948
+ elseif ub == Any
1949
+ # anonymous non-trivial lower bound
1950
+ return print (io, " >:" , lb)
1951
+ end
1952
+ @assert false
1953
+ elseif lb != Bottom && ub == Any
1954
+ show_unquoted (io, tv. name)
1955
+ print (io, " >:" )
1956
+ return show_bound (io, lb)
1957
+ else
1958
+ if lb != Bottom
1859
1959
show_bound (io, lb)
1860
1960
print (io, " <:" )
1861
- show_unquoted (io, tv. name)
1862
1961
end
1863
- else
1864
1962
show_unquoted (io, tv. name)
1963
+ if ub != Any
1964
+ print (io, " <:" )
1965
+ show_bound (io, ub)
1966
+ end
1865
1967
end
1866
- if ! in_env && ub != = Any
1867
- print (io, " <:" )
1868
- show_bound (io, ub)
1869
- end
1870
- nothing
1968
+ return nothing
1871
1969
end
1872
1970
1873
1971
module IRShow
@@ -2027,19 +2125,19 @@ end
2027
2125
2028
2126
# Types
2029
2127
function dump (io:: IOContext , x:: DataType , n:: Int , indent)
2030
- print (io, x)
2128
+ tvar_io = io
2129
+ for tparam in x. parameters
2130
+ # approximately recapture the list of tvar parameterization
2131
+ # that may be used by the internal fields
2132
+ if isa (tparam, TypeVar)
2133
+ tvar_io = IOContext (tvar_io, :tv_standalone => tparam)
2134
+ end
2135
+ end
2136
+ print (tvar_io, x)
2031
2137
if x != = Any
2032
- print (io , " <: " , supertype (x))
2138
+ print (tvar_io , " <: " , supertype (x))
2033
2139
end
2034
2140
if n > 0 && ! (x <: Tuple ) && ! x. abstract
2035
- tvar_io:: IOContext = io
2036
- for tparam in x. parameters
2037
- # approximately recapture the list of tvar parameterization
2038
- # that may be used by the internal fields
2039
- if isa (tparam, TypeVar)
2040
- tvar_io = IOContext (tvar_io, :unionall_env => tparam)
2041
- end
2042
- end
2043
2141
if x. name === NamedTuple_typename && ! (x. parameters[1 ] isa Tuple)
2044
2142
# named tuple type with unknown field names
2045
2143
return
0 commit comments