@@ -3,7 +3,8 @@ use either::Either;
33use hir_def:: {
44 data:: adt:: { StructKind , VariantData } ,
55 generics:: {
6- TypeOrConstParamData , TypeParamProvenance , WherePredicate , WherePredicateTypeTarget ,
6+ GenericParams , TypeOrConstParamData , TypeParamProvenance , WherePredicate ,
7+ WherePredicateTypeTarget ,
78 } ,
89 lang_item:: LangItem ,
910 type_ref:: { TypeBound , TypeRef } ,
@@ -16,6 +17,8 @@ use hir_ty::{
1617 } ,
1718 AliasEq , AliasTy , Interner , ProjectionTyExt , TraitRefExt , TyKind , WhereClause ,
1819} ;
20+ use intern:: Interned ;
21+ use itertools:: Itertools ;
1922
2023use crate :: {
2124 Adt , AsAssocItem , AssocItem , AssocItemContainer , Const , ConstParam , Enum , ExternCrateDecl ,
@@ -30,9 +33,13 @@ impl HirDisplay for Function {
3033 let data = db. function_data ( self . id ) ;
3134 let container = self . as_assoc_item ( db) . map ( |it| it. container ( db) ) ;
3235 let mut module = self . module ( db) ;
33- if let Some ( AssocItemContainer :: Impl ( _) ) = container {
34- // Block-local impls are "hoisted" to the nearest (non-block) module.
35- module = module. nearest_non_block_module ( db) ;
36+
37+ match container {
38+ Some ( AssocItemContainer :: Impl ( _) ) => {
39+ // Block-local impls are "hoisted" to the nearest (non-block) module.
40+ module = module. nearest_non_block_module ( db) ;
41+ }
42+ _ => { }
3643 }
3744 let module_id = module. id ;
3845 write_visibility ( module_id, self . visibility ( db) , f) ?;
@@ -555,101 +562,96 @@ fn write_where_clause(
555562) -> Result < bool , HirDisplayError > {
556563 let params = f. db . generic_params ( def) ;
557564
558- // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
559- let is_unnamed_type_target = |target : & WherePredicateTypeTarget | match target {
560- WherePredicateTypeTarget :: TypeRef ( _) => false ,
561- WherePredicateTypeTarget :: TypeOrConstParam ( id) => {
562- params. type_or_consts [ * id] . name ( ) . is_none ( )
563- }
565+ let no_displayable_pred = |params : & Interned < GenericParams > | {
566+ params. where_predicates . iter ( ) . all ( |pred| {
567+ matches ! (
568+ pred,
569+ WherePredicate :: TypeBound { target: WherePredicateTypeTarget :: TypeOrConstParam ( id) , .. }
570+ if params. type_or_consts[ * id] . name( ) . is_none( )
571+ )
572+ } )
564573 } ;
565574
566- let has_displayable_predicate = params
567- . where_predicates
568- . iter ( )
569- . any ( |pred| {
570- !matches ! ( pred, WherePredicate :: TypeBound { target, .. } if is_unnamed_type_target( target) )
571- } ) ;
572-
573- if !has_displayable_predicate {
575+ if no_displayable_pred ( & params) {
574576 return Ok ( false ) ;
575577 }
576578
579+ f. write_str ( "\n where" ) ?;
580+ write_where_predicates ( & params, f) ?;
581+
582+ Ok ( true )
583+ }
584+
585+ fn write_where_predicates (
586+ params : & Interned < GenericParams > ,
587+ f : & mut HirFormatter < ' _ > ,
588+ ) -> Result < ( ) , HirDisplayError > {
589+ use WherePredicate :: * ;
590+
591+ // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
592+ let is_unnamed_type_target =
593+ |params : & Interned < GenericParams > , target : & WherePredicateTypeTarget | {
594+ matches ! ( target,
595+ WherePredicateTypeTarget :: TypeOrConstParam ( id) if params. type_or_consts[ * id] . name( ) . is_none( )
596+ )
597+ } ;
598+
577599 let write_target = |target : & WherePredicateTypeTarget , f : & mut HirFormatter < ' _ > | match target {
578600 WherePredicateTypeTarget :: TypeRef ( ty) => ty. hir_fmt ( f) ,
579- WherePredicateTypeTarget :: TypeOrConstParam ( id) => {
580- match & params. type_or_consts [ * id] . name ( ) {
581- Some ( name) => write ! ( f, "{}" , name. display( f. db. upcast( ) ) ) ,
582- None => f. write_str ( "{unnamed}" ) ,
583- }
584- }
601+ WherePredicateTypeTarget :: TypeOrConstParam ( id) => match params. type_or_consts [ * id] . name ( ) {
602+ Some ( name) => write ! ( f, "{}" , name. display( f. db. upcast( ) ) ) ,
603+ None => f. write_str ( "{unnamed}" ) ,
604+ } ,
585605 } ;
586606
587- f. write_str ( "\n where" ) ?;
588-
589- for ( pred_idx, pred) in params. where_predicates . iter ( ) . enumerate ( ) {
590- let prev_pred =
591- if pred_idx == 0 { None } else { Some ( & params. where_predicates [ pred_idx - 1 ] ) } ;
607+ let check_same_target = |pred1 : & WherePredicate , pred2 : & WherePredicate | match ( pred1, pred2) {
608+ ( TypeBound { target : t1, .. } , TypeBound { target : t2, .. } ) => t1 == t2,
609+ ( Lifetime { target : t1, .. } , Lifetime { target : t2, .. } ) => t1 == t2,
610+ (
611+ ForLifetime { lifetimes : l1, target : t1, .. } ,
612+ ForLifetime { lifetimes : l2, target : t2, .. } ,
613+ ) => l1 == l2 && t1 == t2,
614+ _ => false ,
615+ } ;
592616
593- let new_predicate = |f : & mut HirFormatter < ' _ > | {
594- f. write_str ( if pred_idx == 0 { "\n " } else { ",\n " } )
595- } ;
617+ let mut iter = params. where_predicates . iter ( ) . peekable ( ) ;
618+ while let Some ( pred) = iter. next ( ) {
619+ if matches ! ( pred, TypeBound { target, .. } if is_unnamed_type_target( params, target) ) {
620+ continue ;
621+ }
596622
623+ f. write_str ( "\n " ) ?;
597624 match pred {
598- WherePredicate :: TypeBound { target, .. } if is_unnamed_type_target ( target) => { }
599- WherePredicate :: TypeBound { target, bound } => {
600- if matches ! ( prev_pred, Some ( WherePredicate :: TypeBound { target: target_, .. } ) if target_ == target)
601- {
602- f. write_str ( " + " ) ?;
603- } else {
604- new_predicate ( f) ?;
605- write_target ( target, f) ?;
606- f. write_str ( ": " ) ?;
607- }
625+ TypeBound { target, bound } => {
626+ write_target ( target, f) ?;
627+ f. write_str ( ": " ) ?;
608628 bound. hir_fmt ( f) ?;
609629 }
610- WherePredicate :: Lifetime { target, bound } => {
611- if matches ! ( prev_pred, Some ( WherePredicate :: Lifetime { target: target_, .. } ) if target_ == target)
612- {
613- write ! ( f, " + {}" , bound. name. display( f. db. upcast( ) ) ) ?;
614- } else {
615- new_predicate ( f) ?;
616- write ! (
617- f,
618- "{}: {}" ,
619- target. name. display( f. db. upcast( ) ) ,
620- bound. name. display( f. db. upcast( ) )
621- ) ?;
622- }
630+ Lifetime { target, bound } => {
631+ let target = target. name . display ( f. db . upcast ( ) ) ;
632+ let bound = bound. name . display ( f. db . upcast ( ) ) ;
633+ write ! ( f, "{target}: {bound}" ) ?;
623634 }
624- WherePredicate :: ForLifetime { lifetimes, target, bound } => {
625- if matches ! (
626- prev_pred,
627- Some ( WherePredicate :: ForLifetime { lifetimes: lifetimes_, target: target_, .. } )
628- if lifetimes_ == lifetimes && target_ == target,
629- ) {
630- f. write_str ( " + " ) ?;
631- } else {
632- new_predicate ( f) ?;
633- f. write_str ( "for<" ) ?;
634- for ( idx, lifetime) in lifetimes. iter ( ) . enumerate ( ) {
635- if idx != 0 {
636- f. write_str ( ", " ) ?;
637- }
638- write ! ( f, "{}" , lifetime. display( f. db. upcast( ) ) ) ?;
639- }
640- f. write_str ( "> " ) ?;
641- write_target ( target, f) ?;
642- f. write_str ( ": " ) ?;
643- }
635+ ForLifetime { lifetimes, target, bound } => {
636+ let lifetimes = lifetimes. iter ( ) . map ( |it| it. display ( f. db . upcast ( ) ) ) . join ( ", " ) ;
637+ write ! ( f, "for<{lifetimes}> " ) ?;
638+ write_target ( target, f) ?;
639+ f. write_str ( ": " ) ?;
644640 bound. hir_fmt ( f) ?;
645641 }
646642 }
647- }
648643
649- // End of final predicate. There must be at least one predicate here.
650- f. write_char ( ',' ) ?;
644+ while let Some ( nxt) = iter. next_if ( |nxt| check_same_target ( pred, nxt) ) {
645+ f. write_str ( " + " ) ?;
646+ match nxt {
647+ TypeBound { bound, .. } | ForLifetime { bound, .. } => bound. hir_fmt ( f) ?,
648+ Lifetime { bound, .. } => write ! ( f, "{}" , bound. name. display( f. db. upcast( ) ) ) ?,
649+ }
650+ }
651+ f. write_str ( "," ) ?;
652+ }
651653
652- Ok ( true )
654+ Ok ( ( ) )
653655}
654656
655657impl HirDisplay for Const {
@@ -689,17 +691,8 @@ impl HirDisplay for Static {
689691
690692impl HirDisplay for Trait {
691693 fn hir_fmt ( & self , f : & mut HirFormatter < ' _ > ) -> Result < ( ) , HirDisplayError > {
692- write_visibility ( self . module ( f. db ) . id , self . visibility ( f. db ) , f) ?;
693- let data = f. db . trait_data ( self . id ) ;
694- if data. is_unsafe {
695- f. write_str ( "unsafe " ) ?;
696- }
697- if data. is_auto {
698- f. write_str ( "auto " ) ?;
699- }
700- write ! ( f, "trait {}" , data. name. display( f. db. upcast( ) ) ) ?;
694+ write_trait_header ( self , f) ?;
701695 let def_id = GenericDefId :: TraitId ( self . id ) ;
702- write_generic_params ( def_id, f) ?;
703696 let has_where_clause = write_where_clause ( def_id, f) ?;
704697
705698 if let Some ( limit) = f. entity_limit {
@@ -735,6 +728,20 @@ impl HirDisplay for Trait {
735728 }
736729}
737730
731+ fn write_trait_header ( trait_ : & Trait , f : & mut HirFormatter < ' _ > ) -> Result < ( ) , HirDisplayError > {
732+ write_visibility ( trait_. module ( f. db ) . id , trait_. visibility ( f. db ) , f) ?;
733+ let data = f. db . trait_data ( trait_. id ) ;
734+ if data. is_unsafe {
735+ f. write_str ( "unsafe " ) ?;
736+ }
737+ if data. is_auto {
738+ f. write_str ( "auto " ) ?;
739+ }
740+ write ! ( f, "trait {}" , data. name. display( f. db. upcast( ) ) ) ?;
741+ write_generic_params ( GenericDefId :: TraitId ( trait_. id ) , f) ?;
742+ Ok ( ( ) )
743+ }
744+
738745impl HirDisplay for TraitAlias {
739746 fn hir_fmt ( & self , f : & mut HirFormatter < ' _ > ) -> Result < ( ) , HirDisplayError > {
740747 write_visibility ( self . module ( f. db ) . id , self . visibility ( f. db ) , f) ?;
0 commit comments