about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2023-03-04 00:24:05 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2023-03-04 00:24:05 +0900
commite2ec3a6561d73cc4b530c69a9bafc30c4f34b1ec (patch)
tree72b611d7d61bca146382e955aea678b4934bdbc5
parent356d12eae4b8985dc933c13e9281546d532d0845 (diff)
downloadrust-e2ec3a6561d73cc4b530c69a9bafc30c4f34b1ec.tar.gz
rust-e2ec3a6561d73cc4b530c69a9bafc30c4f34b1ec.zip
Refactor generic parameter lowering
Since we moved impl trait handling to other place, there are only two
cases now: those that introduce implicit `Self` parameter and those that
don't.
-rw-r--r--crates/hir-def/src/generics.rs18
-rw-r--r--crates/hir-def/src/item_tree/lower.rs84
2 files changed, 45 insertions, 57 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index b2ab0c30e03..5a0aa193388 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -207,12 +207,10 @@ impl GenericParams {
     pub(crate) fn fill_bounds(
         &mut self,
         lower_ctx: &LowerCtx<'_>,
-        node: &dyn ast::HasTypeBounds,
+        type_bounds: Option<ast::TypeBoundList>,
         target: Either<TypeRef, LifetimeRef>,
     ) {
-        for bound in
-            node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
-        {
+        for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
             self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
         }
     }
@@ -233,7 +231,11 @@ impl GenericParams {
                     };
                     self.type_or_consts.alloc(param.into());
                     let type_ref = TypeRef::Path(name.into());
-                    self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
+                    self.fill_bounds(
+                        lower_ctx,
+                        type_param.type_bound_list(),
+                        Either::Left(type_ref),
+                    );
                 }
                 ast::TypeOrConstParam::Const(const_param) => {
                     let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
@@ -255,7 +257,11 @@ impl GenericParams {
             let param = LifetimeParamData { name: name.clone() };
             self.lifetimes.alloc(param);
             let lifetime_ref = LifetimeRef::new_name(name);
-            self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
+            self.fill_bounds(
+                lower_ctx,
+                lifetime_param.type_bound_list(),
+                Either::Right(lifetime_ref),
+            );
         }
     }
 
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index bd7c556ae69..b64b4d11e37 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -3,7 +3,7 @@
 use std::{collections::hash_map::Entry, sync::Arc};
 
 use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
