@@ -26,8 +26,8 @@ use hir_ty::{
2626 autoderef,
2727 display:: { HirDisplayError , HirFormatter } ,
2828 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 ,
3131} ;
3232use ra_db:: { CrateId , CrateName , Edition , FileId } ;
3333use ra_prof:: profile;
@@ -1375,6 +1375,18 @@ impl Type {
13751375 Some ( adt. into ( ) )
13761376 }
13771377
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+
13781390 // FIXME: provide required accessors such that it becomes implementable from outside.
13791391 pub fn is_equal_for_find_impls ( & self , other : & Type ) -> bool {
13801392 match ( & self . ty . value , & other. ty . value ) {
@@ -1397,96 +1409,72 @@ impl Type {
13971409 }
13981410 }
13991411
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 ) ;
14051417 }
14061418 }
14071419
1408- fn push_bounds (
1420+ fn walk_trait (
14091421 db : & dyn HirDatabase ,
1410- predicates : & [ GenericPredicate ] ,
1411- acc : & mut Vec < ModuleDef > ,
1422+ ty : Ty ,
1423+ trait_ref : & TraitRef ,
1424+ cb : & mut impl FnMut ( Type ) ,
14121425 ) {
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) ;
14231431 }
14241432
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 } ) => {
14351438 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+ }
14441448 }
14451449 _ => ( ) ,
14461450 }
1451+
14471452 // adt params, tuples, etc...
1448- walk_substs ( db, parameters, acc ) ;
1453+ walk_substs ( db, parameters, cb ) ;
14491454 }
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) ;
14521461 }
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) ;
14661465 }
14671466 }
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+ }
14821471 }
1472+
14831473 _ => ( ) ,
14841474 }
14851475 }
14861476
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) ;
14901478 }
14911479}
14921480
0 commit comments