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 } ,
@@ -148,7 +148,7 @@ impl<'a> Ctx<'a> {
148
148
fn lower_struct ( & mut self , strukt : & ast:: Struct ) -> Option < FileItemTreeId < Struct > > {
149
149
let visibility = self . lower_visibility ( strukt) ;
150
150
let name = strukt. name ( ) ?. as_name ( ) ;
151
- let generic_params = self . lower_generic_params ( GenericsOwner :: Struct , strukt) ;
151
+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , strukt) ;
152
152
let fields = self . lower_fields ( & strukt. kind ( ) ) ;
153
153
let ast_id = self . source_ast_id_map . ast_id ( strukt) ;
154
154
let res = Struct { name, visibility, generic_params, fields, ast_id } ;
@@ -212,7 +212,7 @@ impl<'a> Ctx<'a> {
212
212
fn lower_union ( & mut self , union : & ast:: Union ) -> Option < FileItemTreeId < Union > > {
213
213
let visibility = self . lower_visibility ( union) ;
214
214
let name = union. name ( ) ?. as_name ( ) ;
215
- let generic_params = self . lower_generic_params ( GenericsOwner :: Union , union) ;
215
+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , union) ;
216
216
let fields = match union. record_field_list ( ) {
217
217
Some ( record_field_list) => self . lower_fields ( & StructKind :: Record ( record_field_list) ) ,
218
218
None => Fields :: Record ( IdxRange :: new ( self . next_field_idx ( ) ..self . next_field_idx ( ) ) ) ,
@@ -225,7 +225,7 @@ impl<'a> Ctx<'a> {
225
225
fn lower_enum ( & mut self , enum_ : & ast:: Enum ) -> Option < FileItemTreeId < Enum > > {
226
226
let visibility = self . lower_visibility ( enum_) ;
227
227
let name = enum_. name ( ) ?. as_name ( ) ;
228
- let generic_params = self . lower_generic_params ( GenericsOwner :: Enum , enum_) ;
228
+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , enum_) ;
229
229
let variants = match & enum_. variant_list ( ) {
230
230
Some ( variant_list) => self . lower_variants ( variant_list) ,
231
231
None => IdxRange :: new ( self . next_variant_idx ( ) ..self . next_variant_idx ( ) ) ,
@@ -373,8 +373,7 @@ impl<'a> Ctx<'a> {
373
373
ast_id,
374
374
flags,
375
375
} ;
376
- res. explicit_generic_params =
377
- self . lower_generic_params ( GenericsOwner :: Function ( & res) , func) ;
376
+ res. explicit_generic_params = self . lower_generic_params ( HasImplicitSelf :: No , func) ;
378
377
379
378
Some ( id ( self . data ( ) . functions . alloc ( res) ) )
380
379
}
@@ -387,7 +386,7 @@ impl<'a> Ctx<'a> {
387
386
let type_ref = type_alias. ty ( ) . map ( |it| self . lower_type_ref ( & it) ) ;
388
387
let visibility = self . lower_visibility ( type_alias) ;
389
388
let bounds = self . lower_type_bounds ( type_alias) ;
390
- let generic_params = self . lower_generic_params ( GenericsOwner :: TypeAlias , type_alias) ;
389
+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , type_alias) ;
391
390
let ast_id = self . source_ast_id_map . ast_id ( type_alias) ;
392
391
let res = TypeAlias {
393
392
name,
@@ -443,7 +442,8 @@ impl<'a> Ctx<'a> {
443
442
fn lower_trait ( & mut self , trait_def : & ast:: Trait ) -> Option < FileItemTreeId < Trait > > {
444
443
let name = trait_def. name ( ) ?. as_name ( ) ;
445
444
let visibility = self . lower_visibility ( trait_def) ;
446
- 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) ;
447
447
let is_auto = trait_def. auto_token ( ) . is_some ( ) ;
448
448
let is_unsafe = trait_def. unsafe_token ( ) . is_some ( ) ;
449
449
let items = trait_def. assoc_item_list ( ) . map ( |list| {
@@ -463,7 +463,9 @@ impl<'a> Ctx<'a> {
463
463
}
464
464
465
465
fn lower_impl ( & mut self , impl_def : & ast:: Impl ) -> Option < FileItemTreeId < Impl > > {
466
- let generic_params = self . lower_generic_params ( GenericsOwner :: Impl , impl_def) ;
466
+ // Note that trait impls don't get implicit `Self` unlike traits, because here they are a
467
+ // type alias rather than a type parameter, so this is handled by the resolver.
468
+ let generic_params = self . lower_generic_params ( HasImplicitSelf :: No , impl_def) ;
467
469
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
468
470
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
469
471
// equals itself.
@@ -567,42 +569,29 @@ impl<'a> Ctx<'a> {
567
569
568
570
fn lower_generic_params (
569
571
& mut self ,
570
- owner : GenericsOwner < ' _ > ,
572
+ has_implicit_self : HasImplicitSelf ,
571
573
node : & dyn ast:: HasGenericParams ,
572
574
) -> Interned < GenericParams > {
573
575
let mut generics = GenericParams :: default ( ) ;
574
- match owner {
575
- GenericsOwner :: Function ( _)
576
- | GenericsOwner :: Struct
577
- | GenericsOwner :: Enum
578
- | GenericsOwner :: Union
579
- | GenericsOwner :: TypeAlias => {
580
- generics. fill ( & self . body_ctx , node) ;
581
- }
582
- GenericsOwner :: Trait ( trait_def) => {
583
- // traits get the Self type as an implicit first type parameter
584
- generics. type_or_consts . alloc (
585
- TypeParamData {
586
- name : Some ( name ! [ Self ] ) ,
587
- default : None ,
588
- provenance : TypeParamProvenance :: TraitSelf ,
589
- }
590
- . into ( ) ,
591
- ) ;
592
- // add super traits as bounds on Self
593
- // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
594
- let self_param = TypeRef :: Path ( name ! [ Self ] . into ( ) ) ;
595
- generics. fill_bounds ( & self . body_ctx , trait_def, Either :: Left ( self_param) ) ;
596
- generics. fill ( & self . body_ctx , node) ;
597
- }
598
- GenericsOwner :: Impl => {
599
- // Note that we don't add `Self` here: in `impl`s, `Self` is not a
600
- // type-parameter, but rather is a type-alias for impl's target
601
- // type, so this is handled by the resolver.
602
- generics. fill ( & self . body_ctx , node) ;
603
- }
576
+
577
+ if let HasImplicitSelf :: Yes ( bounds) = has_implicit_self {
578
+ // Traits and trait aliases get the Self type as an implicit first type parameter.
579
+ generics. type_or_consts . alloc (
580
+ TypeParamData {
581
+ name : Some ( name ! [ Self ] ) ,
582
+ default : None ,
583
+ provenance : TypeParamProvenance :: TraitSelf ,
584
+ }
585
+ . into ( ) ,
586
+ ) ;
587
+ // add super traits as bounds on Self
588
+ // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
589
+ let self_param = TypeRef :: Path ( name ! [ Self ] . into ( ) ) ;
590
+ generics. fill_bounds ( & self . body_ctx , bounds, Either :: Left ( self_param) ) ;
604
591
}
605
592
593
+ generics. fill ( & self . body_ctx , node) ;
594
+
606
595
generics. shrink_to_fit ( ) ;
607
596
Interned :: new ( generics)
608
597
}
@@ -674,17 +663,10 @@ fn desugar_future_path(orig: TypeRef) -> Path {
674
663
Path :: from_known_path ( path, generic_args)
675
664
}
676
665
677
- enum GenericsOwner < ' a > {
678
- /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
679
- /// position.
680
- Function ( & ' a Function ) ,
681
- Struct ,
682
- Enum ,
683
- Union ,
684
- /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
685
- Trait ( & ' a ast:: Trait ) ,
686
- TypeAlias ,
687
- Impl ,
666
+ enum HasImplicitSelf {
667
+ /// Inner list is a type bound list for the implicit `Self`.
668
+ Yes ( Option < ast:: TypeBoundList > ) ,
669
+ No ,
688
670
}
689
671
690
672
fn lower_abi ( abi : ast:: Abi ) -> Interned < str > {
0 commit comments