From 2e7d2c2d045e2a66a4e309cbb71a3264004f8678 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sat, 4 Mar 2023 00:23:56 +0900 Subject: [PATCH 1/5] Parse trait alias as a distinct AST type --- crates/hir-def/src/item_tree/lower.rs | 1 + crates/parser/src/grammar/items/traits.rs | 2 +- crates/parser/src/syntax_kind/generated.rs | 1 + .../parser/inline/ok/0151_trait_alias.rast | 2 +- .../ok/0177_trait_alias_where_clause.rast | 4 +- crates/syntax/rust.ungram | 10 +++-- crates/syntax/src/ast.rs | 3 +- crates/syntax/src/ast/generated/nodes.rs | 43 +++++++++++++++++- crates/syntax/src/ast/node_ext.rs | 45 +++++++++++++++++++ crates/syntax/src/tests/ast_src.rs | 1 + crates/syntax/src/tests/sourcegen_ast.rs | 1 + 11 files changed, 103 insertions(+), 10 deletions(-) diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index d4d3c5ef19a60..bd7c556ae69db 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -110,6 +110,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(_) => return None, 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(), diff --git a/crates/parser/src/grammar/items/traits.rs b/crates/parser/src/grammar/items/traits.rs index c982e2d564c90..a8a1ccb15e6c2 100644 --- a/crates/parser/src/grammar/items/traits.rs +++ b/crates/parser/src/grammar/items/traits.rs @@ -20,7 +20,7 @@ pub(super) fn trait_(p: &mut Parser<'_>, m: Marker) { // trait Z = where Self: T; generic_params::opt_where_clause(p); p.expect(T![;]); - m.complete(p, TRAIT); + m.complete(p, TRAIT_ALIAS); return; } diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index 52b3fc23d59ca..cd87b304a2fb3 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs @@ -135,6 +135,7 @@ pub enum SyntaxKind { STATIC, CONST, TRAIT, + TRAIT_ALIAS, IMPL, TYPE_ALIAS, MACRO_CALL, diff --git a/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rast b/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rast index 2ef66484ae48f..c45f870898007 100644 --- a/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rast +++ b/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rast @@ -1,5 +1,5 @@ SOURCE_FILE - TRAIT + TRAIT_ALIAS TRAIT_KW "trait" WHITESPACE " " NAME diff --git a/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rast b/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rast index 4443d9d142630..8f678247731dc 100644 --- a/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rast +++ b/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rast @@ -1,5 +1,5 @@ SOURCE_FILE - TRAIT + TRAIT_ALIAS TRAIT_KW "trait" WHITESPACE " " NAME @@ -50,7 +50,7 @@ SOURCE_FILE IDENT "Copy" SEMICOLON ";" WHITESPACE "\n" - TRAIT + TRAIT_ALIAS TRAIT_KW "trait" WHITESPACE " " NAME diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 36ad5fddfd0c5..548b5ba8b8b6d 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -97,6 +97,7 @@ Item = | Static | Struct | Trait +| TraitAlias | TypeAlias | Union | Use @@ -240,10 +241,11 @@ Trait = Attr* Visibility? 'unsafe'? 'auto'? 'trait' Name GenericParamList? - ( - (':' TypeBoundList?)? WhereClause? AssocItemList - | '=' TypeBoundList? WhereClause? ';' - ) + (':' TypeBoundList?)? WhereClause? AssocItemList + +TraitAlias = + Attr* Visibility? + 'trait' Name GenericParamList? '=' TypeBoundList? WhereClause? ';' AssocItemList = '{' Attr* AssocItem* '}' diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 679536fe27af1..745f2e14e95c8 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -25,7 +25,8 @@ pub use self::{ generated::{nodes::*, tokens::*}, node_ext::{ AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, - SlicePatComponents, StructKind, TypeBoundKind, TypeOrConstParam, VisibilityKind, + SlicePatComponents, StructKind, TraitOrAlias, TypeBoundKind, TypeOrConstParam, + VisibilityKind, }, operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix}, diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 642a3bfc35d13..fe324845360d7 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -407,7 +407,21 @@ impl Trait { pub fn auto_token(&self) -> Option { support::token(&self.syntax, T![auto]) } pub fn trait_token(&self) -> Option { support::token(&self.syntax, T![trait]) } pub fn assoc_item_list(&self) -> Option { support::child(&self.syntax) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TraitAlias { + pub(crate) syntax: SyntaxNode, +} +impl ast::HasAttrs for TraitAlias {} +impl ast::HasName for TraitAlias {} +impl ast::HasVisibility for TraitAlias {} +impl ast::HasGenericParams for TraitAlias {} +impl ast::HasDocComments for TraitAlias {} +impl TraitAlias { + pub fn trait_token(&self) -> Option { support::token(&self.syntax, T![trait]) } pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } + pub fn type_bound_list(&self) -> Option { support::child(&self.syntax) } pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } @@ -1573,6 +1587,7 @@ pub enum Item { Static(Static), Struct(Struct), Trait(Trait), + TraitAlias(TraitAlias), TypeAlias(TypeAlias), Union(Union), Use(Use), @@ -2058,6 +2073,17 @@ impl AstNode for Trait { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for TraitAlias { + fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_ALIAS } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for TypeAlias { fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS } fn cast(syntax: SyntaxNode) -> Option { @@ -3570,6 +3596,9 @@ impl From for Item { impl From for Item { fn from(node: Trait) -> Item { Item::Trait(node) } } +impl From for Item { + fn from(node: TraitAlias) -> Item { Item::TraitAlias(node) } +} impl From for Item { fn from(node: TypeAlias) -> Item { Item::TypeAlias(node) } } @@ -3596,6 +3625,7 @@ impl AstNode for Item { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -3616,6 +3646,7 @@ impl AstNode for Item { STATIC => Item::Static(Static { syntax }), STRUCT => Item::Struct(Struct { syntax }), TRAIT => Item::Trait(Trait { syntax }), + TRAIT_ALIAS => Item::TraitAlias(TraitAlias { syntax }), TYPE_ALIAS => Item::TypeAlias(TypeAlias { syntax }), UNION => Item::Union(Union { syntax }), USE => Item::Use(Use { syntax }), @@ -3638,6 +3669,7 @@ impl AstNode for Item { Item::Static(it) => &it.syntax, Item::Struct(it) => &it.syntax, Item::Trait(it) => &it.syntax, + Item::TraitAlias(it) => &it.syntax, Item::TypeAlias(it) => &it.syntax, Item::Union(it) => &it.syntax, Item::Use(it) => &it.syntax, @@ -3950,6 +3982,7 @@ impl AstNode for AnyHasAttrs { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -4035,6 +4068,7 @@ impl AstNode for AnyHasDocComments { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -4056,7 +4090,7 @@ impl AnyHasGenericParams { } impl AstNode for AnyHasGenericParams { fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, ENUM | FN | IMPL | STRUCT | TRAIT | TYPE_ALIAS | UNION) + matches!(kind, ENUM | FN | IMPL | STRUCT | TRAIT | TRAIT_ALIAS | TYPE_ALIAS | UNION) } fn cast(syntax: SyntaxNode) -> Option { Self::can_cast(syntax.kind()).then_some(AnyHasGenericParams { syntax }) @@ -4108,6 +4142,7 @@ impl AstNode for AnyHasName { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | RENAME @@ -4163,6 +4198,7 @@ impl AstNode for AnyHasVisibility { | STATIC | STRUCT | TRAIT + | TRAIT_ALIAS | TYPE_ALIAS | UNION | USE @@ -4391,6 +4427,11 @@ impl std::fmt::Display for Trait { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for TraitAlias { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for TypeAlias { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index fe82aa907222f..301fbcebf1c88 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -680,6 +680,51 @@ impl TypeOrConstParam { } } +#[derive(Debug, Clone)] +pub enum TraitOrAlias { + Trait(ast::Trait), + TraitAlias(ast::TraitAlias), +} + +impl TraitOrAlias { + pub fn name(&self) -> Option { + match self { + TraitOrAlias::Trait(x) => x.name(), + TraitOrAlias::TraitAlias(x) => x.name(), + } + } +} + +impl AstNode for TraitOrAlias { + fn can_cast(kind: SyntaxKind) -> bool + where + Self: Sized, + { + matches!(kind, SyntaxKind::TRAIT | SyntaxKind::TRAIT_ALIAS) + } + + fn cast(syntax: SyntaxNode) -> Option + where + Self: Sized, + { + let res = match syntax.kind() { + SyntaxKind::TRAIT => TraitOrAlias::Trait(ast::Trait { syntax }), + SyntaxKind::TRAIT_ALIAS => TraitOrAlias::TraitAlias(ast::TraitAlias { syntax }), + _ => return None, + }; + Some(res) + } + + fn syntax(&self) -> &SyntaxNode { + match self { + TraitOrAlias::Trait(it) => it.syntax(), + TraitOrAlias::TraitAlias(it) => it.syntax(), + } + } +} + +impl HasAttrs for TraitOrAlias {} + pub enum VisibilityKind { In(ast::Path), PubCrate, diff --git a/crates/syntax/src/tests/ast_src.rs b/crates/syntax/src/tests/ast_src.rs index 3ff6e03006b5a..ccce71966ff88 100644 --- a/crates/syntax/src/tests/ast_src.rs +++ b/crates/syntax/src/tests/ast_src.rs @@ -86,6 +86,7 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc { "STATIC", "CONST", "TRAIT", + "TRAIT_ALIAS", "IMPL", "TYPE_ALIAS", "MACRO_CALL", diff --git a/crates/syntax/src/tests/sourcegen_ast.rs b/crates/syntax/src/tests/sourcegen_ast.rs index 03aa2c451e848..e954b58251faa 100644 --- a/crates/syntax/src/tests/sourcegen_ast.rs +++ b/crates/syntax/src/tests/sourcegen_ast.rs @@ -783,6 +783,7 @@ fn extract_struct_traits(ast: &mut AstSrc) { "Enum", "Variant", "Trait", + "TraitAlias", "Module", "Static", "Const", From 356d12eae4b8985dc933c13e9281546d532d0845 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sat, 4 Mar 2023 00:24:03 +0900 Subject: [PATCH 2/5] refactor: leverage `HasAttrs` for code brevity --- crates/hir-def/src/attr.rs | 46 +++++++------------------------ crates/syntax/src/ast.rs | 7 +++++ crates/syntax/src/ast/node_ext.rs | 30 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index fcd92ad338583..79c2c188ff122 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -315,26 +315,14 @@ impl AttrsWithOwner { let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db.upcast(), - src.with_value(src.value[it.local_id()].as_ref().either( - |it| match it { - ast::TypeOrConstParam::Type(it) => it as _, - ast::TypeOrConstParam::Const(it) => it as _, - }, - |it| it as _, - )), + src.with_value(&src.value[it.local_id()]), ) } GenericParamId::TypeParamId(it) => { let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db.upcast(), - src.with_value(src.value[it.local_id()].as_ref().either( - |it| match it { - ast::TypeOrConstParam::Type(it) => it as _, - ast::TypeOrConstParam::Const(it) => it as _, - }, - |it| it as _, - )), + src.with_value(&src.value[it.local_id()]), ) } GenericParamId::LifetimeParamId(it) => { @@ -412,28 +400,14 @@ impl AttrsWithOwner { }, AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::GenericParamId(id) => match id { - GenericParamId::ConstParamId(id) => { - id.parent().child_source(db).map(|source| match &source[id.local_id()] { - Either::Left(ast::TypeOrConstParam::Type(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Left(ast::TypeOrConstParam::Const(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), - }) - } - GenericParamId::TypeParamId(id) => { - id.parent().child_source(db).map(|source| match &source[id.local_id()] { - Either::Left(ast::TypeOrConstParam::Type(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Left(ast::TypeOrConstParam::Const(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), - }) - } + GenericParamId::ConstParamId(id) => id + .parent() + .child_source(db) + .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())), + GenericParamId::TypeParamId(id) => id + .parent() + .child_source(db) + .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())), GenericParamId::LifetimeParamId(id) => id .parent .child_source(db) diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 745f2e14e95c8..1e691befff62a 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -129,6 +129,13 @@ where } } +impl HasAttrs for Either +where + L: HasAttrs, + R: HasAttrs, +{ +} + mod support { use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken}; diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 301fbcebf1c88..15bd5ab3c7299 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -680,6 +680,36 @@ impl TypeOrConstParam { } } +impl AstNode for TypeOrConstParam { + fn can_cast(kind: SyntaxKind) -> bool + where + Self: Sized, + { + matches!(kind, SyntaxKind::TYPE_PARAM | SyntaxKind::CONST_PARAM) + } + + fn cast(syntax: SyntaxNode) -> Option + where + Self: Sized, + { + let res = match syntax.kind() { + SyntaxKind::TYPE_PARAM => TypeOrConstParam::Type(ast::TypeParam { syntax }), + SyntaxKind::CONST_PARAM => TypeOrConstParam::Const(ast::ConstParam { syntax }), + _ => return None, + }; + Some(res) + } + + fn syntax(&self) -> &SyntaxNode { + match self { + TypeOrConstParam::Type(it) => it.syntax(), + TypeOrConstParam::Const(it) => it.syntax(), + } + } +} + +impl HasAttrs for TypeOrConstParam {} + #[derive(Debug, Clone)] pub enum TraitOrAlias { Trait(ast::Trait), From e2ec3a6561d73cc4b530c69a9bafc30c4f34b1ec Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sat, 4 Mar 2023 00:24:05 +0900 Subject: [PATCH 3/5] 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. --- crates/hir-def/src/generics.rs | 18 ++++-- crates/hir-def/src/item_tree/lower.rs | 84 +++++++++++---------------- 2 files changed, 45 insertions(+), 57 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index b2ab0c30e0370..5a0aa19338801 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, target: Either, ) { - 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 bd7c556ae69db..b64b4d11e373d 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> { 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> { 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> { 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> { 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> { - 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 { 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), + No, } fn lower_abi(abi: ast::Abi) -> Interned { From 29c957f97388afd2a21ec3364ea4ce8c269cfbcd Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sat, 4 Mar 2023 00:24:07 +0900 Subject: [PATCH 4/5] Lower and handle trait aliases in HIR --- crates/hir-def/src/attr.rs | 2 + crates/hir-def/src/child_by_source.rs | 3 +- crates/hir-def/src/data.rs | 37 +++++++++------ crates/hir-def/src/db.rs | 11 +++-- crates/hir-def/src/generics.rs | 26 +++++++--- crates/hir-def/src/import_map.rs | 2 + crates/hir-def/src/item_scope.rs | 1 + crates/hir-def/src/item_tree.rs | 17 ++++++- crates/hir-def/src/item_tree/lower.rs | 47 +++++++++++++------ crates/hir-def/src/item_tree/pretty.rs | 29 ++++++------ crates/hir-def/src/keys.rs | 5 +- crates/hir-def/src/lib.rs | 15 +++++- crates/hir-def/src/nameres/collector.rs | 17 ++++++- .../hir-def/src/nameres/tests/incremental.rs | 1 + crates/hir-def/src/resolver.rs | 16 ++++++- crates/hir-ty/src/diagnostics/decl_check.rs | 1 + crates/hir-ty/src/infer.rs | 5 +- crates/hir-ty/src/lower.rs | 6 +++ crates/hir-ty/src/utils.rs | 5 +- crates/hir/src/attrs.rs | 5 +- crates/hir/src/display.rs | 20 +++++++- crates/hir/src/from_id.rs | 5 ++ crates/hir/src/has_source.rs | 10 +++- crates/hir/src/lib.rs | 39 ++++++++++++++- crates/hir/src/semantics.rs | 5 +- crates/hir/src/semantics/source_to_def.rs | 17 ++++++- crates/hir/src/source_analyzer.rs | 4 +- crates/hir/src/symbols.rs | 4 ++ .../src/handlers/fix_visibility.rs | 4 ++ crates/ide-completion/src/completions/type.rs | 4 +- crates/ide-completion/src/context.rs | 1 + crates/ide-completion/src/item.rs | 3 +- crates/ide-completion/src/render.rs | 3 ++ crates/ide-db/src/active_parameter.rs | 1 + crates/ide-db/src/defs.rs | 12 ++++- crates/ide-db/src/lib.rs | 2 + crates/ide-db/src/rename.rs | 1 + crates/ide-db/src/search.rs | 1 + crates/ide/src/doc_links.rs | 2 + crates/ide/src/hover/render.rs | 1 + crates/ide/src/moniker.rs | 3 ++ crates/ide/src/navigation_target.rs | 5 ++ crates/ide/src/signature_help.rs | 4 ++ .../ide/src/syntax_highlighting/highlight.rs | 1 + crates/ide/src/syntax_highlighting/inject.rs | 1 + crates/ide/src/syntax_highlighting/tags.rs | 1 + crates/rust-analyzer/src/to_proto.rs | 4 +- 47 files changed, 334 insertions(+), 75 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 79c2c188ff122..200072c172ebe 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -300,6 +300,7 @@ impl AttrsWithOwner { AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), }, AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), + AttrDefId::TraitAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::MacroId(it) => match it { MacroId::Macro2Id(it) => attrs_from_item_tree(it.lookup(db).id, db), MacroId::MacroRulesId(it) => attrs_from_item_tree(it.lookup(db).id, db), @@ -392,6 +393,7 @@ impl AttrsWithOwner { AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), + AttrDefId::TraitAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::MacroId(id) => match id { MacroId::Macro2Id(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index 19d2fe956f098..68b57acca2adc 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -1,7 +1,7 @@ //! When *constructing* `hir`, we start at some parent syntax node and recursively //! lower the children. //! -//! This modules allows one to go in the opposite direction: start with a syntax +//! This module allows one to go in the opposite direction: start with a syntax //! node for a *child*, and get its hir. use either::Either; @@ -145,6 +145,7 @@ impl ChildBySource for ItemScope { ModuleDefId::StaticId(id) => insert!(map[keys::STATIC].insert(id)), ModuleDefId::TypeAliasId(id) => insert!(map[keys::TYPE_ALIAS].insert(id)), ModuleDefId::TraitId(id) => insert!(map[keys::TRAIT].insert(id)), + ModuleDefId::TraitAliasId(id) => insert!(map[keys::TRAIT_ALIAS].insert(id)), ModuleDefId::AdtId(adt) => match adt { AdtId::StructId(id) => insert!(map[keys::STRUCT].insert(id)), AdtId::UnionId(id) => insert!(map[keys::UNION].insert(id)), diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index c3c1dfd39ac0b..ee6e269fe5586 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -22,7 +22,7 @@ use crate::{ visibility::RawVisibility, AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, Intern, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ModuleId, ProcMacroId, - StaticId, TraitId, TypeAliasId, TypeAliasLoc, + StaticId, TraitAliasId, TraitId, TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -245,19 +245,11 @@ impl TraitData { attrs.by_key("rustc_skip_array_during_method_dispatch").exists(); let rustc_has_incoherent_inherent_impls = attrs.by_key("rustc_has_incoherent_inherent_impls").exists(); - let (items, attribute_calls, diagnostics) = match &tr_def.items { - Some(items) => { - let mut collector = AssocItemCollector::new( - db, - module_id, - tree_id.file_id(), - ItemContainerId::TraitId(tr), - ); - collector.collect(&item_tree, tree_id.tree_id(), items); - collector.finish() - } - None => Default::default(), - }; + let mut collector = + AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); + collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); + let (items, attribute_calls, diagnostics) = collector.finish(); + ( Arc::new(TraitData { name, @@ -299,6 +291,23 @@ impl TraitData { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TraitAliasData { + pub name: Name, + pub visibility: RawVisibility, +} + +impl TraitAliasData { + pub(crate) fn trait_alias_query(db: &dyn DefDatabase, id: TraitAliasId) -> Arc { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let alias = &item_tree[loc.id.value]; + let visibility = item_tree[alias.visibility].clone(); + + Arc::new(TraitAliasData { name: alias.name.clone(), visibility }) + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct ImplData { pub target_trait: Option>, diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index b23427a73b345..270cfa06e5815 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -14,7 +14,7 @@ use crate::{ body::{scope::ExprScopes, Body, BodySourceMap}, data::{ ConstData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData, - TraitData, TypeAliasData, + TraitAliasData, TraitData, TypeAliasData, }, generics::GenericParams, import_map::ImportMap, @@ -25,8 +25,8 @@ use crate::{ AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc, - StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, - UnionId, UnionLoc, VariantId, + StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, + TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -46,6 +46,8 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_trait(&self, loc: TraitLoc) -> TraitId; #[salsa::interned] + fn intern_trait_alias(&self, loc: TraitAliasLoc) -> TraitAliasId; + #[salsa::interned] fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; #[salsa::interned] fn intern_impl(&self, loc: ImplLoc) -> ImplId; @@ -125,6 +127,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)] fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc, Arc<[DefDiagnostic]>); + #[salsa::invoke(TraitAliasData::trait_alias_query)] + fn trait_alias_data(&self, e: TraitAliasId) -> Arc; + #[salsa::invoke(TypeAliasData::type_alias_data_query)] fn type_alias_data(&self, e: TypeAliasId) -> Arc; diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 5a0aa19338801..e4912fa8a64a4 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -187,6 +187,7 @@ impl GenericParams { GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id), GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id), GenericDefId::TraitId(id) => id_to_generics!(id), + GenericDefId::TraitAliasId(id) => id_to_generics!(id), GenericDefId::TypeAliasId(id) => id_to_generics!(id), GenericDefId::ImplId(id) => id_to_generics!(id), GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { @@ -427,6 +428,10 @@ fn file_id_and_params_of( let src = it.lookup(db).source(db); (src.file_id, src.value.generic_param_list()) } + GenericDefId::TraitAliasId(it) => { + let src = it.lookup(db).source(db); + (src.file_id, src.value.generic_param_list()) + } GenericDefId::TypeAliasId(it) => { let src = it.lookup(db).source(db); (src.file_id, src.value.generic_param_list()) @@ -441,7 +446,7 @@ fn file_id_and_params_of( } impl HasChildSource for GenericDefId { - type Value = Either; + type Value = Either; fn child_source( &self, db: &dyn DefDatabase, @@ -453,11 +458,20 @@ impl HasChildSource for GenericDefId { let mut params = ArenaMap::default(); - // For traits the first type index is `Self`, we need to add it before the other params. - if let GenericDefId::TraitId(id) = *self { - let trait_ref = id.lookup(db).source(db).value; - let idx = idx_iter.next().unwrap(); - params.insert(idx, Either::Right(trait_ref)); + // For traits and trait aliases the first type index is `Self`, we need to add it before + // the other params. + match *self { + GenericDefId::TraitId(id) => { + let trait_ref = id.lookup(db).source(db).value; + let idx = idx_iter.next().unwrap(); + params.insert(idx, Either::Right(ast::TraitOrAlias::Trait(trait_ref))); + } + GenericDefId::TraitAliasId(id) => { + let alias = id.lookup(db).source(db).value; + let idx = idx_iter.next().unwrap(); + params.insert(idx, Either::Right(ast::TraitOrAlias::TraitAlias(alias))); + } + _ => {} } if let Some(generic_params_list) = generic_params_list { diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 63e92df0e7204..07a68d1598c59 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -268,6 +268,7 @@ pub enum ImportKind { Const, Static, Trait, + TraitAlias, TypeAlias, BuiltinType, AssociatedItem, @@ -463,6 +464,7 @@ fn item_import_kind(item: ItemInNs) -> Option { ModuleDefId::ConstId(_) => ImportKind::Const, ModuleDefId::StaticId(_) => ImportKind::Static, ModuleDefId::TraitId(_) => ImportKind::Trait, + ModuleDefId::TraitAliasId(_) => ImportKind::TraitAlias, ModuleDefId::TypeAliasId(_) => ImportKind::TypeAlias, ModuleDefId::BuiltinType(_) => ImportKind::BuiltinType, ModuleDefId::MacroId(_) => ImportKind::Macro, diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 53a4173ff4230..991e447033fe7 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -431,6 +431,7 @@ impl PerNs { ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), ModuleDefId::TraitId(_) => PerNs::types(def, v), + ModuleDefId::TraitAliasId(_) => PerNs::types(def, v), ModuleDefId::TypeAliasId(_) => PerNs::types(def, v), ModuleDefId::BuiltinType(_) => PerNs::types(def, v), ModuleDefId::MacroId(mac) => PerNs::macros(mac, v), diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 19d01630ef088..9da5b2d47c877 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -204,6 +204,7 @@ impl ItemTree { consts, statics, traits, + trait_aliases, impls, type_aliases, mods, @@ -226,6 +227,7 @@ impl ItemTree { consts.shrink_to_fit(); statics.shrink_to_fit(); traits.shrink_to_fit(); + trait_aliases.shrink_to_fit(); impls.shrink_to_fit(); type_aliases.shrink_to_fit(); mods.shrink_to_fit(); @@ -276,6 +278,7 @@ struct ItemTreeData { consts: Arena, statics: Arena, traits: Arena, + trait_aliases: Arena, impls: Arena, type_aliases: Arena, mods: Arena, @@ -496,6 +499,7 @@ mod_items! { Const in consts -> ast::Const, Static in statics -> ast::Static, Trait in traits -> ast::Trait, + TraitAlias in trait_aliases -> ast::TraitAlias, Impl in impls -> ast::Impl, TypeAlias in type_aliases -> ast::TypeAlias, Mod in mods -> ast::Module, @@ -672,11 +676,18 @@ pub struct Trait { pub generic_params: Interned, pub is_auto: bool, pub is_unsafe: bool, - /// This is [`None`] if this Trait is a trait alias. - pub items: Option>, + pub items: Box<[AssocItem]>, pub ast_id: FileAstId, } +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct TraitAlias { + pub name: Name, + pub visibility: RawVisibilityId, + pub generic_params: Interned, + pub ast_id: FileAstId, +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Impl { pub generic_params: Interned, @@ -872,6 +883,7 @@ impl ModItem { | ModItem::Enum(_) | ModItem::Static(_) | ModItem::Trait(_) + | ModItem::TraitAlias(_) | ModItem::Impl(_) | ModItem::Mod(_) | ModItem::MacroRules(_) @@ -899,6 +911,7 @@ impl ModItem { ModItem::Const(it) => tree[it.index].ast_id().upcast(), ModItem::Static(it) => tree[it.index].ast_id().upcast(), ModItem::Trait(it) => tree[it.index].ast_id().upcast(), + ModItem::TraitAlias(it) => tree[it.index].ast_id().upcast(), ModItem::Impl(it) => tree[it.index].ast_id().upcast(), ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(), ModItem::Mod(it) => tree[it.index].ast_id().upcast(), diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index b64b4d11e373d..495a8878c3343 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -110,7 +110,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(_) => return None, + 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(), @@ -446,20 +446,39 @@ impl<'a> Ctx<'a> { 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> { + 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> { diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 8f230b87d0101..5f29997964b9c 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -374,23 +374,24 @@ impl<'a> Printer<'a> { } w!(self, "trait {}", name); self.print_generic_params(generic_params); - match items { - Some(items) => { - self.print_where_clause_and_opening_brace(generic_params); - self.indented(|this| { - for item in &**items { - this.print_mod_item((*item).into()); - } - }); - } - None => { - w!(self, " = "); - // FIXME: Print the aliased traits - self.print_where_clause_and_opening_brace(generic_params); + self.print_where_clause_and_opening_brace(generic_params); + self.indented(|this| { + for item in &**items { + this.print_mod_item((*item).into()); } - } + }); wln!(self, "}}"); } + ModItem::TraitAlias(it) => { + let TraitAlias { name, visibility, generic_params, ast_id: _ } = &self.tree[it]; + self.print_visibility(*visibility); + w!(self, "trait {}", name); + self.print_generic_params(generic_params); + w!(self, " = "); + self.print_where_clause(generic_params); + w!(self, ";"); + wln!(self); + } ModItem::Impl(it) => { let Impl { target_trait, self_ty, is_negative, items, generic_params, ast_id: _ } = &self.tree[it]; diff --git a/crates/hir-def/src/keys.rs b/crates/hir-def/src/keys.rs index 72beec8186c1f..f30be6b64e3de 100644 --- a/crates/hir-def/src/keys.rs +++ b/crates/hir-def/src/keys.rs @@ -9,8 +9,8 @@ use syntax::{ast, AstNode, AstPtr}; use crate::{ dyn_map::{DynMap, Policy}, ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id, - MacroRulesId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, - UnionId, + MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, + TypeOrConstParamId, UnionId, }; pub type Key = crate::dyn_map::Key>; @@ -21,6 +21,7 @@ pub const STATIC: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const IMPL: Key = Key::new(); pub const TRAIT: Key = Key::new(); +pub const TRAIT_ALIAS: Key = Key::new(); pub const STRUCT: Key = Key::new(); pub const UNION: Key = Key::new(); pub const ENUM: Key = Key::new(); diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 2aab1ccd914c1..8c2e93f090597 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -86,7 +86,7 @@ use crate::{ builtin_type::BuiltinType, item_tree::{ Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem, - Static, Struct, Trait, TypeAlias, Union, + Static, Struct, Trait, TraitAlias, TypeAlias, Union, }, }; @@ -261,6 +261,11 @@ pub struct TraitId(salsa::InternId); pub type TraitLoc = ItemLoc; impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TraitAliasId(salsa::InternId); +pub type TraitAliasLoc = ItemLoc; +impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAliasId(salsa::InternId); type TypeAliasLoc = AssocItemLoc; @@ -453,6 +458,7 @@ pub enum ModuleDefId { ConstId(ConstId), StaticId(StaticId), TraitId(TraitId), + TraitAliasId(TraitAliasId), TypeAliasId(TypeAliasId), BuiltinType(BuiltinType), MacroId(MacroId), @@ -466,6 +472,7 @@ impl_from!( ConstId, StaticId, TraitId, + TraitAliasId, TypeAliasId, BuiltinType for ModuleDefId @@ -516,6 +523,7 @@ pub enum GenericDefId { FunctionId(FunctionId), AdtId(AdtId), TraitId(TraitId), + TraitAliasId(TraitAliasId), TypeAliasId(TypeAliasId), ImplId(ImplId), // enum variants cannot have generics themselves, but their parent enums @@ -528,6 +536,7 @@ impl_from!( FunctionId, AdtId(StructId, EnumId, UnionId), TraitId, + TraitAliasId, TypeAliasId, ImplId, EnumVariantId, @@ -555,6 +564,7 @@ pub enum AttrDefId { StaticId(StaticId), ConstId(ConstId), TraitId(TraitId), + TraitAliasId(TraitAliasId), TypeAliasId(TypeAliasId), MacroId(MacroId), ImplId(ImplId), @@ -714,6 +724,7 @@ impl HasModule for GenericDefId { GenericDefId::FunctionId(it) => it.lookup(db).module(db), GenericDefId::AdtId(it) => it.module(db), GenericDefId::TraitId(it) => it.lookup(db).container, + GenericDefId::TraitAliasId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::ImplId(it) => it.lookup(db).container, GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, @@ -747,6 +758,7 @@ impl ModuleDefId { ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), ModuleDefId::StaticId(id) => id.lookup(db).module(db), ModuleDefId::TraitId(id) => id.lookup(db).container, + ModuleDefId::TraitAliasId(id) => id.lookup(db).container, ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), ModuleDefId::MacroId(id) => id.module(db), ModuleDefId::BuiltinType(_) => return None, @@ -765,6 +777,7 @@ impl AttrDefId { AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, AttrDefId::TraitId(it) => it.lookup(db).container.krate, + AttrDefId::TraitAliasId(it) => it.lookup(db).container.krate, AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, AttrDefId::ImplId(it) => it.lookup(db).container.krate, AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate, diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index e3704bf2164b0..70acc3442c306 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -51,7 +51,8 @@ use crate::{ AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, ExternBlockLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, - ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, + ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, + UnresolvedMacro, }; static GLOB_RECURSION_LIMIT: Limit = Limit::new(100); @@ -1709,6 +1710,20 @@ impl ModCollector<'_, '_> { false, ); } + ModItem::TraitAlias(id) => { + let it = &self.item_tree[id]; + + let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + update_def( + self.def_collector, + TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } + .intern(db) + .into(), + &it.name, + vis, + false, + ); + } ModItem::TypeAlias(id) => { let it = &self.item_tree[id]; diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs index f5190b76db058..13e6825f8210e 100644 --- a/crates/hir-def/src/nameres/tests/incremental.rs +++ b/crates/hir-def/src/nameres/tests/incremental.rs @@ -223,6 +223,7 @@ pub type Ty = (); ModuleDefId::ConstId(it) => drop(db.const_data(it)), ModuleDefId::StaticId(it) => drop(db.static_data(it)), ModuleDefId::TraitId(it) => drop(db.trait_data(it)), + ModuleDefId::TraitAliasId(it) => drop(db.trait_alias_data(it)), ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)), ModuleDefId::EnumVariantId(_) | ModuleDefId::ModuleId(_) diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 36d8b24e9c337..043d49f768fca 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -22,7 +22,8 @@ use crate::{ AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, - StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, VariantId, + StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, + VariantId, }; #[derive(Debug, Clone)] @@ -74,6 +75,7 @@ pub enum TypeNs { TypeAliasId(TypeAliasId), BuiltinType(BuiltinType), TraitId(TraitId), + TraitAliasId(TraitAliasId), // Module belong to type ns, but the resolver is used when all module paths // are fully resolved. // ModuleId(ModuleId) @@ -402,6 +404,8 @@ impl Resolver { } pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet { + // FIXME(trait_alias): Trait alias brings aliased traits in scope! Note that supertraits of + // aliased traits are NOT brought in scope (unless also aliased). let mut traits = FxHashSet::default(); for scope in self.scopes() { @@ -650,6 +654,7 @@ impl ModuleItemMap { let ty = match module_def.take_types()? { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it), ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), @@ -687,6 +692,7 @@ fn to_value_ns(per_ns: PerNs) -> Option { ModuleDefId::AdtId(AdtId::EnumId(_) | AdtId::UnionId(_)) | ModuleDefId::TraitId(_) + | ModuleDefId::TraitAliasId(_) | ModuleDefId::TypeAliasId(_) | ModuleDefId::BuiltinType(_) | ModuleDefId::MacroId(_) @@ -704,6 +710,7 @@ fn to_type_ns(per_ns: PerNs) -> Option { ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it), ModuleDefId::FunctionId(_) | ModuleDefId::ConstId(_) @@ -788,6 +795,12 @@ impl HasResolver for TraitId { } } +impl HasResolver for TraitAliasId { + fn resolver(self, db: &dyn DefDatabase) -> Resolver { + self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) + } +} + impl + Copy> HasResolver for T { fn resolver(self, db: &dyn DefDatabase) -> Resolver { let def = self.into(); @@ -867,6 +880,7 @@ impl HasResolver for GenericDefId { GenericDefId::FunctionId(inner) => inner.resolver(db), GenericDefId::AdtId(adt) => adt.resolver(db), GenericDefId::TraitId(inner) => inner.resolver(db), + GenericDefId::TraitAliasId(inner) => inner.resolver(db), GenericDefId::TypeAliasId(inner) => inner.resolver(db), GenericDefId::ImplId(inner) => inner.resolver(db), GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index f7031a8546a29..f4d1013ceb044 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -178,6 +178,7 @@ impl<'a> DeclValidator<'a> { AttrDefId::StaticId(sid) => Some(sid.lookup(self.db.upcast()).container.into()), AttrDefId::ConstId(cid) => Some(cid.lookup(self.db.upcast()).container.into()), AttrDefId::TraitId(tid) => Some(tid.lookup(self.db.upcast()).container.into()), + AttrDefId::TraitAliasId(taid) => Some(taid.lookup(self.db.upcast()).container.into()), AttrDefId::ImplId(iid) => Some(iid.lookup(self.db.upcast()).container.into()), AttrDefId::ExternBlockId(id) => Some(id.lookup(self.db.upcast()).container.into()), // These warnings should not explore macro definitions at all diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index c77a5e073757e..535e0ab115544 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -868,7 +868,10 @@ impl<'a> InferenceContext<'a> { // FIXME potentially resolve assoc type (self.err_ty(), None) } - TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => { + TypeNs::AdtId(AdtId::EnumId(_)) + | TypeNs::BuiltinType(_) + | TypeNs::TraitId(_) + | TypeNs::TraitAliasId(_) => { // FIXME diagnostic (self.err_ty(), None) } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 296c6c5b21fab..23b15087e3165 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -522,6 +522,10 @@ impl<'a> TyLoweringContext<'a> { }; return (ty, None); } + TypeNs::TraitAliasId(_) => { + // FIXME(trait_alias): Implement trait alias. + return (TyKind::Error.intern(Interner), None); + } TypeNs::GenericParam(param_id) => { let generics = generics( self.db.upcast(), @@ -877,6 +881,7 @@ impl<'a> TyLoweringContext<'a> { ) -> Option { let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path.mod_path())? { + // FIXME(trait_alias): We need to handle trait alias here. TypeNs::TraitId(tr) => tr, _ => return None, }; @@ -1442,6 +1447,7 @@ pub(crate) fn trait_environment_query( GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container), GenericDefId::AdtId(_) => None, GenericDefId::TraitId(_) => None, + GenericDefId::TraitAliasId(_) => None, GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container), GenericDefId::ImplId(_) => None, GenericDefId::EnumVariantId(_) => None, diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index f69cb6bacbd1a..34d957e26ef5b 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -315,7 +315,10 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option it.lookup(db).container, GenericDefId::ConstId(it) => it.lookup(db).container, GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), - GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, + GenericDefId::AdtId(_) + | GenericDefId::TraitId(_) + | GenericDefId::ImplId(_) + | GenericDefId::TraitAliasId(_) => return None, }; match container { diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 54425d69b6b7f..db0b84ef0887b 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -14,7 +14,8 @@ use syntax::{ast, AstNode}; use crate::{ Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam, - Macro, Module, ModuleDef, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, + Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias, TypeParam, Union, + Variant, }; pub trait HasAttrs { @@ -60,6 +61,7 @@ impl_has_attrs![ (Static, StaticId), (Const, ConstId), (Trait, TraitId), + (TraitAlias, TraitAliasId), (TypeAlias, TypeAliasId), (Macro, MacroId), (Function, FunctionId), @@ -134,6 +136,7 @@ fn resolve_doc_path( AttrDefId::StaticId(it) => it.resolver(db.upcast()), AttrDefId::ConstId(it) => it.resolver(db.upcast()), AttrDefId::TraitId(it) => it.resolver(db.upcast()), + AttrDefId::TraitAliasId(it) => it.resolver(db.upcast()), AttrDefId::TypeAliasId(it) => it.resolver(db.upcast()), AttrDefId::ImplId(it) => it.resolver(db.upcast()), AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()), diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 66bf2a2900e87..5aae92efd19ed 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -18,8 +18,8 @@ use hir_ty::{ use crate::{ Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, Field, Function, GenericParam, - HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, Trait, TyBuilder, Type, - TypeAlias, TypeOrConstParam, TypeParam, Union, Variant, + HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, Trait, TraitAlias, + TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -501,6 +501,22 @@ impl HirDisplay for Trait { } } +impl HirDisplay for TraitAlias { + fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { + write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; + let data = f.db.trait_alias_data(self.id); + write!(f, "trait {}", data.name)?; + let def_id = GenericDefId::TraitAliasId(self.id); + write_generic_params(def_id, f)?; + f.write_str(" = ")?; + // FIXME: Currently we lower every bounds in a trait alias as a trait bound on `Self` i.e. + // `trait Foo = Bar` is stored and displayed as `trait Foo = where Self: Bar`, which might + // be less readable. + write_where_clause(def_id, f)?; + Ok(()) + } +} + impl HirDisplay for TypeAlias { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index f825a72c0f58a..4327691956755 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -37,6 +37,7 @@ from_id![ (hir_def::EnumId, crate::Enum), (hir_def::TypeAliasId, crate::TypeAlias), (hir_def::TraitId, crate::Trait), + (hir_def::TraitAliasId, crate::TraitAlias), (hir_def::StaticId, crate::Static), (hir_def::ConstId, crate::Const), (hir_def::FunctionId, crate::Function), @@ -110,6 +111,7 @@ impl From for ModuleDef { ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()), ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()), ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()), + ModuleDefId::TraitAliasId(it) => ModuleDef::TraitAlias(it.into()), ModuleDefId::TypeAliasId(it) => ModuleDef::TypeAlias(it.into()), ModuleDefId::BuiltinType(it) => ModuleDef::BuiltinType(it.into()), ModuleDefId::MacroId(it) => ModuleDef::Macro(it.into()), @@ -127,6 +129,7 @@ impl From for ModuleDefId { ModuleDef::Const(it) => ModuleDefId::ConstId(it.into()), ModuleDef::Static(it) => ModuleDefId::StaticId(it.into()), ModuleDef::Trait(it) => ModuleDefId::TraitId(it.into()), + ModuleDef::TraitAlias(it) => ModuleDefId::TraitAliasId(it.into()), ModuleDef::TypeAlias(it) => ModuleDefId::TypeAliasId(it.into()), ModuleDef::BuiltinType(it) => ModuleDefId::BuiltinType(it.into()), ModuleDef::Macro(it) => ModuleDefId::MacroId(it.into()), @@ -172,6 +175,7 @@ impl From for GenericDefId { GenericDef::Function(it) => GenericDefId::FunctionId(it.id), GenericDef::Adt(it) => GenericDefId::AdtId(it.into()), GenericDef::Trait(it) => GenericDefId::TraitId(it.id), + GenericDef::TraitAlias(it) => GenericDefId::TraitAliasId(it.id), GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), GenericDef::Impl(it) => GenericDefId::ImplId(it.id), GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()), @@ -186,6 +190,7 @@ impl From for GenericDef { GenericDefId::FunctionId(it) => GenericDef::Function(it.into()), GenericDefId::AdtId(it) => GenericDef::Adt(it.into()), GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), + GenericDefId::TraitAliasId(it) => GenericDef::TraitAlias(it.into()), GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), GenericDefId::ImplId(it) => GenericDef::Impl(it.into()), GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()), diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index f8b01db3e3288..a28b2d577aa12 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -11,7 +11,7 @@ use syntax::ast; use crate::{ db::HirDatabase, Adt, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, Macro, - Module, Static, Struct, Trait, TypeAlias, TypeOrConstParam, Union, Variant, + Module, Static, Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, }; pub trait HasSource { @@ -122,6 +122,12 @@ impl HasSource for Trait { Some(self.id.lookup(db.upcast()).source(db.upcast())) } } +impl HasSource for TraitAlias { + type Ast = ast::TraitAlias; + fn source(self, db: &dyn HirDatabase) -> Option> { + Some(self.id.lookup(db.upcast()).source(db.upcast())) + } +} impl HasSource for TypeAlias { type Ast = ast::TypeAlias; fn source(self, db: &dyn HirDatabase) -> Option> { @@ -158,7 +164,7 @@ impl HasSource for Impl { } impl HasSource for TypeOrConstParam { - type Ast = Either; + type Ast = Either; fn source(self, db: &dyn HirDatabase) -> Option> { let child_source = self.id.parent.child_source(db.upcast()); Some(child_source.map(|it| it[self.id.local_id].clone())) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c64106d3afde5..27f35bd264468 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -53,7 +53,7 @@ use hir_def::{ AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, + TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{name::name, MacroCallKind}; use hir_ty::{ @@ -272,6 +272,7 @@ pub enum ModuleDef { Const(Const), Static(Static), Trait(Trait), + TraitAlias(TraitAlias), TypeAlias(TypeAlias), BuiltinType(BuiltinType), Macro(Macro), @@ -284,6 +285,7 @@ impl_from!( Const, Static, Trait, + TraitAlias, TypeAlias, BuiltinType, Macro @@ -310,6 +312,7 @@ impl ModuleDef { ModuleDef::Const(it) => Some(it.module(db)), ModuleDef::Static(it) => Some(it.module(db)), ModuleDef::Trait(it) => Some(it.module(db)), + ModuleDef::TraitAlias(it) => Some(it.module(db)), ModuleDef::TypeAlias(it) => Some(it.module(db)), ModuleDef::Macro(it) => Some(it.module(db)), ModuleDef::BuiltinType(_) => None, @@ -338,6 +341,7 @@ impl ModuleDef { ModuleDef::Const(it) => it.name(db)?, ModuleDef::Adt(it) => it.name(db), ModuleDef::Trait(it) => it.name(db), + ModuleDef::TraitAlias(it) => it.name(db), ModuleDef::Function(it) => it.name(db), ModuleDef::Variant(it) => it.name(db), ModuleDef::TypeAlias(it) => it.name(db), @@ -356,6 +360,7 @@ impl ModuleDef { Adt::Union(it) => it.id.into(), }, ModuleDef::Trait(it) => it.id.into(), + ModuleDef::TraitAlias(it) => it.id.into(), ModuleDef::Function(it) => it.id.into(), ModuleDef::TypeAlias(it) => it.id.into(), ModuleDef::Module(it) => it.id.into(), @@ -398,6 +403,7 @@ impl ModuleDef { ModuleDef::Module(_) | ModuleDef::Adt(_) | ModuleDef::Trait(_) + | ModuleDef::TraitAlias(_) | ModuleDef::TypeAlias(_) | ModuleDef::Macro(_) | ModuleDef::BuiltinType(_) => None, @@ -413,6 +419,7 @@ impl ModuleDef { ModuleDef::Const(it) => it.attrs(db), ModuleDef::Static(it) => it.attrs(db), ModuleDef::Trait(it) => it.attrs(db), + ModuleDef::TraitAlias(it) => it.attrs(db), ModuleDef::TypeAlias(it) => it.attrs(db), ModuleDef::Macro(it) => it.attrs(db), ModuleDef::BuiltinType(_) => return None, @@ -429,6 +436,7 @@ impl HasVisibility for ModuleDef { ModuleDef::Const(it) => it.visibility(db), ModuleDef::Static(it) => it.visibility(db), ModuleDef::Trait(it) => it.visibility(db), + ModuleDef::TraitAlias(it) => it.visibility(db), ModuleDef::TypeAlias(it) => it.visibility(db), ModuleDef::Variant(it) => it.visibility(db), ModuleDef::Macro(it) => it.visibility(db), @@ -1934,6 +1942,27 @@ impl HasVisibility for Trait { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TraitAlias { + pub(crate) id: TraitAliasId, +} + +impl TraitAlias { + pub fn module(self, db: &dyn HirDatabase) -> Module { + Module { id: self.id.lookup(db.upcast()).container } + } + + pub fn name(self, db: &dyn HirDatabase) -> Name { + db.trait_alias_data(self.id).name.clone() + } +} + +impl HasVisibility for TraitAlias { + fn visibility(&self, db: &dyn HirDatabase) -> Visibility { + db.trait_alias_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAlias { pub(crate) id: TypeAliasId, @@ -2306,6 +2335,7 @@ pub enum GenericDef { Function(Function), Adt(Adt), Trait(Trait), + TraitAlias(TraitAlias), TypeAlias(TypeAlias), Impl(Impl), // enum variants cannot have generics themselves, but their parent enums @@ -2318,6 +2348,7 @@ impl_from!( Function, Adt(Struct, Enum, Union), Trait, + TraitAlias, TypeAlias, Impl, Variant, @@ -4066,6 +4097,12 @@ impl HasCrate for Trait { } } +impl HasCrate for TraitAlias { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + self.module(db).krate() + } +} + impl HasCrate for Static { fn krate(&self, db: &dyn HirDatabase) -> Crate { self.module(db).krate() diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index b3ba1c7d349fc..be2dffc29cccf 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -68,7 +68,8 @@ impl PathResolution { | ModuleDef::Function(_) | ModuleDef::Module(_) | ModuleDef::Static(_) - | ModuleDef::Trait(_), + | ModuleDef::Trait(_) + | ModuleDef::TraitAlias(_), ) => None, PathResolution::Def(ModuleDef::TypeAlias(alias)) => { Some(TypeNs::TypeAliasId((*alias).into())) @@ -1330,6 +1331,7 @@ impl<'db> SemanticsImpl<'db> { }) } ChildContainer::TraitId(it) => it.resolver(self.db.upcast()), + ChildContainer::TraitAliasId(it) => it.resolver(self.db.upcast()), ChildContainer::ImplId(it) => it.resolver(self.db.upcast()), ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()), ChildContainer::EnumId(it) => it.resolver(self.db.upcast()), @@ -1556,6 +1558,7 @@ to_def_impls![ (crate::Enum, ast::Enum, enum_to_def), (crate::Union, ast::Union, union_to_def), (crate::Trait, ast::Trait, trait_to_def), + (crate::TraitAlias, ast::TraitAlias, trait_alias_to_def), (crate::Impl, ast::Impl, impl_to_def), (crate::TypeAlias, ast::TypeAlias, type_alias_to_def), (crate::Const, ast::Const, const_to_def), diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 2b5bfda1d4347..ddfec20e3f9ab 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -93,7 +93,7 @@ use hir_def::{ keys::{self, Key}, AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, + TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, }; use hir_expand::{attrs::AttrId, name::AsName, HirFileId, MacroCallId}; use rustc_hash::FxHashMap; @@ -159,6 +159,12 @@ impl SourceToDefCtx<'_, '_> { pub(super) fn trait_to_def(&mut self, src: InFile) -> Option { self.to_def(src, keys::TRAIT) } + pub(super) fn trait_alias_to_def( + &mut self, + src: InFile, + ) -> Option { + self.to_def(src, keys::TRAIT_ALIAS) + } pub(super) fn impl_to_def(&mut self, src: InFile) -> Option { self.to_def(src, keys::IMPL) } @@ -353,6 +359,9 @@ impl SourceToDefCtx<'_, '_> { match item { ast::Item::Module(it) => self.module_to_def(container.with_value(it))?.into(), ast::Item::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), + ast::Item::TraitAlias(it) => { + self.trait_alias_to_def(container.with_value(it))?.into() + } ast::Item::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), ast::Item::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), ast::Item::TypeAlias(it) => { @@ -400,6 +409,9 @@ impl SourceToDefCtx<'_, '_> { ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(), ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(), ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(), + ast::Item::TraitAlias(it) => { + self.trait_alias_to_def(InFile::new(file_id, it))?.into() + } ast::Item::TypeAlias(it) => { self.type_alias_to_def(InFile::new(file_id, it))?.into() } @@ -435,6 +447,7 @@ pub(crate) enum ChildContainer { DefWithBodyId(DefWithBodyId), ModuleId(ModuleId), TraitId(TraitId), + TraitAliasId(TraitAliasId), ImplId(ImplId), EnumId(EnumId), VariantId(VariantId), @@ -447,6 +460,7 @@ impl_from! { DefWithBodyId, ModuleId, TraitId, + TraitAliasId, ImplId, EnumId, VariantId, @@ -462,6 +476,7 @@ impl ChildContainer { ChildContainer::DefWithBodyId(it) => it.child_by_source(db, file_id), ChildContainer::ModuleId(it) => it.child_by_source(db, file_id), ChildContainer::TraitId(it) => it.child_by_source(db, file_id), + ChildContainer::TraitAliasId(_) => DynMap::default(), ChildContainer::ImplId(it) => it.child_by_source(db, file_id), ChildContainer::EnumId(it) => it.child_by_source(db, file_id), ChildContainer::VariantId(it) => it.child_by_source(db, file_id), diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 61e58cb1c4a71..ada529fa74c21 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -51,7 +51,7 @@ use syntax::{ use crate::{ db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, Function, Local, Macro, ModuleDef, Static, - Struct, ToolModule, Trait, Type, TypeAlias, Variant, + Struct, ToolModule, Trait, TraitAlias, Type, TypeAlias, Variant, }; /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of @@ -978,6 +978,7 @@ fn resolve_hir_path_( TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), + TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), }; match unresolved { Some(unresolved) => resolver @@ -1065,6 +1066,7 @@ fn resolve_hir_path_qualifier( TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), + TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), }) .or_else(|| { resolver diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index fd78decda4e64..a9afa1c6f4519 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -68,6 +68,7 @@ pub enum FileSymbolKind { Static, Struct, Trait, + TraitAlias, TypeAlias, Union, } @@ -153,6 +154,9 @@ impl<'a> SymbolCollector<'a> { self.push_decl(id, FileSymbolKind::Trait); self.collect_from_trait(id); } + ModuleDefId::TraitAliasId(id) => { + self.push_decl(id, FileSymbolKind::TraitAlias); + } ModuleDefId::TypeAliasId(id) => { self.push_decl_assoc(id, FileSymbolKind::TypeAlias); } diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs index d9e00435ecf5d..4c61678eab4f2 100644 --- a/crates/ide-assists/src/handlers/fix_visibility.rs +++ b/crates/ide-assists/src/handlers/fix_visibility.rs @@ -192,6 +192,10 @@ fn target_data_for_def( target_name = Some(t.name(db)); offset_target_and_file_id(db, t)? } + hir::ModuleDef::TraitAlias(t) => { + target_name = Some(t.name(db)); + offset_target_and_file_id(db, t)? + } hir::ModuleDef::TypeAlias(t) => { target_name = Some(t.name(db)); offset_target_and_file_id(db, t)? diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index 37849c251a480..69c05a76df4ce 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -33,7 +33,9 @@ pub(crate) fn complete_type_path( // Don't suggest attribute macros and derives. ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db), // Type things are fine - ScopeDef::ModuleDef(BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TypeAlias(_)) + ScopeDef::ModuleDef( + BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TraitAlias(_) | TypeAlias(_), + ) | ScopeDef::AdtSelfType(_) | ScopeDef::Unknown | ScopeDef::GenericParam(TypeParam(_)) => true, diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index ea54068b0f8bf..92e64cd123830 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -416,6 +416,7 @@ impl<'a> CompletionContext<'a> { hir::ModuleDef::Const(it) => self.is_visible(it), hir::ModuleDef::Static(it) => self.is_visible(it), hir::ModuleDef::Trait(it) => self.is_visible(it), + hir::ModuleDef::TraitAlias(it) => self.is_visible(it), hir::ModuleDef::TypeAlias(it) => self.is_visible(it), hir::ModuleDef::Macro(it) => self.is_visible(it), hir::ModuleDef::BuiltinType(_) => Visible::Yes, diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index 2f65491d85e14..bb9fa7ccaccc6 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -288,7 +288,7 @@ impl_from!(SymbolKind for CompletionItemKind); impl CompletionItemKind { #[cfg(test)] - pub(crate) fn tag(&self) -> &'static str { + pub(crate) fn tag(self) -> &'static str { match self { CompletionItemKind::SymbolKind(kind) => match kind { SymbolKind::Attribute => "at", @@ -312,6 +312,7 @@ impl CompletionItemKind { SymbolKind::Struct => "st", SymbolKind::ToolModule => "tm", SymbolKind::Trait => "tt", + SymbolKind::TraitAlias => "tr", SymbolKind::TypeAlias => "ta", SymbolKind::TypeParam => "tp", SymbolKind::Union => "un", diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index d99ad5f9f04ba..c1f51aabb9676 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -367,6 +367,9 @@ fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind { ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const), ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static), ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait), + ScopeDef::ModuleDef(TraitAlias(..)) => { + CompletionItemKind::SymbolKind(SymbolKind::TraitAlias) + } ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias), ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param { diff --git a/crates/ide-db/src/active_parameter.rs b/crates/ide-db/src/active_parameter.rs index 2b6b60547b355..0da4e729a8ddd 100644 --- a/crates/ide-db/src/active_parameter.rs +++ b/crates/ide-db/src/active_parameter.rs @@ -96,6 +96,7 @@ pub fn generic_def_for_node( hir::PathResolution::Def(hir::ModuleDef::Adt(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(), + hir::PathResolution::Def(hir::ModuleDef::TraitAlias(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(), hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_)) diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index ed7f04fd8e7fe..cce33dcfe4690 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -9,7 +9,8 @@ use arrayvec::ArrayVec; use hir::{ Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, Field, Function, GenericParam, HasVisibility, Impl, ItemInNs, Label, Local, Macro, Module, ModuleDef, - Name, PathResolution, Semantics, Static, ToolModule, Trait, TypeAlias, Variant, Visibility, + Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant, + Visibility, }; use stdx::impl_from; use syntax::{ @@ -31,6 +32,7 @@ pub enum Definition { Const(Const), Static(Static), Trait(Trait), + TraitAlias(TraitAlias), TypeAlias(TypeAlias), BuiltinType(BuiltinType), SelfType(Impl), @@ -64,6 +66,7 @@ impl Definition { Definition::Const(it) => it.module(db), Definition::Static(it) => it.module(db), Definition::Trait(it) => it.module(db), + Definition::TraitAlias(it) => it.module(db), Definition::TypeAlias(it) => it.module(db), Definition::Variant(it) => it.module(db), Definition::SelfType(it) => it.module(db), @@ -87,6 +90,7 @@ impl Definition { Definition::Const(it) => it.visibility(db), Definition::Static(it) => it.visibility(db), Definition::Trait(it) => it.visibility(db), + Definition::TraitAlias(it) => it.visibility(db), Definition::TypeAlias(it) => it.visibility(db), Definition::Variant(it) => it.visibility(db), Definition::BuiltinType(_) => Visibility::Public, @@ -113,6 +117,7 @@ impl Definition { Definition::Const(it) => it.name(db)?, Definition::Static(it) => it.name(db), Definition::Trait(it) => it.name(db), + Definition::TraitAlias(it) => it.name(db), Definition::TypeAlias(it) => it.name(db), Definition::BuiltinType(it) => it.name(), Definition::SelfType(_) => return None, @@ -300,6 +305,7 @@ impl NameClass { ast::Item::Module(it) => Definition::Module(sema.to_def(&it)?), ast::Item::Static(it) => Definition::Static(sema.to_def(&it)?), ast::Item::Trait(it) => Definition::Trait(sema.to_def(&it)?), + ast::Item::TraitAlias(it) => Definition::TraitAlias(sema.to_def(&it)?), ast::Item::TypeAlias(it) => Definition::TypeAlias(sema.to_def(&it)?), ast::Item::Enum(it) => Definition::Adt(hir::Adt::Enum(sema.to_def(&it)?)), ast::Item::Struct(it) => Definition::Adt(hir::Adt::Struct(sema.to_def(&it)?)), @@ -542,7 +548,7 @@ impl NameRefClass { } impl_from!( - Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local, + Field, Module, Function, Adt, Variant, Const, Static, Trait, TraitAlias, TypeAlias, BuiltinType, Local, GenericParam, Label, Macro for Definition ); @@ -599,6 +605,7 @@ impl From for Definition { ModuleDef::Const(it) => Definition::Const(it), ModuleDef::Static(it) => Definition::Static(it), ModuleDef::Trait(it) => Definition::Trait(it), + ModuleDef::TraitAlias(it) => Definition::TraitAlias(it), ModuleDef::TypeAlias(it) => Definition::TypeAlias(it), ModuleDef::Macro(it) => Definition::Macro(it), ModuleDef::BuiltinType(it) => Definition::BuiltinType(it), @@ -616,6 +623,7 @@ impl From for Option { Definition::Const(it) => ModuleDef::Const(it), Definition::Static(it) => ModuleDef::Static(it), Definition::Trait(it) => ModuleDef::Trait(it), + Definition::TraitAlias(it) => ModuleDef::TraitAlias(it), Definition::TypeAlias(it) => ModuleDef::TypeAlias(it), Definition::BuiltinType(it) => ModuleDef::BuiltinType(it), _ => return None, diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 156bbb634e4d5..4c53ba3b83033 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -191,6 +191,7 @@ pub enum SymbolKind { Struct, ToolModule, Trait, + TraitAlias, TypeAlias, TypeParam, Union, @@ -221,6 +222,7 @@ impl From for SymbolKind { FileSymbolKind::Static => SymbolKind::Static, FileSymbolKind::Struct => SymbolKind::Struct, FileSymbolKind::Trait => SymbolKind::Trait, + FileSymbolKind::TraitAlias => SymbolKind::TraitAlias, FileSymbolKind::TypeAlias => SymbolKind::TypeAlias, FileSymbolKind::Union => SymbolKind::Union, } diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs index 84d70b258ff86..4179f1bd4f365 100644 --- a/crates/ide-db/src/rename.rs +++ b/crates/ide-db/src/rename.rs @@ -119,6 +119,7 @@ impl Definition { Definition::Const(it) => name_range(it, sema), Definition::Static(it) => name_range(it, sema), Definition::Trait(it) => name_range(it, sema), + Definition::TraitAlias(it) => name_range(it, sema), Definition::TypeAlias(it) => name_range(it, sema), Definition::Local(local) => { let src = local.source(sema.db); diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index c18a27f17d22c..bcdaac4cf8262 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -261,6 +261,7 @@ impl Definition { hir::GenericDef::Function(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::Adt(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::Trait(it) => it.source(db).map(|src| src.syntax().cloned()), + hir::GenericDef::TraitAlias(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::TypeAlias(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::Impl(it) => it.source(db).map(|src| src.syntax().cloned()), hir::GenericDef::Variant(it) => it.source(db).map(|src| src.syntax().cloned()), diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 339bb28180221..fae25f3102333 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -192,6 +192,7 @@ pub(crate) fn resolve_doc_path_for_def( Definition::Const(it) => it.resolve_doc_path(db, link, ns), Definition::Static(it) => it.resolve_doc_path(db, link, ns), Definition::Trait(it) => it.resolve_doc_path(db, link, ns), + Definition::TraitAlias(it) => it.resolve_doc_path(db, link, ns), Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns), Definition::Macro(it) => it.resolve_doc_path(db, link, ns), Definition::Field(it) => it.resolve_doc_path(db, link, ns), @@ -504,6 +505,7 @@ fn filename_and_frag_for_def( None => String::from("index.html"), }, Definition::Trait(t) => format!("trait.{}.html", t.name(db)), + Definition::TraitAlias(t) => format!("traitalias.{}.html", t.name(db)), Definition::TypeAlias(t) => format!("type.{}.html", t.name(db)), Definition::BuiltinType(t) => format!("primitive.{}.html", t.name()), Definition::Function(f) => format!("fn.{}.html", f.name(db)), diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 749c224c46207..c64b60d2936a0 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -454,6 +454,7 @@ pub(super) fn definition( Some(body.to_string()) }), Definition::Trait(it) => label_and_docs(db, it), + Definition::TraitAlias(it) => label_and_docs(db, it), Definition::TypeAlias(it) => label_and_docs(db, it), Definition::BuiltinType(it) => { return famous_defs diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs index af5e96d2381ac..349e79ecfdda0 100644 --- a/crates/ide/src/moniker.rs +++ b/crates/ide/src/moniker.rs @@ -208,6 +208,9 @@ pub(crate) fn def_to_moniker( Definition::Trait(trait_) => { MonikerDescriptor { name: trait_.name(db), desc: MonikerDescriptorKind::Type } } + Definition::TraitAlias(ta) => { + MonikerDescriptor { name: ta.name(db), desc: MonikerDescriptorKind::Type } + } Definition::TypeAlias(ta) => { MonikerDescriptor { name: ta.name(db), desc: MonikerDescriptorKind::TypeParameter } } diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 3aa799d43a8a3..9787724b45ec7 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -192,6 +192,7 @@ impl TryToNav for Definition { Definition::Const(it) => it.try_to_nav(db), Definition::Static(it) => it.try_to_nav(db), Definition::Trait(it) => it.try_to_nav(db), + Definition::TraitAlias(it) => it.try_to_nav(db), Definition::TypeAlias(it) => it.try_to_nav(db), Definition::BuiltinType(_) => None, Definition::ToolModule(_) => None, @@ -212,6 +213,7 @@ impl TryToNav for hir::ModuleDef { hir::ModuleDef::Const(it) => it.try_to_nav(db), hir::ModuleDef::Static(it) => it.try_to_nav(db), hir::ModuleDef::Trait(it) => it.try_to_nav(db), + hir::ModuleDef::TraitAlias(it) => it.try_to_nav(db), hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db), hir::ModuleDef::Macro(it) => it.try_to_nav(db), hir::ModuleDef::BuiltinType(_) => None, @@ -249,6 +251,9 @@ impl ToNavFromAst for hir::TypeAlias { impl ToNavFromAst for hir::Trait { const KIND: SymbolKind = SymbolKind::Trait; } +impl ToNavFromAst for hir::TraitAlias { + const KIND: SymbolKind = SymbolKind::TraitAlias; +} impl TryToNav for D where diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index f70ca55a508d2..d32ae83c8f7be 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -252,6 +252,10 @@ fn signature_help_for_generics( res.doc = it.docs(db).map(|it| it.into()); format_to!(res.signature, "trait {}", it.name(db)); } + hir::GenericDef::TraitAlias(it) => { + res.doc = it.docs(db).map(|it| it.into()); + format_to!(res.signature, "trait {}", it.name(db)); + } hir::GenericDef::TypeAlias(it) => { res.doc = it.docs(db).map(|it| it.into()); format_to!(res.signature, "type {}", it.name(db)); diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 892e6a9bb0ab8..390b7efdeb0bc 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -410,6 +410,7 @@ fn highlight_def( h } Definition::Trait(_) => Highlight::new(HlTag::Symbol(SymbolKind::Trait)), + Definition::TraitAlias(_) => Highlight::new(HlTag::Symbol(SymbolKind::TraitAlias)), Definition::TypeAlias(type_) => { let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias)); diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 9139528c7ed96..3c4cfc78152dd 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -274,6 +274,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { Definition::Const(_) => SymbolKind::Const, Definition::Static(_) => SymbolKind::Static, Definition::Trait(_) => SymbolKind::Trait, + Definition::TraitAlias(_) => SymbolKind::TraitAlias, Definition::TypeAlias(_) => SymbolKind::TypeAlias, Definition::BuiltinType(_) => return HlTag::BuiltinType, Definition::Macro(_) => SymbolKind::Macro, diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 3949f1189bd5e..a81c4ee0cbd41 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -150,6 +150,7 @@ impl HlTag { SymbolKind::Struct => "struct", SymbolKind::ToolModule => "tool_module", SymbolKind::Trait => "trait", + SymbolKind::TraitAlias => "trait_alias", SymbolKind::TypeAlias => "type_alias", SymbolKind::TypeParam => "type_param", SymbolKind::Union => "union", diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 92029dc1de78f..7d97b69f8ea05 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -50,7 +50,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { SymbolKind::Struct => lsp_types::SymbolKind::STRUCT, SymbolKind::Enum => lsp_types::SymbolKind::ENUM, SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER, - SymbolKind::Trait => lsp_types::SymbolKind::INTERFACE, + SymbolKind::Trait | SymbolKind::TraitAlias => lsp_types::SymbolKind::INTERFACE, SymbolKind::Macro | SymbolKind::BuiltinAttr | SymbolKind::Attribute @@ -135,6 +135,7 @@ pub(crate) fn completion_item_kind( SymbolKind::Static => lsp_types::CompletionItemKind::VALUE, SymbolKind::Struct => lsp_types::CompletionItemKind::STRUCT, SymbolKind::Trait => lsp_types::CompletionItemKind::INTERFACE, + SymbolKind::TraitAlias => lsp_types::CompletionItemKind::INTERFACE, SymbolKind::TypeAlias => lsp_types::CompletionItemKind::STRUCT, SymbolKind::TypeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER, SymbolKind::Union => lsp_types::CompletionItemKind::STRUCT, @@ -656,6 +657,7 @@ fn semantic_token_type_and_modifiers( SymbolKind::Union => semantic_tokens::UNION, SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS, SymbolKind::Trait => semantic_tokens::INTERFACE, + SymbolKind::TraitAlias => semantic_tokens::INTERFACE, SymbolKind::Macro => semantic_tokens::MACRO, SymbolKind::BuiltinAttr => semantic_tokens::BUILTIN_ATTRIBUTE, SymbolKind::ToolModule => semantic_tokens::TOOL_MODULE, From f8eac19b3354722a6fa0177968af54a58bb5b9e1 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sat, 4 Mar 2023 00:24:08 +0900 Subject: [PATCH 5/5] Support trait aliases in IDE where type support isn't needed --- crates/ide/src/file_structure.rs | 79 +++++++++++++++++++---------- crates/ide/src/goto_definition.rs | 8 ++- crates/ide/src/markup.rs | 2 +- crates/ide/src/move_item.rs | 1 + crates/ide/src/navigation_target.rs | 1 + crates/ide/src/references.rs | 32 ++++++++++++ crates/ide/src/runnables.rs | 1 + 7 files changed, 95 insertions(+), 29 deletions(-) diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs index b23763dce8679..a32ac35496aa4 100644 --- a/crates/ide/src/file_structure.rs +++ b/crates/ide/src/file_structure.rs @@ -149,6 +149,7 @@ fn structure_node(node: &SyntaxNode) -> Option { ast::Enum(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Enum)), ast::Variant(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Variant)), ast::Trait(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Trait)), + ast::TraitAlias(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::TraitAlias)), ast::Module(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Module)), ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::TypeAlias)), ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Field)), @@ -262,6 +263,8 @@ enum E { X, Y(i32) } type T = (); static S: i32 = 92; const C: i32 = 92; +trait Tr {} +trait Alias = Tr; impl E {} @@ -457,11 +460,33 @@ fn g() {} ), deprecated: false, }, + StructureNode { + parent: None, + label: "Tr", + navigation_range: 239..241, + node_range: 233..244, + kind: SymbolKind( + Trait, + ), + detail: None, + deprecated: false, + }, + StructureNode { + parent: None, + label: "Alias", + navigation_range: 251..256, + node_range: 245..262, + kind: SymbolKind( + TraitAlias, + ), + detail: None, + deprecated: false, + }, StructureNode { parent: None, label: "impl E", - navigation_range: 239..240, - node_range: 234..243, + navigation_range: 269..270, + node_range: 264..273, kind: SymbolKind( Impl, ), @@ -471,8 +496,8 @@ fn g() {} StructureNode { parent: None, label: "impl fmt::Debug for E", - navigation_range: 265..266, - node_range: 245..269, + navigation_range: 295..296, + node_range: 275..299, kind: SymbolKind( Impl, ), @@ -482,8 +507,8 @@ fn g() {} StructureNode { parent: None, label: "mc", - navigation_range: 284..286, - node_range: 271..303, + navigation_range: 314..316, + node_range: 301..333, kind: SymbolKind( Macro, ), @@ -493,8 +518,8 @@ fn g() {} StructureNode { parent: None, label: "mcexp", - navigation_range: 334..339, - node_range: 305..356, + navigation_range: 364..369, + node_range: 335..386, kind: SymbolKind( Macro, ), @@ -504,8 +529,8 @@ fn g() {} StructureNode { parent: None, label: "mcexp", - navigation_range: 387..392, - node_range: 358..409, + navigation_range: 417..422, + node_range: 388..439, kind: SymbolKind( Macro, ), @@ -515,8 +540,8 @@ fn g() {} StructureNode { parent: None, label: "obsolete", - navigation_range: 428..436, - node_range: 411..441, + navigation_range: 458..466, + node_range: 441..471, kind: SymbolKind( Function, ), @@ -528,8 +553,8 @@ fn g() {} StructureNode { parent: None, label: "very_obsolete", - navigation_range: 481..494, - node_range: 443..499, + navigation_range: 511..524, + node_range: 473..529, kind: SymbolKind( Function, ), @@ -541,8 +566,8 @@ fn g() {} StructureNode { parent: None, label: "Some region name", - navigation_range: 501..528, - node_range: 501..528, + navigation_range: 531..558, + node_range: 531..558, kind: Region, detail: None, deprecated: false, @@ -550,8 +575,8 @@ fn g() {} StructureNode { parent: None, label: "m", - navigation_range: 568..569, - node_range: 543..606, + navigation_range: 598..599, + node_range: 573..636, kind: SymbolKind( Module, ), @@ -560,22 +585,22 @@ fn g() {} }, StructureNode { parent: Some( - 20, + 22, ), label: "dontpanic", - navigation_range: 543..563, - node_range: 543..563, + navigation_range: 573..593, + node_range: 573..593, kind: Region, detail: None, deprecated: false, }, StructureNode { parent: Some( - 20, + 22, ), label: "f", - navigation_range: 575..576, - node_range: 572..581, + navigation_range: 605..606, + node_range: 602..611, kind: SymbolKind( Function, ), @@ -586,11 +611,11 @@ fn g() {} }, StructureNode { parent: Some( - 20, + 22, ), label: "g", - navigation_range: 598..599, - node_range: 582..604, + navigation_range: 628..629, + node_range: 612..634, kind: SymbolKind( Function, ), diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 65d1181d09244..cf0819a2524b9 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -764,6 +764,13 @@ trait Foo$0 { } "#, ); + check( + r#" +trait Foo$0 = ; + //^^^ +"#, + ); + check( r#" mod bar$0 { } @@ -1423,7 +1430,6 @@ include!("included.rs$0"); ); } - #[cfg(test)] mod goto_impl_of_trait_fn { use super::check; #[test] diff --git a/crates/ide/src/markup.rs b/crates/ide/src/markup.rs index de9fef61a78ea..411eb695fbf27 100644 --- a/crates/ide/src/markup.rs +++ b/crates/ide/src/markup.rs @@ -32,7 +32,7 @@ impl Markup { pub fn as_str(&self) -> &str { self.text.as_str() } - pub fn fenced_block(contents: &impl fmt::Display) -> Markup { + pub fn fenced_block(contents: impl fmt::Display) -> Markup { format!("```rust\n{contents}\n```").into() } } diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs index ffc4bdd7da33f..b955ea99f0c04 100644 --- a/crates/ide/src/move_item.rs +++ b/crates/ide/src/move_item.rs @@ -73,6 +73,7 @@ fn find_ancestors(item: SyntaxElement, direction: Direction, range: TextRange) - SyntaxKind::MACRO_CALL, SyntaxKind::TYPE_ALIAS, SyntaxKind::TRAIT, + SyntaxKind::TRAIT_ALIAS, SyntaxKind::IMPL, SyntaxKind::MACRO_DEF, SyntaxKind::STRUCT, diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 9787724b45ec7..11d10d2b85420 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -549,6 +549,7 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> ast::Struct(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), ast::Enum(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), ast::Trait(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), + ast::TraitAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), ast::Module(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), ast::TypeAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), ast::Const(it) => sema.to_def(&it).map(|it| it.display(db).to_string()), diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index cabbc287279f6..3684c1033f32f 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -1355,6 +1355,38 @@ impl Foo { ); } + #[test] + fn test_trait_alias() { + check( + r#" +trait Foo {} +trait Bar$0 = Foo where Self: ; +fn foo(_: impl Bar, _: &dyn Bar) {} +"#, + expect![[r#" + Bar TraitAlias FileId(0) 13..42 19..22 + + FileId(0) 53..56 + FileId(0) 66..69 + FileId(0) 79..82 + "#]], + ); + } + + #[test] + fn test_trait_alias_self() { + check( + r#" +trait Foo = where Self$0: ; +"#, + expect![[r#" + Self TypeParam FileId(0) 6..9 6..9 + + FileId(0) 18..22 + "#]], + ); + } + #[test] fn test_attr_differs_from_fn_with_same_name() { check( diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 77aef710ad1d6..8a8a9151c4257 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -416,6 +416,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { Definition::Const(it) => it.attrs(db), Definition::Static(it) => it.attrs(db), Definition::Trait(it) => it.attrs(db), + Definition::TraitAlias(it) => it.attrs(db), Definition::TypeAlias(it) => it.attrs(db), Definition::Macro(it) => it.attrs(db), Definition::SelfType(it) => it.attrs(db),