@@ -28,7 +28,7 @@ use intern::{Internable, Interned};
2828use itertools:: Itertools ;
2929use la_arena:: ArenaMap ;
3030use smallvec:: SmallVec ;
31- use stdx:: never;
31+ use stdx:: { never, IsNoneOr } ;
3232use triomphe:: Arc ;
3333
3434use crate :: {
@@ -41,9 +41,9 @@ use crate::{
4141 mir:: pad16,
4242 primitive, to_assoc_type_id,
4343 utils:: { self , detect_variant_from_bytes, generics, ClosureSubst } ,
44- AdtId , AliasEq , AliasTy , Binders , CallableDefId , CallableSig , Const , ConstScalar , ConstValue ,
45- DomainGoal , FnAbi , GenericArg , GenericArgData , ImplTraitId , Interner , Lifetime , LifetimeData ,
46- LifetimeOutlives , MemoryMap , Mutability , OpaqueTy , ProjectionTy , ProjectionTyExt ,
44+ AdtId , AliasEq , AliasTy , Binders , CallableDefId , CallableSig , ConcreteConst , Const ,
45+ ConstScalar , ConstValue , DomainGoal , FnAbi , GenericArg , ImplTraitId , Interner , Lifetime ,
46+ LifetimeData , LifetimeOutlives , MemoryMap , Mutability , OpaqueTy , ProjectionTy , ProjectionTyExt ,
4747 QuantifiedWhereClause , Scalar , Substitution , TraitEnvironment , TraitRef , TraitRefExt , Ty ,
4848 TyExt , WhereClause ,
4949} ;
@@ -60,11 +60,18 @@ impl HirWrite for String {}
6060impl HirWrite for fmt:: Formatter < ' _ > { }
6161
6262pub struct HirFormatter < ' a > {
63+ /// The database handle
6364 pub db : & ' a dyn HirDatabase ,
65+ /// The sink to write into
6466 fmt : & ' a mut dyn HirWrite ,
67+ /// A buffer to intercept writes with, this allows us to track the overall size of the formatted output.
6568 buf : String ,
69+ /// The current size of the formatted output.
6670 curr_size : usize ,
67- pub ( crate ) max_size : Option < usize > ,
71+ /// Size from which we should truncate the output.
72+ max_size : Option < usize > ,
73+ /// When rendering something that has a concept of "children" (like fields in a struct), this limits
74+ /// how many should be rendered.
6875 pub entity_limit : Option < usize > ,
6976 omit_verbose_types : bool ,
7077 closure_style : ClosureStyle ,
@@ -304,7 +311,6 @@ impl DisplayTarget {
304311#[ derive( Debug ) ]
305312pub enum DisplaySourceCodeError {
306313 PathNotFound ,
307- UnknownType ,
308314 Coroutine ,
309315 OpaqueType ,
310316}
@@ -418,6 +424,7 @@ impl HirDisplay for ProjectionTy {
418424 let proj_params = & self . substitution . as_slice ( Interner ) [ ..proj_params_count] ;
419425 if !proj_params. is_empty ( ) {
420426 write ! ( f, "<" ) ?;
427+ // FIXME use `hir_fmt_generics` here
421428 f. write_joined ( proj_params, ", " ) ?;
422429 write ! ( f, ">" ) ?;
423430 }
@@ -967,6 +974,7 @@ impl HirDisplay for Ty {
967974 . chain ( fn_params)
968975 . flatten ( ) ;
969976 write ! ( f, "<" ) ?;
977+ // FIXME use `hir_fmt_generics` here
970978 f. write_joined ( params, ", " ) ?;
971979 write ! ( f, ">" ) ?;
972980 }
@@ -1037,6 +1045,7 @@ impl HirDisplay for Ty {
10371045 // FIXME: reconsider the generic args order upon formatting?
10381046 if parameters. len ( Interner ) > 0 {
10391047 write ! ( f, "<" ) ?;
1048+ // FIXME use `hir_fmt_generics` here
10401049 f. write_joined ( parameters. as_slice ( Interner ) , ", " ) ?;
10411050 write ! ( f, ">" ) ?;
10421051 }
@@ -1287,11 +1296,10 @@ impl HirDisplay for Ty {
12871296 }
12881297 TyKind :: Error => {
12891298 if f. display_target . is_source_code ( ) {
1290- return Err ( HirDisplayError :: DisplaySourceCodeError (
1291- DisplaySourceCodeError :: UnknownType ,
1292- ) ) ;
1299+ f . write_char ( '_' ) ? ;
1300+ } else {
1301+ write ! ( f , "{{unknown}}" ) ? ;
12931302 }
1294- write ! ( f, "{{unknown}}" ) ?;
12951303 }
12961304 TyKind :: InferenceVar ( ..) => write ! ( f, "_" ) ?,
12971305 TyKind :: Coroutine ( _, subst) => {
@@ -1331,98 +1339,90 @@ fn hir_fmt_generics(
13311339 parameters : & Substitution ,
13321340 generic_def : Option < hir_def:: GenericDefId > ,
13331341) -> Result < ( ) , HirDisplayError > {
1334- let db = f. db ;
1335- if parameters. len ( Interner ) > 0 {
1336- use std:: cmp:: Ordering ;
1337- let param_compare =
1338- |a : & GenericArg , b : & GenericArg | match ( a. data ( Interner ) , b. data ( Interner ) ) {
1339- ( crate :: GenericArgData :: Lifetime ( _) , crate :: GenericArgData :: Lifetime ( _) ) => {
1340- Ordering :: Equal
1341- }
1342- ( crate :: GenericArgData :: Lifetime ( _) , _) => Ordering :: Less ,
1343- ( _, crate :: GenericArgData :: Lifetime ( _) ) => Ordering :: Less ,
1344- ( _, _) => Ordering :: Equal ,
1345- } ;
1346- let parameters_to_write = if f. display_target . is_source_code ( ) || f. omit_verbose_types ( ) {
1347- match generic_def
1348- . map ( |generic_def_id| db. generic_defaults ( generic_def_id) )
1349- . filter ( |defaults| !defaults. is_empty ( ) )
1350- {
1351- None => parameters. as_slice ( Interner ) ,
1352- Some ( default_parameters) => {
1353- fn should_show (
1354- parameter : & GenericArg ,
1355- default_parameters : & [ Binders < GenericArg > ] ,
1356- i : usize ,
1357- parameters : & Substitution ,
1358- ) -> bool {
1359- if parameter. ty ( Interner ) . map ( |it| it. kind ( Interner ) )
1360- == Some ( & TyKind :: Error )
1361- {
1362- return true ;
1363- }
1364- if let Some ( ConstValue :: Concrete ( c) ) =
1365- parameter. constant ( Interner ) . map ( |it| & it. data ( Interner ) . value )
1366- {
1367- if c. interned == ConstScalar :: Unknown {
1368- return true ;
1369- }
1370- }
1371- if let Some ( crate :: LifetimeData :: Static | crate :: LifetimeData :: Error ) =
1372- parameter. lifetime ( Interner ) . map ( |it| it. data ( Interner ) )
1373- {
1374- return true ;
1342+ if parameters. is_empty ( Interner ) {
1343+ return Ok ( ( ) ) ;
1344+ }
1345+
1346+ let parameters_to_write =
1347+ generic_args_sans_defaults ( f, generic_def, parameters. as_slice ( Interner ) ) ;
1348+ if !parameters_to_write. is_empty ( ) {
1349+ write ! ( f, "<" ) ?;
1350+ hir_fmt_generic_arguments ( f, parameters_to_write) ?;
1351+ write ! ( f, ">" ) ?;
1352+ }
1353+
1354+ Ok ( ( ) )
1355+ }
1356+
1357+ fn generic_args_sans_defaults < ' ga > (
1358+ f : & mut HirFormatter < ' _ > ,
1359+ generic_def : Option < hir_def:: GenericDefId > ,
1360+ parameters : & ' ga [ GenericArg ] ,
1361+ ) -> & ' ga [ GenericArg ] {
1362+ if f. display_target . is_source_code ( ) || f. omit_verbose_types ( ) {
1363+ match generic_def
1364+ . map ( |generic_def_id| f. db . generic_defaults ( generic_def_id) )
1365+ . filter ( |it| !it. is_empty ( ) )
1366+ {
1367+ None => parameters,
1368+ Some ( default_parameters) => {
1369+ let should_show = |arg : & GenericArg , i : usize | {
1370+ let is_err = |arg : & GenericArg | match arg. data ( Interner ) {
1371+ chalk_ir:: GenericArgData :: Lifetime ( it) => {
1372+ * it. data ( Interner ) == LifetimeData :: Error
13751373 }
1376- let default_parameter = match default_parameters. get ( i) {
1377- Some ( it) => it,
1378- None => return true ,
1379- } ;
1380- let actual_default =
1381- default_parameter. clone ( ) . substitute ( Interner , & parameters) ;
1382- parameter != & actual_default
1374+ chalk_ir:: GenericArgData :: Ty ( it) => * it. kind ( Interner ) == TyKind :: Error ,
1375+ chalk_ir:: GenericArgData :: Const ( it) => matches ! (
1376+ it. data( Interner ) . value,
1377+ ConstValue :: Concrete ( ConcreteConst {
1378+ interned: ConstScalar :: Unknown ,
1379+ ..
1380+ } )
1381+ ) ,
1382+ } ;
1383+ // if the arg is error like, render it to inform the user
1384+ if is_err ( arg) {
1385+ return true ;
13831386 }
1384- let mut default_from = 0 ;
1385- for ( i, parameter) in parameters. iter ( Interner ) . enumerate ( ) {
1386- if should_show ( parameter, & default_parameters, i, parameters) {
1387- default_from = i + 1 ;
1388- }
1387+ // otherwise, if the arg is equal to the param default, hide it (unless the
1388+ // default is an error which can happen for the trait Self type)
1389+ default_parameters. get ( i) . is_none_or ( |default_parameter| {
1390+ // !is_err(default_parameter.skip_binders())
1391+ // &&
1392+ arg != & default_parameter. clone ( ) . substitute ( Interner , & parameters)
1393+ } )
1394+ } ;
1395+ let mut default_from = 0 ;
1396+ for ( i, parameter) in parameters. iter ( ) . enumerate ( ) {
1397+ if should_show ( parameter, i) {
1398+ default_from = i + 1 ;
13891399 }
1390- & parameters. as_slice ( Interner ) [ 0 ..default_from]
1391- }
1392- }
1393- } else {
1394- parameters. as_slice ( Interner )
1395- } ;
1396- //FIXME: Should handle the ordering of lifetimes when creating substitutions
1397- let mut parameters_to_write = parameters_to_write. to_vec ( ) ;
1398- parameters_to_write. sort_by ( param_compare) ;
1399- if !parameters_to_write. is_empty ( ) {
1400- write ! ( f, "<" ) ?;
1401- let mut first = true ;
1402- for generic_arg in parameters_to_write {
1403- if !first {
1404- write ! ( f, ", " ) ?;
1405- }
1406- first = false ;
1407- if f. display_target . is_source_code ( ) {
1408- match generic_arg. data ( Interner ) {
1409- GenericArgData :: Lifetime ( l)
1410- if matches ! ( l. data( Interner ) , LifetimeData :: Error ) =>
1411- {
1412- write ! ( f, "'_" )
1413- }
1414- GenericArgData :: Ty ( t) if matches ! ( t. kind( Interner ) , TyKind :: Error ) => {
1415- write ! ( f, "_" )
1416- }
1417- _ => generic_arg. hir_fmt ( f) ,
1418- } ?
1419- } else {
1420- generic_arg. hir_fmt ( f) ?;
14211400 }
1401+ & parameters[ 0 ..default_from]
14221402 }
1403+ }
1404+ } else {
1405+ parameters
1406+ }
1407+ }
14231408
1424- write ! ( f, ">" ) ?;
1409+ fn hir_fmt_generic_arguments (
1410+ f : & mut HirFormatter < ' _ > ,
1411+ parameters : & [ GenericArg ] ,
1412+ ) -> Result < ( ) , HirDisplayError > {
1413+ let mut first = true ;
1414+ let lifetime_offset = parameters. iter ( ) . position ( |arg| arg. lifetime ( Interner ) . is_some ( ) ) ;
1415+
1416+ let ( ty_or_const, lifetimes) = match lifetime_offset {
1417+ Some ( offset) => parameters. split_at ( offset) ,
1418+ None => ( parameters, & [ ] [ ..] ) ,
1419+ } ;
1420+ for generic_arg in lifetimes. iter ( ) . chain ( ty_or_const) {
1421+ if !first {
1422+ write ! ( f, ", " ) ?;
14251423 }
1424+ first = false ;
1425+ generic_arg. hir_fmt ( f) ?;
14261426 }
14271427 Ok ( ( ) )
14281428}
@@ -1544,20 +1544,29 @@ fn write_bounds_like_dyn_trait(
15441544 f. start_location_link ( trait_. into ( ) ) ;
15451545 write ! ( f, "{}" , f. db. trait_data( trait_) . name. display( f. db. upcast( ) ) ) ?;
15461546 f. end_location_link ( ) ;
1547- if let [ _ , params @ .. ] = trait_ref . substitution . as_slice ( Interner ) {
1548- if is_fn_trait {
1547+ if is_fn_trait {
1548+ if let [ _self , params @ .. ] = trait_ref . substitution . as_slice ( Interner ) {
15491549 if let Some ( args) =
15501550 params. first ( ) . and_then ( |it| it. assert_ty_ref ( Interner ) . as_tuple ( ) )
15511551 {
15521552 write ! ( f, "(" ) ?;
1553- f . write_joined ( args. as_slice ( Interner ) , ", " ) ?;
1553+ hir_fmt_generic_arguments ( f , args. as_slice ( Interner ) ) ?;
15541554 write ! ( f, ")" ) ?;
15551555 }
1556- } else if !params. is_empty ( ) {
1557- write ! ( f, "<" ) ?;
1558- f. write_joined ( params, ", " ) ?;
1559- // there might be assoc type bindings, so we leave the angle brackets open
1560- angle_open = true ;
1556+ }
1557+ } else {
1558+ let params = generic_args_sans_defaults (
1559+ f,
1560+ Some ( trait_. into ( ) ) ,
1561+ trait_ref. substitution . as_slice ( Interner ) ,
1562+ ) ;
1563+ if let [ _self, params @ ..] = params {
1564+ if !params. is_empty ( ) {
1565+ write ! ( f, "<" ) ?;
1566+ hir_fmt_generic_arguments ( f, params) ?;
1567+ // there might be assoc type bindings, so we leave the angle brackets open
1568+ angle_open = true ;
1569+ }
15611570 }
15621571 }
15631572 }
@@ -1609,9 +1618,9 @@ fn write_bounds_like_dyn_trait(
16091618 let proj_arg_count = generics ( f. db . upcast ( ) , assoc_ty_id. into ( ) ) . len_self ( ) ;
16101619 if proj_arg_count > 0 {
16111620 write ! ( f, "<" ) ?;
1612- f. write_joined (
1621+ hir_fmt_generic_arguments (
1622+ f,
16131623 & proj. substitution . as_slice ( Interner ) [ ..proj_arg_count] ,
1614- ", " ,
16151624 ) ?;
16161625 write ! ( f, ">" ) ?;
16171626 }
@@ -1670,6 +1679,7 @@ fn fmt_trait_ref(
16701679 f. end_location_link ( ) ;
16711680 if tr. substitution . len ( Interner ) > 1 {
16721681 write ! ( f, "<" ) ?;
1682+ // FIXME use `hir_fmt_generics` here
16731683 f. write_joined ( & tr. substitution . as_slice ( Interner ) [ 1 ..] , ", " ) ?;
16741684 write ! ( f, ">" ) ?;
16751685 }
@@ -1728,15 +1738,16 @@ impl HirDisplay for Lifetime {
17281738impl HirDisplay for LifetimeData {
17291739 fn hir_fmt ( & self , f : & mut HirFormatter < ' _ > ) -> Result < ( ) , HirDisplayError > {
17301740 match self {
1731- LifetimeData :: BoundVar ( idx) => idx. hir_fmt ( f) ,
1732- LifetimeData :: InferenceVar ( _) => write ! ( f, "_" ) ,
17331741 LifetimeData :: Placeholder ( idx) => {
17341742 let id = lt_from_placeholder_idx ( f. db , * idx) ;
17351743 let generics = generics ( f. db . upcast ( ) , id. parent ) ;
17361744 let param_data = & generics. params [ id. local_id ] ;
17371745 write ! ( f, "{}" , param_data. name. display( f. db. upcast( ) ) ) ?;
17381746 Ok ( ( ) )
17391747 }
1748+ _ if f. display_target . is_source_code ( ) => write ! ( f, "'_" ) ,
1749+ LifetimeData :: BoundVar ( idx) => idx. hir_fmt ( f) ,
1750+ LifetimeData :: InferenceVar ( _) => write ! ( f, "_" ) ,
17401751 LifetimeData :: Static => write ! ( f, "'static" ) ,
17411752 LifetimeData :: Error => write ! ( f, "'{{error}}" ) ,
17421753 LifetimeData :: Erased => Ok ( ( ) ) ,
0 commit comments