33use std:: { collections:: hash_map:: Entry , sync:: Arc } ;
44
55use hir_expand:: { ast_id_map:: AstIdMap , hygiene:: Hygiene , HirFileId } ;
6- use syntax:: ast:: { self , HasModuleItem } ;
6+ use syntax:: ast:: { self , HasModuleItem , HasTypeBounds } ;
77
88use crate :: {
99 generics:: { GenericParams , TypeParamData , TypeParamProvenance } ,
@@ -109,7 +109,8 @@ impl<'a> Ctx<'a> {
109109 ast:: Item :: Static ( ast) => self . lower_static ( ast) ?. into ( ) ,
110110 ast:: Item :: Const ( ast) => self . lower_const ( ast) . into ( ) ,
111111 ast:: Item :: Module ( ast) => self . lower_module ( ast) ?. into ( ) ,
112- ast:: Item :: Trait ( ast) => self . lower_trait ( ast) ?,
112+ ast:: Item :: Trait ( ast) => self . lower_trait ( ast) ?. into ( ) ,
113+ ast:: Item :: TraitAlias ( ast) => self . lower_trait_alias ( ast) ?. into ( ) ,
113114 ast:: Item :: Impl ( ast) => self . lower_impl ( ast) ?. into ( ) ,
114115 ast:: Item :: Use ( ast) => self . lower_use ( ast) ?. into ( ) ,
115116 ast:: Item :: ExternCrate ( ast) => self . lower_extern_crate ( ast) ?. into ( ) ,
@@ -147,7 +148,7 @@ impl<'a> Ctx<'a> {
147148 fn lower_struct ( & mut self , strukt : & ast:: Struct ) -> Option < FileItemTreeId < Struct > > {
148149 let visibility = self . lower_visibility ( strukt) ;
149150 let name = strukt. name ( ) ?. as_name ( ) ;
150- let generic_params = self . lower_generic_params ( GenericsOwner :: Struct , strukt) ;
151+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , strukt) ;
151152 let fields = self . lower_fields ( & strukt. kind ( ) ) ;
152153 let ast_id = self . source_ast_id_map . ast_id ( strukt) ;
153154 let res = Struct { name, visibility, generic_params, fields, ast_id } ;
@@ -211,7 +212,7 @@ impl<'a> Ctx<'a> {
211212 fn lower_union ( & mut self , union : & ast:: Union ) -> Option < FileItemTreeId < Union > > {
212213 let visibility = self . lower_visibility ( union) ;
213214 let name = union. name ( ) ?. as_name ( ) ;
214- let generic_params = self . lower_generic_params ( GenericsOwner :: Union , union) ;
215+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , union) ;
215216 let fields = match union. record_field_list ( ) {
216217 Some ( record_field_list) => self . lower_fields ( & StructKind :: Record ( record_field_list) ) ,
217218 None => Fields :: Record ( IdxRange :: new ( self . next_field_idx ( ) ..self . next_field_idx ( ) ) ) ,
@@ -224,7 +225,7 @@ impl<'a> Ctx<'a> {
224225 fn lower_enum ( & mut self , enum_ : & ast:: Enum ) -> Option < FileItemTreeId < Enum > > {
225226 let visibility = self . lower_visibility ( enum_) ;
226227 let name = enum_. name ( ) ?. as_name ( ) ;
227- let generic_params = self . lower_generic_params ( GenericsOwner :: Enum , enum_) ;
228+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , enum_) ;
228229 let variants = match & enum_. variant_list ( ) {
229230 Some ( variant_list) => self . lower_variants ( variant_list) ,
230231 None => IdxRange :: new ( self . next_variant_idx ( ) ..self . next_variant_idx ( ) ) ,
@@ -372,8 +373,7 @@ impl<'a> Ctx<'a> {
372373 ast_id,
373374 flags,
374375 } ;
375- res. explicit_generic_params =
376- self . lower_generic_params ( GenericsOwner :: Function ( & res) , func) ;
376+ res. explicit_generic_params = self . lower_generic_params ( HasImplicitSelf :: No , func) ;
377377
378378 Some ( id ( self . data ( ) . functions . alloc ( res) ) )
379379 }
@@ -386,7 +386,7 @@ impl<'a> Ctx<'a> {
386386 let type_ref = type_alias. ty ( ) . map ( |it| self . lower_type_ref ( & it) ) ;
387387 let visibility = self . lower_visibility ( type_alias) ;
388388 let bounds = self . lower_type_bounds ( type_alias) ;
389- let generic_params = self . lower_generic_params ( GenericsOwner :: TypeAlias , type_alias) ;
389+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , type_alias) ;
390390 let ast_id = self . source_ast_id_map . ast_id ( type_alias) ;
391391 let res = TypeAlias {
392392 name,
@@ -439,43 +439,52 @@ impl<'a> Ctx<'a> {
439439 Some ( id ( self . data ( ) . mods . alloc ( res) ) )
440440 }
441441
442- fn lower_trait ( & mut self , trait_def : & ast:: Trait ) -> Option < ModItem > {
442+ fn lower_trait ( & mut self , trait_def : & ast:: Trait ) -> Option < FileItemTreeId < Trait > > {
443443 let name = trait_def. name ( ) ?. as_name ( ) ;
444444 let visibility = self . lower_visibility ( trait_def) ;
445- let generic_params = self . lower_generic_params ( GenericsOwner :: Trait ( trait_def) , trait_def) ;
445+ let generic_params =
446+ self . lower_generic_params ( HasImplicitSelf :: Yes ( trait_def. type_bound_list ( ) ) , trait_def) ;
446447 let is_auto = trait_def. auto_token ( ) . is_some ( ) ;
447448 let is_unsafe = trait_def. unsafe_token ( ) . is_some ( ) ;
448449 let ast_id = self . source_ast_id_map . ast_id ( trait_def) ;
449450
450- let item = if trait_def. eq_token ( ) . is_some ( ) {
451- // trait aliases
452- let bounds = self . lower_type_bounds ( trait_def) . into_boxed_slice ( ) ;
453- let alias = TraitAlias { name, visibility, generic_params, bounds, ast_id } ;
454- id ( self . data ( ) . trait_aliases . alloc ( alias) ) . into ( )
455- } else {
456- // trait definition
457- let items = trait_def
458- . assoc_item_list ( )
459- . into_iter ( )
460- . flat_map ( |list| list. assoc_items ( ) )
461- . filter_map ( |item| {
462- let attrs = RawAttrs :: new ( self . db . upcast ( ) , & item, self . hygiene ( ) ) ;
463- self . lower_assoc_item ( & item) . map ( |item| {
464- self . add_attrs ( ModItem :: from ( item) . into ( ) , attrs) ;
465- item
466- } )
451+ let items = trait_def
452+ . assoc_item_list ( )
453+ . into_iter ( )
454+ . flat_map ( |list| list. assoc_items ( ) )
455+ . filter_map ( |item| {
456+ let attrs = RawAttrs :: new ( self . db . upcast ( ) , & item, self . hygiene ( ) ) ;
457+ self . lower_assoc_item ( & item) . map ( |item| {
458+ self . add_attrs ( ModItem :: from ( item) . into ( ) , attrs) ;
459+ item
467460 } )
468- . collect ( ) ;
461+ } )
462+ . collect ( ) ;
469463
470- let def = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id } ;
471- id ( self . data ( ) . traits . alloc ( def) ) . into ( )
472- } ;
464+ let def = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id } ;
465+ Some ( id ( self . data ( ) . traits . alloc ( def) ) )
466+ }
473467
474- Some ( item)
468+ fn lower_trait_alias (
469+ & mut self ,
470+ trait_alias_def : & ast:: TraitAlias ,
471+ ) -> Option < FileItemTreeId < TraitAlias > > {
472+ let name = trait_alias_def. name ( ) ?. as_name ( ) ;
473+ let visibility = self . lower_visibility ( trait_alias_def) ;
474+ let generic_params = self . lower_generic_params (
475+ HasImplicitSelf :: Yes ( trait_alias_def. type_bound_list ( ) ) ,
476+ trait_alias_def,
477+ ) ;
478+ let ast_id = self . source_ast_id_map . ast_id ( trait_alias_def) ;
479+
480+ let alias = TraitAlias { name, visibility, generic_params, ast_id } ;
481+ Some ( id ( self . data ( ) . trait_aliases . alloc ( alias) ) )
475482 }
476483
477484 fn lower_impl ( & mut self , impl_def : & ast:: Impl ) -> Option < FileItemTreeId < Impl > > {
478- let generic_params = self . lower_generic_params ( GenericsOwner :: Impl , impl_def) ;
485+ // Note that trait impls don't get implicit `Self` unlike traits, because here they are a
486+ // type alias rather than a type parameter, so this is handled by the resolver.
487+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , impl_def) ;
479488 // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
480489 // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
481490 // equals itself.
@@ -579,42 +588,29 @@ impl<'a> Ctx<'a> {
579588
580589 fn lower_generic_params (
581590 & mut self ,
582- owner : GenericsOwner < ' _ > ,
591+ has_implicit_self : HasImplicitSelf ,
583592 node : & dyn ast:: HasGenericParams ,
584593 ) -> Interned < GenericParams > {
585594 let mut generics = GenericParams :: default ( ) ;
586- match owner {
587- GenericsOwner :: Function ( _)
588- | GenericsOwner :: Struct
589- | GenericsOwner :: Enum
590- | GenericsOwner :: Union
591- | GenericsOwner :: TypeAlias => {
592- generics. fill ( & self . body_ctx , node) ;
593- }
594- GenericsOwner :: Trait ( trait_def) => {
595- // traits get the Self type as an implicit first type parameter
596- generics. type_or_consts . alloc (
597- TypeParamData {
598- name : Some ( name ! [ Self ] ) ,
599- default : None ,
600- provenance : TypeParamProvenance :: TraitSelf ,
601- }
602- . into ( ) ,
603- ) ;
604- // add super traits as bounds on Self
605- // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
606- let self_param = TypeRef :: Path ( name ! [ Self ] . into ( ) ) ;
607- generics. fill_bounds ( & self . body_ctx , trait_def, Either :: Left ( self_param) ) ;
608- generics. fill ( & self . body_ctx , node) ;
609- }
610- GenericsOwner :: Impl => {
611- // Note that we don't add `Self` here: in `impl`s, `Self` is not a
612- // type-parameter, but rather is a type-alias for impl's target
613- // type, so this is handled by the resolver.
614- generics. fill ( & self . body_ctx , node) ;
615- }
595+
596+ if let HasImplicitSelf :: Yes ( bounds) = has_implicit_self {
597+ // Traits and trait aliases get the Self type as an implicit first type parameter.
598+ generics. type_or_consts . alloc (
599+ TypeParamData {
600+ name : Some ( name ! [ Self ] ) ,
601+ default : None ,
602+ provenance : TypeParamProvenance :: TraitSelf ,
603+ }
604+ . into ( ) ,
605+ ) ;
606+ // add super traits as bounds on Self
607+ // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
608+ let self_param = TypeRef :: Path ( name ! [ Self ] . into ( ) ) ;
609+ generics. fill_bounds ( & self . body_ctx , bounds, Either :: Left ( self_param) ) ;
616610 }
617611
612+ generics. fill ( & self . body_ctx , node) ;
613+
618614 generics. shrink_to_fit ( ) ;
619615 Interned :: new ( generics)
620616 }
@@ -686,17 +682,10 @@ fn desugar_future_path(orig: TypeRef) -> Path {
686682 Path :: from_known_path ( path, generic_args)
687683}
688684
689- enum GenericsOwner < ' a > {
690- /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
691- /// position.
692- Function ( & ' a Function ) ,
693- Struct ,
694- Enum ,
695- Union ,
696- /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
697- Trait ( & ' a ast:: Trait ) ,
698- TypeAlias ,
699- Impl ,
685+ enum HasImplicitSelf {
686+ /// Inner list is a type bound list for the implicit `Self`.
687+ Yes ( Option < ast:: TypeBoundList > ) ,
688+ No ,
700689}
701690
702691fn lower_abi ( abi : ast:: Abi ) -> Interned < str > {
0 commit comments