@@ -26,8 +26,8 @@ use hir_ty::{
26
26
autoderef,
27
27
display:: { HirDisplayError , HirFormatter } ,
28
28
expr:: ExprValidator ,
29
- method_resolution, ApplicationTy , Canonical , GenericPredicate , InEnvironment , OpaqueTyId ,
30
- Substs , TraitEnvironment , Ty , TyDefId , TypeCtor ,
29
+ method_resolution, ApplicationTy , Canonical , InEnvironment , Substs , TraitEnvironment , TraitRef ,
30
+ Ty , TyDefId , TypeCtor ,
31
31
} ;
32
32
use ra_db:: { CrateId , CrateName , Edition , FileId } ;
33
33
use ra_prof:: profile;
@@ -1375,6 +1375,18 @@ impl Type {
1375
1375
Some ( adt. into ( ) )
1376
1376
}
1377
1377
1378
+ pub fn as_dyn_trait ( & self ) -> Option < Trait > {
1379
+ self . ty . value . dyn_trait ( ) . map ( Into :: into)
1380
+ }
1381
+
1382
+ pub fn as_impl_trait ( & self , db : & dyn HirDatabase ) -> Option < Trait > {
1383
+ self . ty . value . impl_trait_ref ( db) . map ( |it| it. trait_ . into ( ) )
1384
+ }
1385
+
1386
+ pub fn as_associated_type_parent_trait ( & self , db : & dyn HirDatabase ) -> Option < Trait > {
1387
+ self . ty . value . associated_type_parent_trait ( db) . map ( Into :: into)
1388
+ }
1389
+
1378
1390
// FIXME: provide required accessors such that it becomes implementable from outside.
1379
1391
pub fn is_equal_for_find_impls ( & self , other : & Type ) -> bool {
1380
1392
match ( & self . ty . value , & other. ty . value ) {
@@ -1397,96 +1409,72 @@ impl Type {
1397
1409
}
1398
1410
}
1399
1411
1400
- /// Returns a flattened list of all ADTs and Traits mentioned in the type
1401
- pub fn flattened_type_items ( & self , db : & dyn HirDatabase ) -> Vec < ModuleDef > {
1402
- fn push_new_item ( item : ModuleDef , acc : & mut Vec < ModuleDef > ) {
1403
- if !acc . contains ( & item ) {
1404
- acc . push ( item ) ;
1412
+ pub fn walk ( & self , db : & dyn HirDatabase , mut cb : impl FnMut ( Type ) ) {
1413
+ // TypeWalk::walk does not preserve items order!
1414
+ fn walk_substs ( db : & dyn HirDatabase , substs : & Substs , cb : & mut impl FnMut ( Type ) ) {
1415
+ for ty in substs . iter ( ) {
1416
+ walk_ty ( db , ty , cb ) ;
1405
1417
}
1406
1418
}
1407
1419
1408
- fn push_bounds (
1420
+ fn walk_trait (
1409
1421
db : & dyn HirDatabase ,
1410
- predicates : & [ GenericPredicate ] ,
1411
- acc : & mut Vec < ModuleDef > ,
1422
+ ty : Ty ,
1423
+ trait_ref : & TraitRef ,
1424
+ cb : & mut impl FnMut ( Type ) ,
1412
1425
) {
1413
- for p in predicates. iter ( ) {
1414
- match p {
1415
- GenericPredicate :: Implemented ( trait_ref) => {
1416
- push_new_item ( Trait :: from ( trait_ref. trait_ ) . into ( ) , acc) ;
1417
- walk_substs ( db, & trait_ref. substs , acc) ;
1418
- }
1419
- GenericPredicate :: Projection ( _) => { }
1420
- GenericPredicate :: Error => ( ) ,
1421
- }
1422
- }
1426
+ let def_db: & dyn DefDatabase = db. upcast ( ) ;
1427
+ let resolver = trait_ref. trait_ . resolver ( def_db) ;
1428
+ let krate = trait_ref. trait_ . lookup ( def_db) . container . module ( def_db) . krate ;
1429
+ cb ( Type :: new_with_resolver_inner ( db, krate, & resolver, ty) ) ;
1430
+ walk_substs ( db, & trait_ref. substs , cb) ;
1423
1431
}
1424
1432
1425
- // TypeWalk::walk does not preserve items order!
1426
- fn walk_substs ( db : & dyn HirDatabase , substs : & Substs , acc : & mut Vec < ModuleDef > ) {
1427
- for ty in substs. iter ( ) {
1428
- walk_type ( db, ty, acc) ;
1429
- }
1430
- }
1431
-
1432
- fn walk_type ( db : & dyn HirDatabase , ty : & Ty , acc : & mut Vec < ModuleDef > ) {
1433
- match ty. strip_references ( ) {
1434
- Ty :: Apply ( ApplicationTy { ctor, parameters, .. } ) => {
1433
+ fn walk_ty ( db : & dyn HirDatabase , ty : & Ty , cb : & mut impl FnMut ( Type ) ) {
1434
+ let def_db: & dyn DefDatabase = db. upcast ( ) ;
1435
+ let ty = ty. strip_references ( ) ;
1436
+ match ty {
1437
+ Ty :: Apply ( ApplicationTy { ctor, parameters } ) => {
1435
1438
match ctor {
1436
- TypeCtor :: Adt ( adt_id) => push_new_item ( Adt :: from ( * adt_id) . into ( ) , acc) ,
1437
- TypeCtor :: AssociatedType ( type_alias_id) => {
1438
- let trait_id = match type_alias_id. lookup ( db. upcast ( ) ) . container {
1439
- AssocContainerId :: TraitId ( it) => it,
1440
- _ => panic ! ( "not an associated type" ) ,
1441
- } ;
1442
-
1443
- push_new_item ( Trait :: from ( trait_id) . into ( ) , acc) ;
1439
+ TypeCtor :: Adt ( adt) => {
1440
+ cb ( Type :: from_def ( db, adt. module ( def_db) . krate , * adt) ) ;
1441
+ }
1442
+ TypeCtor :: AssociatedType ( _) => {
1443
+ if let Some ( trait_id) = ty. associated_type_parent_trait ( db) {
1444
+ let resolver = trait_id. resolver ( def_db) ;
1445
+ let krate = trait_id. lookup ( def_db) . container . module ( def_db) . krate ;
1446
+ cb ( Type :: new_with_resolver_inner ( db, krate, & resolver, ty. clone ( ) ) ) ;
1447
+ }
1444
1448
}
1445
1449
_ => ( ) ,
1446
1450
}
1451
+
1447
1452
// adt params, tuples, etc...
1448
- walk_substs ( db, parameters, acc ) ;
1453
+ walk_substs ( db, parameters, cb ) ;
1449
1454
}
1450
- Ty :: Dyn ( predicates) => {
1451
- push_bounds ( db, predicates, acc) ;
1455
+ Ty :: Opaque ( opaque_ty) => {
1456
+ if let Some ( trait_ref) = ty. impl_trait_ref ( db) {
1457
+ walk_trait ( db, ty. clone ( ) , & trait_ref, cb) ;
1458
+ }
1459
+
1460
+ walk_substs ( db, & opaque_ty. parameters , cb) ;
1452
1461
}
1453
- Ty :: Placeholder ( id) => {
1454
- let generic_params = db. generic_params ( id. parent ) ;
1455
- let param_data = & generic_params. types [ id. local_id ] ;
1456
- match param_data. provenance {
1457
- hir_def:: generics:: TypeParamProvenance :: ArgumentImplTrait => {
1458
- let predicates: Vec < _ > = db
1459
- . generic_predicates_for_param ( * id)
1460
- . into_iter ( )
1461
- . map ( |pred| pred. value . clone ( ) )
1462
- . collect ( ) ;
1463
- push_bounds ( db, & predicates, acc) ;
1464
- }
1465
- _ => ( ) ,
1462
+ Ty :: Placeholder ( _) => {
1463
+ if let Some ( trait_ref) = ty. impl_trait_ref ( db) {
1464
+ walk_trait ( db, ty. clone ( ) , & trait_ref, cb) ;
1466
1465
}
1467
1466
}
1468
- Ty :: Opaque ( opaque_ty) => {
1469
- let bounds = match opaque_ty. opaque_ty_id {
1470
- OpaqueTyId :: ReturnTypeImplTrait ( func, idx) => {
1471
- let datas = db
1472
- . return_type_impl_traits ( func)
1473
- . expect ( "impl trait id without data" ) ;
1474
- let data = ( * datas)
1475
- . as_ref ( )
1476
- . map ( |rpit| rpit. impl_traits [ idx as usize ] . bounds . clone ( ) ) ;
1477
- data. clone ( ) . subst ( & opaque_ty. parameters )
1478
- }
1479
- } ;
1480
- push_bounds ( db, & bounds. value , acc) ;
1481
- walk_substs ( db, & opaque_ty. parameters , acc) ;
1467
+ Ty :: Dyn ( _) => {
1468
+ if let Some ( trait_ref) = ty. dyn_trait_ref ( ) {
1469
+ walk_trait ( db, ty. clone ( ) , trait_ref, cb) ;
1470
+ }
1482
1471
}
1472
+
1483
1473
_ => ( ) ,
1484
1474
}
1485
1475
}
1486
1476
1487
- let mut res: Vec < ModuleDef > = Vec :: new ( ) ; // not a Set to preserve the order
1488
- walk_type ( db, & self . ty . value , & mut res) ;
1489
- res
1477
+ walk_ty ( db, & self . ty . value , & mut cb) ;
1490
1478
}
1491
1479
}
1492
1480
0 commit comments