@@ -529,11 +529,70 @@ function show(io::IO, @nospecialize(x::Type))
529
529
end
530
530
end
531
531
532
+ io = IOContext (io, :unionall_tvs => tvars (io))
533
+
534
+ _unionall_name_tvs (io, x)
532
535
show (IOContext (io, :unionall_env => x. var), x. body)
533
- print (io, " where " )
534
- show (io, x. var)
536
+
537
+ if isnamed (io, x. var)
538
+ print (io, " where " )
539
+ show (io, x. var)
540
+ end
535
541
end
536
542
543
+
544
+ tvars (io:: IO ) = get (io, :unionall_tvs , IdDict {TypeVar,Int} ())
545
+
546
+ isgensym (x:: Symbol ) = first (String (x)) == ' #'
547
+ isnamed (io:: IO , tv) = get (tvars (io), tv, 0 ) > 1
548
+ setnamed (io:: IO , tv) = setindex! (tvars (io), 2 , tv)
549
+
550
+ function _unionall_name_tvs (io:: IO , @nospecialize x:: UnionAll )
551
+ # collect typevar naming candidates
552
+ tvs = TypeVar[]
553
+ y = x
554
+ while y isa UnionAll
555
+ # if it is named then this method was called already on a parent
556
+ isnamed (io, y. var) && return io
557
+ push! (tvs, y. var)
558
+ y = y. body
559
+ end
560
+
561
+ if y isa DataType
562
+ # count typevar occurrences within the body recursively
563
+ isempty (tvars (io)) && _count_tvs! (tvars (io), y)
564
+
565
+ for tv in reverse (collect (y. parameters))
566
+ tv isa TypeVar || continue
567
+ # might have been named above or earlier in the printing hierarchy
568
+ isnamed (io, tv) && continue
569
+
570
+ if last (tvs) == tv && (isgensym (tv. name) || (:compact => true ) in io) &&
571
+ (tv. lb == Bottom || tv. ub == Any)
572
+ # safe for elision
573
+ pop! (tvs)
574
+ isempty (tvs) && return io
575
+ else
576
+ setnamed (io, tv)
577
+ end
578
+ end
579
+ end
580
+
581
+ # remaining ones need to be named, since anonymizing further nested
582
+ # occurences is disallowed, includes e.g. y::Union
583
+ foreach (tv -> isnamed (io, tv) || setnamed (io, tv), tvs)
584
+ end
585
+
586
+ @nospecialize
587
+ _count_tvs! (counts) = counts
588
+ _count_tvs! (counts, x) = counts
589
+ _count_tvs! (counts, x:: TypeVar ) = setindex! (counts, get (counts, x, 0 ) + 1 , x)
590
+ _count_tvs! (counts, x:: UnionAll ) = _count_tvs! (counts, x. var. lb, x. var. ub, x. body)
591
+ _count_tvs! (counts, x:: Union ) = _count_tvs! (counts, x. a, x. b)
592
+ _count_tvs! (counts, x:: DataType ) = _count_tvs! (counts, x. parameters... )
593
+ _count_tvs! (counts, x1, x2, x... ) = (_count_tvs! (counts, x1); _count_tvs! (counts, x2, x... ))
594
+ @specialize
595
+
537
596
# Check whether 'sym' (defined in module 'parent') is visible from module 'from'
538
597
# If an object with this name exists in 'from', we need to check that it's the same binding
539
598
# and that it's not deprecated.
@@ -596,14 +655,19 @@ function show_datatype(io::IO, x::DataType)
596
655
print (io, " NTuple{" , n, ' ,' , x. parameters[1 ], " }" )
597
656
else
598
657
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.
658
+
659
+ # find the first type parameter that can not be elided when
660
+ # printing
661
+ j = istuple ? n : findlast (x. parameters) do tv
662
+ return ! isa (tv, TypeVar) || ! isgensym (tv. name) || isnamed (io, tv) ||
663
+ in (:tv_standalone => tv, io) || tv. lb != Bottom || tv. ub != Any
664
+ end
665
+ isnothing (j) && return
666
+
603
667
print (io, ' {' )
604
- for (i, p) in enumerate (x. parameters)
668
+ for (i, p) in enumerate (x. parameters[ 1 : j] )
605
669
show (io, p)
606
- i < n && print (io, ' ,' )
670
+ i < j && print (io, ' ,' )
607
671
end
608
672
print (io, ' }' )
609
673
end
@@ -1753,7 +1817,7 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type, demangle=false, kwa
1753
1817
env_io = io
1754
1818
while isa (sig, UnionAll)
1755
1819
push! (tv, sig. var)
1756
- env_io = IOContext (env_io, :unionall_env => sig. var)
1820
+ env_io = IOContext (env_io, :tv_standalone => sig. var)
1757
1821
sig = sig. body
1758
1822
end
1759
1823
sig = sig. parameters
@@ -1821,37 +1885,45 @@ function ismodulecall(ex::Expr)
1821
1885
end
1822
1886
1823
1887
function show (io:: IO , tv:: TypeVar )
1824
- # If we are in the `unionall_env`, the type-variable is bound
1825
- # and the type constraints are already printed.
1826
- # We don't need to print it again.
1827
- # Otherwise, the lower bound should be printed if it is not `Bottom`
1828
- # and the upper bound should be printed if it is not `Any`.
1829
- in_env = (:unionall_env => tv) in io
1830
1888
function show_bound (io:: IO , @nospecialize (b))
1831
1889
parens = isa (b,UnionAll) && ! print_without_params (b)
1832
1890
parens && print (io, " (" )
1833
1891
show (io, b)
1834
1892
parens && print (io, " )" )
1835
1893
end
1836
1894
lb, ub = tv. lb, tv. ub
1837
- if ! in_env && lb != = Bottom
1838
- if ub === Any
1839
- show_unquoted (io, tv. name)
1840
- print (io, " >:" )
1841
- show_bound (io, lb)
1842
- else
1895
+
1896
+ (:tv_standalone => tv) in io && return show_unquoted (io, tv. name)
1897
+
1898
+ if (:unionall_env => tv) in io
1899
+ # within unionall type argument for `tv`
1900
+ if isnamed (io, tv)
1901
+ # named typevars get their constraints printed after `where`
1902
+ return show_unquoted (io, tv. name)
1903
+ elseif lb == Bottom
1904
+ # anonymous upper bound, need to show `<:Any` even if trivial
1905
+ return print (io, " <:" , ub)
1906
+ elseif ub == Any
1907
+ # anonymous non-trivial lower bound
1908
+ return print (io, " >:" , lb)
1909
+ end
1910
+ @assert false
1911
+ elseif lb != Bottom && ub == Any
1912
+ show_unquoted (io, tv. name)
1913
+ print (io, " >:" )
1914
+ return show_bound (io, lb)
1915
+ else
1916
+ if lb != Bottom
1843
1917
show_bound (io, lb)
1844
1918
print (io, " <:" )
1845
- show_unquoted (io, tv. name)
1846
1919
end
1847
- else
1848
1920
show_unquoted (io, tv. name)
1921
+ if ub != Any
1922
+ print (io, " <:" )
1923
+ show_bound (io, ub)
1924
+ end
1849
1925
end
1850
- if ! in_env && ub != = Any
1851
- print (io, " <:" )
1852
- show_bound (io, ub)
1853
- end
1854
- nothing
1926
+ return nothing
1855
1927
end
1856
1928
1857
1929
module IRShow
@@ -2007,7 +2079,7 @@ function dump(io::IOContext, x::DataType, n::Int, indent)
2007
2079
# approximately recapture the list of tvar parameterization
2008
2080
# that may be used by the internal fields
2009
2081
if isa (tparam, TypeVar)
2010
- tvar_io = IOContext (tvar_io, :unionall_env => tparam)
2082
+ tvar_io = IOContext (tvar_io, :tv_standalone => tparam)
2011
2083
end
2012
2084
end
2013
2085
if x. name === NamedTuple_typename && ! (x. parameters[1 ] isa Tuple)
0 commit comments