@@ -42,7 +42,7 @@ use hir_def::{
4242 adt:: VariantData ,
4343 body:: { BodyDiagnostic , SyntheticSyntax } ,
4444 expr:: { BindingAnnotation , ExprOrPatId , LabelId , Pat , PatId } ,
45- generics:: { TypeOrConstParamData , TypeParamProvenance } ,
45+ generics:: { LifetimeParamData , TypeOrConstParamData , TypeParamProvenance } ,
4646 item_tree:: ItemTreeNode ,
4747 lang_item:: { LangItem , LangItemTarget } ,
4848 layout:: { Layout , LayoutError , ReprOptions } ,
@@ -1170,6 +1170,25 @@ impl Adt {
11701170 }
11711171 }
11721172
1173+ /// Returns the lifetime of the DataType
1174+ pub fn lifetime ( & self , db : & dyn HirDatabase ) -> Option < LifetimeParamData > {
1175+ let resolver = match self {
1176+ Adt :: Struct ( s) => s. id . resolver ( db. upcast ( ) ) ,
1177+ Adt :: Union ( u) => u. id . resolver ( db. upcast ( ) ) ,
1178+ Adt :: Enum ( e) => e. id . resolver ( db. upcast ( ) ) ,
1179+ } ;
1180+ resolver
1181+ . generic_params ( )
1182+ . and_then ( |gp| {
1183+ ( & gp. lifetimes )
1184+ . iter ( )
1185+ // there should only be a single lifetime
1186+ // but `Arena` requires to use an iterator
1187+ . nth ( 0 )
1188+ } )
1189+ . map ( |arena| arena. 1 . clone ( ) )
1190+ }
1191+
11731192 pub fn as_enum ( & self ) -> Option < Enum > {
11741193 if let Self :: Enum ( v) = self {
11751194 Some ( * v)
@@ -3332,6 +3351,24 @@ impl Type {
33323351 }
33333352 }
33343353
3354+ /// Iterates its type arguments
3355+ ///
3356+ /// It iterates the actual type arguments when concrete types are used
3357+ /// and otherwise the generic names.
3358+ /// It does not include `const` arguments.
3359+ ///
3360+ /// For code, such as:
3361+ /// ```text
3362+ /// struct Foo<T, U>
3363+ ///
3364+ /// impl<U> Foo<String, U>
3365+ /// ```
3366+ ///
3367+ /// It iterates:
3368+ /// ```text
3369+ /// - "String"
3370+ /// - "U"
3371+ /// ```
33353372 pub fn type_arguments ( & self ) -> impl Iterator < Item = Type > + ' _ {
33363373 self . ty
33373374 . strip_references ( )
@@ -3342,6 +3379,58 @@ impl Type {
33423379 . map ( move |ty| self . derived ( ty) )
33433380 }
33443381
3382+ /// Iterates its type and const arguments
3383+ ///
3384+ /// It iterates the actual type and const arguments when concrete types
3385+ /// are used and otherwise the generic names.
3386+ ///
3387+ /// For code, such as:
3388+ /// ```text
3389+ /// struct Foo<T, const U: usize, const X: usize>
3390+ ///
3391+ /// impl<U> Foo<String, U, 12>
3392+ /// ```
3393+ ///
3394+ /// It iterates:
3395+ /// ```text
3396+ /// - "String"
3397+ /// - "U"
3398+ /// - "12"
3399+ /// ```
3400+ pub fn type_and_const_arguments < ' a > (
3401+ & ' a self ,
3402+ db : & ' a dyn HirDatabase ,
3403+ ) -> impl Iterator < Item = SmolStr > + ' a {
3404+ self . ty
3405+ . strip_references ( )
3406+ . as_adt ( )
3407+ . into_iter ( )
3408+ . flat_map ( |( _, substs) | substs. iter ( Interner ) )
3409+ . filter_map ( |arg| {
3410+ // arg can be either a `Ty` or `constant`
3411+ if let Some ( ty) = arg. ty ( Interner ) {
3412+ Some ( SmolStr :: new ( ty. display ( db) . to_string ( ) ) )
3413+ } else if let Some ( const_) = arg. constant ( Interner ) {
3414+ Some ( SmolStr :: new_inline ( & const_. display ( db) . to_string ( ) ) )
3415+ } else {
3416+ None
3417+ }
3418+ } )
3419+ }
3420+
3421+ /// Combines lifetime indicators, type and constant parameters into a single `Iterator`
3422+ pub fn generic_parameters < ' a > (
3423+ & ' a self ,
3424+ db : & ' a dyn HirDatabase ,
3425+ ) -> impl Iterator < Item = SmolStr > + ' a {
3426+ // iterate the lifetime
3427+ self . as_adt ( )
3428+ . and_then ( |a| a. lifetime ( db) . and_then ( |lt| Some ( ( & lt. name ) . to_smol_str ( ) ) ) )
3429+ . into_iter ( )
3430+ // add the type and const paramaters
3431+ . chain ( self . type_and_const_arguments ( db) )
3432+ }
3433+
33453434 pub fn iterate_method_candidates_with_traits < T > (
33463435 & self ,
33473436 db : & dyn HirDatabase ,
0 commit comments