Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_tree/lower.rs')
-rw-r--r--crates/hir-def/src/item_tree/lower.rs137
1 files changed, 73 insertions, 64 deletions
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index d4d3c5ef19..77b186f8e3 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},
@@ -90,6 +90,13 @@ impl<'a> Ctx<'a> {
_ => None,
})
.collect();
+ if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() {
+ if let Some(call) = expr.macro_call() {
+ if let Some(mod_item) = self.lower_mod_item(&call.into()) {
+ self.tree.top_level.push(mod_item);
+ }
+ }
+ }
self.tree
}
@@ -110,6 +117,7 @@ impl<'a> Ctx<'a> {
ast::Item::Const(ast) => self.lower_const(ast).into(),
ast::Item::Module(ast) => self.lower_module(ast)?.into(),
ast::Item::Trait(ast) => self.lower_trait(ast)?.into(),
+ ast::Item::TraitAlias(ast) => self.lower_trait_alias(ast)?.into(),
ast::Item::Impl(ast) => self.lower_impl(ast)?.into(),
ast::Item::Use(ast) => self.lower_use(ast)?.into(),
ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast)?.into(),
@@ -147,7 +155,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 };
@@ -211,7 +219,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())),
@@ -224,7 +232,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()),
@@ -372,8 +380,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)))
}
@@ -386,7 +393,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,
@@ -442,27 +449,49 @@ 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| {
- list.assoc_items()
- .filter_map(|item| {
- let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
- self.lower_assoc_item(&item).map(|item| {
- self.add_attrs(ModItem::from(item).into(), attrs);
- item
- })
- })
- .collect()
- });
let ast_id = self.source_ast_id_map.ast_id(trait_def);
- let res = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id };
- Some(id(self.data().traits.alloc(res)))
+
+ let items = trait_def
+ .assoc_item_list()
+ .into_iter()
+ .flat_map(|list| list.assoc_items())
+ .filter_map(|item| {
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
+ self.lower_assoc_item(&item).map(|item| {
+ self.add_attrs(ModItem::from(item).into(), attrs);
+ item
+ })
+ })
+ .collect();
+
+ let def = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id };
+ Some(id(self.data().traits.alloc(def)))
+ }
+
+ fn lower_trait_alias(
+ &mut self,
+ trait_alias_def: &ast::TraitAlias,
+ ) -> Option<FileItemTreeId<TraitAlias>> {
+ let name = trait_alias_def.name()?.as_name();
+ let visibility = self.lower_visibility(trait_alias_def);
+ let generic_params = self.lower_generic_params(
+ HasImplicitSelf::Yes(trait_alias_def.type_bound_list()),
+ trait_alias_def,
+ );
+ let ast_id = self.source_ast_id_map.ast_id(trait_alias_def);
+
+ let alias = TraitAlias { name, visibility, generic_params, ast_id };
+ Some(id(self.data().trait_aliases.alloc(alias)))
}
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.
@@ -566,42 +595,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)
}
@@ -673,17 +689,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> {