-use syntax::ast::{self, HasModuleItem};
+use syntax::ast::{self, HasModuleItem, HasTypeBounds};
 
 use crate::{
     generics::{GenericParams, TypeParamData, TypeParamProvenance},
@@ -148,7 +148,7 @@ impl<'a> Ctx<'a> {
     fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
         let visibility = self.lower_visibility(strukt);
         let name = strukt.name()?.as_name();
-        let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt);
+        let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
         let fields = self.lower_fields(&strukt.kind());
         let ast_id = self.source_ast_id_map.ast_id(strukt);
         let res = Struct { name, visibility, generic_params, fields, ast_id };
@@ -212,7 +212,7 @@ impl<'a> Ctx<'a> {
     fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
         let visibility = self.lower_visibility(union);
         let name = union.name()?.as_name();
-        let generic_params = self.lower_generic_params(GenericsOwner::Union, union);
+        let generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
         let fields = match union.record_field_list() {
             Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
             None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
@@ -225,7 +225,7 @@ impl<'a> Ctx<'a> {
     fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
         let visibility = self.lower_visibility(enum_);
         let name = enum_.name()?.as_name();
-        let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
+        let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
         let variants = match &enum_.variant_list() {
             Some(variant_list) => self.lower_variants(variant_list),
             None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()),
@@ -373,8 +373,7 @@ impl<'a> Ctx<'a> {
             ast_id,
             flags,
         };
-        res.explicit_generic_params =
-            self.lower_generic_params(GenericsOwner::Function(&res), func);
+        res.explicit_generic_params = self.lower_generic_params(HasImplicitSelf::No, func);
 
         Some(id(self.data().functions.alloc(res)))
     }
@@ -387,7 +386,7 @@ impl<'a> Ctx<'a> {
         let type_ref = type_alias.ty().map(|it| self.lower_type_ref(&it));
         let visibility = self.lower_visibility(type_alias);
         let bounds = self.lower_type_bounds(type_alias);
-        let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias);
+        let generic_params = self.lower_generic_params(HasImplicitSelf::No, type_alias);
         let ast_id = self.source_ast_id_map.ast_id(type_alias);
         let res = TypeAlias {
             name,
@@ -443,7 +442,8 @@ impl<'a> Ctx<'a> {
     fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> {
         let name = trait_def.name()?.as_name();
         let visibility = self.lower_visibility(trait_def);
-        let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def);
+        let generic_params =
+            self.lower_generic_params(HasImplicitSelf::Yes(trait_def.type_bound_list()), trait_def);
         let is_auto = trait_def.auto_token().is_some();
         let is_unsafe = trait_def.unsafe_token().is_some();
         let items = trait_def.assoc_item_list().map(|list| {
@@ -463,7 +463,9 @@ impl<'a> Ctx<'a> {
     }
 
     fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
-        let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def);
+        // Note that trait impls don't get implicit `Self` unlike traits, because here they are a
+        // type alias rather than a type parameter, so this is handled by the resolver.
+        let generic_params = self.lower_generic_params(HasImplicitSelf::No, impl_def);
         // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
         // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
         // equals itself.
@@ -567,42 +569,29 @@ impl<'a> Ctx<'a> {
 
     fn lower_generic_params(
         &mut self,
-        owner: GenericsOwner<'_>,
+        has_implicit_self: HasImplicitSelf,
         node: &dyn ast::HasGenericParams,
     ) -> Interned<GenericParams> {
         let mut generics = GenericParams::default();
-        match owner {
-            GenericsOwner::Function(_)
-            | GenericsOwner::Struct
-            | GenericsOwner::Enum
-            | GenericsOwner::Union
-            | GenericsOwner::TypeAlias => {
-                generics.fill(&self.body_ctx, node);
-            }
-            GenericsOwner::Trait(trait_def) => {
-                // traits get the Self type as an implicit first type parameter
-                generics.type_or_consts.alloc(
-                    TypeParamData {
-                        name: Some(name![Self]),
-                        default: None,
-                        provenance: TypeParamProvenance::TraitSelf,
-                    }
-                    .into(),
-                );
-                // add super traits as bounds on Self
-                // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
-                let self_param = TypeRef::Path(name![Self].into());
-                generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param));
-                generics.fill(&self.body_ctx, node);
-            }
-            GenericsOwner::Impl => {
-                // Note that we don't add `Self` here: in `impl`s, `Self` is not a
-                // type-parameter, but rather is a type-alias for impl's target
-                // type, so this is handled by the resolver.
-                generics.fill(&self.body_ctx, node);
-            }
+
+        if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
+            // Traits and trait aliases get the Self type as an implicit first type parameter.
+            generics.type_or_consts.alloc(
+                TypeParamData {
+                    name: Some(name![Self]),
+                    default: None,
+                    provenance: TypeParamProvenance::TraitSelf,
+                }
+                .into(),
+            );
+            // add super traits as bounds on Self
+            // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
+            let self_param = TypeRef::Path(name![Self].into());
+            generics.fill_bounds(&self.body_ctx, bounds, Either::Left(self_param));
         }
 
+        generics.fill(&self.body_ctx, node);
+
         generics.shrink_to_fit();
         Interned::new(generics)
     }
@@ -674,17 +663,10 @@ fn desugar_future_path(orig: TypeRef) -> Path {
     Path::from_known_path(path, generic_args)
 }
 
-enum GenericsOwner<'a> {
-    /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
-    /// position.
-    Function(&'a Function),
-    Struct,
-    Enum,
-    Union,
-    /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
-    Trait(&'a ast::Trait),
-    TypeAlias,
-    Impl,
+enum HasImplicitSelf {
+    /// Inner list is a type bound list for the implicit `Self`.
+    Yes(Option<ast::TypeBoundList>),
+    No,
 }
 
 fn lower_abi(abi: ast::Abi) -> Interned<str> {