3
3
use std:: { collections:: hash_map:: Entry , sync:: Arc } ;
4
4
5
5
use hir_expand:: { ast_id_map:: AstIdMap , hygiene:: Hygiene , HirFileId } ;
6
- use syntax:: ast:: { self , HasModuleItem } ;
6
+ use syntax:: ast:: { self , HasModuleItem , HasTypeBounds } ;
7
7
8
8
use crate :: {
9
9
generics:: { GenericParams , TypeParamData , TypeParamProvenance } ,
@@ -109,7 +109,8 @@ impl<'a> Ctx<'a> {
109
109
ast:: Item :: Static ( ast) => self . lower_static ( ast) ?. into ( ) ,
110
110
ast:: Item :: Const ( ast) => self . lower_const ( ast) . into ( ) ,
111
111
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 ( ) ,
113
114
ast:: Item :: Impl ( ast) => self . lower_impl ( ast) ?. into ( ) ,
114
115
ast:: Item :: Use ( ast) => self . lower_use ( ast) ?. into ( ) ,
115
116
ast:: Item :: ExternCrate ( ast) => self . lower_extern_crate ( ast) ?. into ( ) ,
@@ -147,7 +148,7 @@ impl<'a> Ctx<'a> {
147
148
fn lower_struct ( & mut self , strukt : & ast:: Struct ) -> Option < FileItemTreeId < Struct > > {
148
149
let visibility = self . lower_visibility ( strukt) ;
149
150
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) ;
151
152
let fields = self . lower_fields ( & strukt. kind ( ) ) ;
152
153
let ast_id = self . source_ast_id_map . ast_id ( strukt) ;
153
154
let res = Struct { name, visibility, generic_params, fields, ast_id } ;
@@ -211,7 +212,7 @@ impl<'a> Ctx<'a> {
211
212
fn lower_union ( & mut self , union : & ast:: Union ) -> Option < FileItemTreeId < Union > > {
212
213
let visibility = self . lower_visibility ( union) ;
213
214
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) ;
215
216
let fields = match union. record_field_list ( ) {
216
217
Some ( record_field_list) => self . lower_fields ( & StructKind :: Record ( record_field_list) ) ,
217
218
None => Fields :: Record ( IdxRange :: new ( self . next_field_idx ( ) ..self . next_field_idx ( ) ) ) ,
@@ -224,7 +225,7 @@ impl<'a> Ctx<'a> {
224
225
fn lower_enum ( & mut self , enum_ : & ast:: Enum ) -> Option < FileItemTreeId < Enum > > {
225
226
let visibility = self . lower_visibility ( enum_) ;
226
227
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_) ;
228
229
let variants = match & enum_. variant_list ( ) {
229
230
Some ( variant_list) => self . lower_variants ( variant_list) ,
230
231
None => IdxRange :: new ( self . next_variant_idx ( ) ..self . next_variant_idx ( ) ) ,
@@ -372,8 +373,7 @@ impl<'a> Ctx<'a> {
372
373
ast_id,
373
374
flags,
374
375
} ;
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) ;
377
377
378
378
Some ( id ( self . data ( ) . functions . alloc ( res) ) )
379
379
}
@@ -386,7 +386,7 @@ impl<'a> Ctx<'a> {
386
386
let type_ref = type_alias. ty ( ) . map ( |it| self . lower_type_ref ( & it) ) ;
387
387
let visibility = self . lower_visibility ( type_alias) ;
388
388
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) ;
390
390
let ast_id = self . source_ast_id_map . ast_id ( type_alias) ;
391
391
let res = TypeAlias {
392
392
name,
@@ -439,43 +439,52 @@ impl<'a> Ctx<'a> {
439
439
Some ( id ( self . data ( ) . mods . alloc ( res) ) )
440
440
}
441
441
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 > > {
443
443
let name = trait_def. name ( ) ?. as_name ( ) ;
444
444
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) ;
446
447
let is_auto = trait_def. auto_token ( ) . is_some ( ) ;
447
448
let is_unsafe = trait_def. unsafe_token ( ) . is_some ( ) ;
448
449
let ast_id = self . source_ast_id_map . ast_id ( trait_def) ;
449
450
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
467
460
} )
468
- . collect ( ) ;
461
+ } )
462
+ . collect ( ) ;
469
463
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
+ }
473
467
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) ) )
475
482
}
476
483
477
484
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) ;
479
488
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
480
489
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
481
490
// equals itself.
@@ -579,42 +588,29 @@ impl<'a> Ctx<'a> {
579
588
580
589
fn lower_generic_params (
581
590
& mut self ,
582
- owner : GenericsOwner < ' _ > ,
591
+ has_implicit_self : HasImplicitSelf ,
583
592
node : & dyn ast:: HasGenericParams ,
584
593
) -> Interned < GenericParams > {
585
594
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) ) ;
616
610
}
617
611
612
+ generics. fill ( & self . body_ctx , node) ;
613
+
618
614
generics. shrink_to_fit ( ) ;
619
615
Interned :: new ( generics)
620
616
}
@@ -686,17 +682,10 @@ fn desugar_future_path(orig: TypeRef) -> Path {
686
682
Path :: from_known_path ( path, generic_args)
687
683
}
688
684
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 ,
700
689
}
701
690
702
691
fn lower_abi ( abi : ast:: Abi ) -> Interned < str > {
0 commit comments