@@ -68,11 +68,35 @@ impl<'db> NamedItem<'db> {
6868 }
6969}
7070
71+ #[ derive( Debug , Clone , Copy , Default , PartialEq , Eq ) ]
72+ enum SignatureNameDisplay {
73+ #[ default]
74+ Auto ,
75+ Force ,
76+ Disallow ,
77+ }
78+
79+ impl SignatureNameDisplay {
80+ const fn should_display ( self , multiline : bool ) -> bool {
81+ match self {
82+ Self :: Auto => multiline,
83+ Self :: Force => true ,
84+ Self :: Disallow => false ,
85+ }
86+ }
87+
88+ const fn allows_type_parameters ( self ) -> bool {
89+ !matches ! ( self , Self :: Disallow )
90+ }
91+ }
92+
7193/// Settings for displaying types and signatures
7294#[ derive( Debug , Clone , Default ) ]
7395pub struct DisplaySettings < ' db > {
7496 /// Whether rendering can be multiline
7597 pub multiline : bool ,
98+ /// Whether callable signatures should include their definition name.
99+ signature_name_display : SignatureNameDisplay ,
76100 /// Class names that should be displayed fully qualified
77101 /// (e.g., `module.ClassName` instead of just `ClassName`)
78102 pub qualified : Rc < FxHashMap < & ' db str , QualificationLevel > > ,
@@ -81,9 +105,6 @@ pub struct DisplaySettings<'db> {
81105 pub qualified_type_aliases : Rc < FxHashMap < & ' db str , QualificationLevel > > ,
82106 /// Whether long unions and literals are displayed in full
83107 pub preserve_full_unions : bool ,
84- /// Disallow Signature printing to introduce a name
85- /// (presumably because we rendered one already)
86- pub disallow_signature_name : bool ,
87108 /// Scopes that are currently active in the display context (e.g. function scopes
88109 /// whose type parameters are currently being displayed).
89110 /// Used to suppress redundant `@{scope}` suffixes for type variables.
@@ -129,7 +150,15 @@ impl<'db> DisplaySettings<'db> {
129150 #[ must_use]
130151 pub fn disallow_signature_name ( & self ) -> Self {
131152 Self {
132- disallow_signature_name : true ,
153+ signature_name_display : SignatureNameDisplay :: Disallow ,
154+ ..self . clone ( )
155+ }
156+ }
157+
158+ #[ must_use]
159+ pub fn force_signature_name ( & self ) -> Self {
160+ Self {
161+ signature_name_display : SignatureNameDisplay :: Force ,
133162 ..self . clone ( )
134163 }
135164 }
@@ -1996,10 +2025,12 @@ impl<'db> FmtDetailed<'db> for DisplaySignature<'_, 'db> {
19962025 f. write_str ( "Top[" ) ?;
19972026 }
19982027
1999- // If we're multiline printing and a name hasn't been emitted, try to
2028+ // If the current display policy wants a signature name and a name hasn't been emitted,
20002029 // remember what the name was by checking if we have a definition
2001- if self . settings . multiline
2002- && !self . settings . disallow_signature_name
2030+ if self
2031+ . settings
2032+ . signature_name_display
2033+ . should_display ( self . settings . multiline )
20032034 && let Some ( definition) = self . definition
20042035 && let Some ( name) = definition. name ( self . db )
20052036 {
@@ -2020,8 +2051,12 @@ impl<'db> FmtDetailed<'db> for DisplaySignature<'_, 'db> {
20202051 } ;
20212052
20222053 // Display type parameters if present, but only when the caller hasn't
2023- // already displayed them (indicated by disallow_signature_name being false)
2024- if !self . settings . disallow_signature_name {
2054+ // already displayed them.
2055+ if self
2056+ . settings
2057+ . signature_name_display
2058+ . allows_type_parameters ( )
2059+ {
20252060 let hide_unused_self = self . should_hide_self_from_display ( self . db ) ;
20262061
20272062 DisplayOptionalGenericContext {
@@ -2372,9 +2407,39 @@ impl<'db> FmtDetailed<'db> for DisplayUnionType<'_, 'db> {
23722407 )
23732408 }
23742409
2410+ fn singleline_union_element_label < ' db > (
2411+ db : & ' db dyn Db ,
2412+ element : Type < ' db > ,
2413+ settings : & DisplaySettings < ' db > ,
2414+ ) -> String {
2415+ element. display_with ( db, settings. singleline ( ) ) . to_string ( )
2416+ }
2417+
2418+ fn duplicate_ambiguous_labels ( element_labels : & [ Option < String > ] ) -> FxHashSet < & str > {
2419+ let mut counts: FxHashMap < & str , usize > = FxHashMap :: default ( ) ;
2420+
2421+ for label in element_labels. iter ( ) . flatten ( ) {
2422+ * counts. entry ( & * * label) . or_default ( ) += 1 ;
2423+ }
2424+
2425+ counts
2426+ . into_iter ( )
2427+ . filter_map ( |( label, count) | ( count > 1 ) . then_some ( label) )
2428+ . collect ( )
2429+ }
2430+
23752431 let elements = self . ty . elements ( self . db ) ;
23762432 let mut condensed_types = vec ! [ ] ;
23772433 let mut subclass_of_types = vec ! [ ] ;
2434+ let element_labels: Vec < _ > = elements
2435+ . iter ( )
2436+ . copied ( )
2437+ . map ( |element| {
2438+ ( !is_condensable ( element) && !element. is_subclass_of ( ) )
2439+ . then ( || singleline_union_element_label ( self . db , element, & self . settings ) )
2440+ } )
2441+ . collect ( ) ;
2442+ let duplicate_ambiguous_labels = duplicate_ambiguous_labels ( & element_labels) ;
23782443
23792444 for element in elements. iter ( ) . copied ( ) {
23802445 if is_condensable ( element) {
@@ -2400,7 +2465,7 @@ impl<'db> FmtDetailed<'db> for DisplayUnionType<'_, 'db> {
24002465 let mut subclass_of_types = Some ( subclass_of_types) ;
24012466 let mut displayed_entries = 0usize ;
24022467
2403- for element in elements {
2468+ for ( element, label ) in elements. iter ( ) . zip ( & element_labels ) {
24042469 if displayed_entries >= display_limit {
24052470 break ;
24062471 }
@@ -2425,10 +2490,18 @@ impl<'db> FmtDetailed<'db> for DisplayUnionType<'_, 'db> {
24252490 }
24262491 } else {
24272492 displayed_entries += 1 ;
2493+ let settings = if label
2494+ . as_deref ( )
2495+ . is_some_and ( |label| duplicate_ambiguous_labels. contains ( label) )
2496+ {
2497+ self . settings . singleline ( ) . force_signature_name ( )
2498+ } else {
2499+ self . settings . singleline ( )
2500+ } ;
24282501 join. entry ( & DisplayMaybeParenthesizedType {
24292502 ty : * element,
24302503 db : self . db ,
2431- settings : self . settings . singleline ( ) ,
2504+ settings,
24322505 } ) ;
24332506 }
24342507 }
0 commit comments