@@ -26,8 +26,8 @@ use hir_ty::{
26
26
autoderef,
27
27
display:: { HirDisplayError , HirFormatter } ,
28
28
expr:: ExprValidator ,
29
- method_resolution, ApplicationTy , Canonical , InEnvironment , Substs , TraitEnvironment , Ty ,
30
- TyDefId , TypeCtor ,
29
+ method_resolution, ApplicationTy , Canonical , GenericPredicate , InEnvironment , OpaqueTyId ,
30
+ Substs , TraitEnvironment , Ty , TyDefId , TypeCtor , TypeWalk ,
31
31
} ;
32
32
use ra_db:: { CrateId , CrateName , Edition , FileId } ;
33
33
use ra_prof:: profile;
@@ -1380,6 +1380,87 @@ impl Type {
1380
1380
ty : InEnvironment { value : ty, environment : self . ty . environment . clone ( ) } ,
1381
1381
}
1382
1382
}
1383
+
1384
+ /// Returns a flattened list of all the ADTs and Traits mentioned in the type
1385
+ pub fn flattened_type_items ( & self , db : & dyn HirDatabase ) -> Vec < AdtOrTrait > {
1386
+ fn push_new_item ( item : AdtOrTrait , acc : & mut Vec < AdtOrTrait > ) {
1387
+ if !acc. contains ( & item) {
1388
+ acc. push ( item) ;
1389
+ }
1390
+ }
1391
+
1392
+ fn push_bounds (
1393
+ db : & dyn HirDatabase ,
1394
+ predicates : & [ GenericPredicate ] ,
1395
+ acc : & mut Vec < AdtOrTrait > ,
1396
+ ) {
1397
+ for p in predicates. iter ( ) {
1398
+ match p {
1399
+ GenericPredicate :: Implemented ( trait_ref) => {
1400
+ push_new_item ( Trait :: from ( trait_ref. trait_ ) . into ( ) , acc) ;
1401
+ walk_types ( db, & trait_ref. substs , acc) ;
1402
+ }
1403
+ GenericPredicate :: Projection ( _) => { }
1404
+ GenericPredicate :: Error => ( ) ,
1405
+ }
1406
+ }
1407
+ }
1408
+
1409
+ fn walk_types < T : TypeWalk > ( db : & dyn HirDatabase , tw : & T , acc : & mut Vec < AdtOrTrait > ) {
1410
+ tw. walk ( & mut |ty| walk_type ( db, ty, acc) ) ;
1411
+ }
1412
+
1413
+ fn walk_type ( db : & dyn HirDatabase , ty : & Ty , acc : & mut Vec < AdtOrTrait > ) {
1414
+ match ty. strip_references ( ) {
1415
+ Ty :: Apply ( ApplicationTy { ctor, parameters, .. } ) => {
1416
+ match ctor {
1417
+ TypeCtor :: Adt ( adt_id) => push_new_item ( Adt :: from ( * adt_id) . into ( ) , acc) ,
1418
+ _ => ( ) ,
1419
+ }
1420
+ // adt params, tuples, etc...
1421
+ walk_types ( db, parameters, acc) ;
1422
+ }
1423
+ Ty :: Dyn ( predicates) => {
1424
+ push_bounds ( db, predicates, acc) ;
1425
+ }
1426
+ Ty :: Placeholder ( id) => {
1427
+ let generic_params = db. generic_params ( id. parent ) ;
1428
+ let param_data = & generic_params. types [ id. local_id ] ;
1429
+ match param_data. provenance {
1430
+ hir_def:: generics:: TypeParamProvenance :: ArgumentImplTrait => {
1431
+ let predicates: Vec < _ > = db
1432
+ . generic_predicates_for_param ( * id)
1433
+ . into_iter ( )
1434
+ . map ( |pred| pred. value . clone ( ) )
1435
+ . collect ( ) ;
1436
+ push_bounds ( db, & predicates, acc) ;
1437
+ }
1438
+ _ => ( ) ,
1439
+ }
1440
+ }
1441
+ Ty :: Opaque ( opaque_ty) => {
1442
+ let bounds = match opaque_ty. opaque_ty_id {
1443
+ OpaqueTyId :: ReturnTypeImplTrait ( func, idx) => {
1444
+ let datas = db
1445
+ . return_type_impl_traits ( func)
1446
+ . expect ( "impl trait id without data" ) ;
1447
+ let data = ( * datas)
1448
+ . as_ref ( )
1449
+ . map ( |rpit| rpit. impl_traits [ idx as usize ] . bounds . clone ( ) ) ;
1450
+ data. clone ( ) . subst ( & opaque_ty. parameters )
1451
+ }
1452
+ } ;
1453
+ push_bounds ( db, & bounds. value , acc) ;
1454
+ walk_types ( db, & opaque_ty. parameters , acc) ;
1455
+ }
1456
+ _ => ( ) ,
1457
+ }
1458
+ }
1459
+
1460
+ let mut res: Vec < AdtOrTrait > = Vec :: new ( ) ; // not a Set to preserve the order
1461
+ walk_type ( db, & self . ty . value , & mut res) ;
1462
+ res
1463
+ }
1383
1464
}
1384
1465
1385
1466
impl HirDisplay for Type {
@@ -1488,3 +1569,26 @@ pub trait HasVisibility {
1488
1569
vis. is_visible_from ( db. upcast ( ) , module. id )
1489
1570
}
1490
1571
}
1572
+
1573
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
1574
+ pub enum AdtOrTrait {
1575
+ Adt ( Adt ) ,
1576
+ Trait ( Trait ) ,
1577
+ }
1578
+ impl_froms ! ( AdtOrTrait : Adt , Trait ) ;
1579
+
1580
+ impl AdtOrTrait {
1581
+ pub fn module ( self , db : & dyn HirDatabase ) -> Module {
1582
+ match self {
1583
+ AdtOrTrait :: Adt ( adt) => adt. module ( db) ,
1584
+ AdtOrTrait :: Trait ( trait_) => trait_. module ( db) ,
1585
+ }
1586
+ }
1587
+
1588
+ pub fn name ( self , db : & dyn HirDatabase ) -> Name {
1589
+ match self {
1590
+ AdtOrTrait :: Adt ( adt) => adt. name ( db) ,
1591
+ AdtOrTrait :: Trait ( trait_) => trait_. name ( db) ,
1592
+ }
1593
+ }
1594
+ }
0 commit comments