Skip to content

Commit e2ec3a6

Browse files
committed
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.
1 parent 356d12e commit e2ec3a6

File tree

2 files changed

+45
-57
lines changed

2 files changed

+45
-57
lines changed

crates/hir-def/src/generics.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,10 @@ impl GenericParams {
207207
pub(crate) fn fill_bounds(
208208
&mut self,
209209
lower_ctx: &LowerCtx<'_>,
210-
node: &dyn ast::HasTypeBounds,
210+
type_bounds: Option<ast::TypeBoundList>,
211211
target: Either<TypeRef, LifetimeRef>,
212212
) {
213-
for bound in
214-
node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
215-
{
213+
for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
216214
self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
217215
}
218216
}
@@ -233,7 +231,11 @@ impl GenericParams {
233231
};
234232
self.type_or_consts.alloc(param.into());
235233
let type_ref = TypeRef::Path(name.into());
236-
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
234+
self.fill_bounds(
235+
lower_ctx,
236+
type_param.type_bound_list(),
237+
Either::Left(type_ref),
238+
);
237239
}
238240
ast::TypeOrConstParam::Const(const_param) => {
239241
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
@@ -255,7 +257,11 @@ impl GenericParams {
255257
let param = LifetimeParamData { name: name.clone() };
256258
self.lifetimes.alloc(param);
257259
let lifetime_ref = LifetimeRef::new_name(name);
258-
self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
260+
self.fill_bounds(
261+
lower_ctx,
262+
lifetime_param.type_bound_list(),
263+
Either::Right(lifetime_ref),
264+
);
259265
}
260266
}
261267

crates/hir-def/src/item_tree/lower.rs

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::{collections::hash_map::Entry, sync::Arc};
44

55
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
6-
use syntax::ast::{self, HasModuleItem};
6+
use syntax::ast::{self, HasModuleItem, HasTypeBounds};
77

88
use crate::{
99
generics::{GenericParams, TypeParamData, TypeParamProvenance},
@@ -148,7 +148,7 @@ impl<'a> Ctx<'a> {
148148
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
149149
let visibility = self.lower_visibility(strukt);
150150
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);
152152
let fields = self.lower_fields(&strukt.kind());
153153
let ast_id = self.source_ast_id_map.ast_id(strukt);
154154
let res = Struct { name, visibility, generic_params, fields, ast_id };
@@ -212,7 +212,7 @@ impl<'a> Ctx<'a> {
212212
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
213213
let visibility = self.lower_visibility(union);
214214
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);
216216
let fields = match union.record_field_list() {
217217
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
218218
None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
@@ -225,7 +225,7 @@ impl<'a> Ctx<'a> {
225225
fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
226226
let visibility = self.lower_visibility(enum_);
227227
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_);
229229
let variants = match &enum_.variant_list() {
230230
Some(variant_list) => self.lower_variants(variant_list),
231231
None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()),
@@ -373,8 +373,7 @@ impl<'a> Ctx<'a> {
373373
ast_id,
374374
flags,
375375
};
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);
378377

379378
Some(id(self.data().functions.alloc(res)))
380379
}
@@ -387,7 +386,7 @@ impl<'a> Ctx<'a> {
387386
let type_ref = type_alias.ty().map(|it| self.lower_type_ref(&it));
388387
let visibility = self.lower_visibility(type_alias);
389388
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);
391390
let ast_id = self.source_ast_id_map.ast_id(type_alias);
392391
let res = TypeAlias {
393392
name,
@@ -443,7 +442,8 @@ impl<'a> Ctx<'a> {
443442
fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> {
444443
let name = trait_def.name()?.as_name();
445444
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);
447447
let is_auto = trait_def.auto_token().is_some();
448448
let is_unsafe = trait_def.unsafe_token().is_some();
449449
let items = trait_def.assoc_item_list().map(|list| {
@@ -463,7 +463,9 @@ impl<'a> Ctx<'a> {
463463
}
464464

465465
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);
467469
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
468470
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
469471
// equals itself.
@@ -567,42 +569,29 @@ impl<'a> Ctx<'a> {
567569

568570
fn lower_generic_params(
569571
&mut self,
570-
owner: GenericsOwner<'_>,
572+
has_implicit_self: HasImplicitSelf,
571573
node: &dyn ast::HasGenericParams,
572574
) -> Interned<GenericParams> {
573575
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));
604591
}
605592

593+
generics.fill(&self.body_ctx, node);
594+
606595
generics.shrink_to_fit();
607596
Interned::new(generics)
608597
}
@@ -674,17 +663,10 @@ fn desugar_future_path(orig: TypeRef) -> Path {
674663
Path::from_known_path(path, generic_args)
675664
}
676665

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,
688670
}
689671

690672
fn lower_abi(abi: ast::Abi) -> Interned<str> {

0 commit comments

Comments
 (0)