about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2023-03-04 00:24:07 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2023-03-04 00:24:07 +0900
commit29c957f97388afd2a21ec3364ea4ce8c269cfbcd (patch)
tree4ef46eaa49bb2bc3d5634777b652d95b528d020a
parente2ec3a6561d73cc4b530c69a9bafc30c4f34b1ec (diff)
downloadrust-29c957f97388afd2a21ec3364ea4ce8c269cfbcd.tar.gz
rust-29c957f97388afd2a21ec3364ea4ce8c269cfbcd.zip
Lower and handle trait aliases in HIR
-rw-r--r--crates/hir-def/src/attr.rs2
-rw-r--r--crates/hir-def/src/child_by_source.rs3
-rw-r--r--crates/hir-def/src/data.rs37
-rw-r--r--crates/hir-def/src/db.rs11
-rw-r--r--crates/hir-def/src/generics.rs26
-rw-r--r--crates/hir-def/src/import_map.rs2
-rw-r--r--crates/hir-def/src/item_scope.rs1
-rw-r--r--crates/hir-def/src/item_tree.rs17
-rw-r--r--crates/hir-def/src/item_tree/lower.rs47
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs29
-rw-r--r--crates/hir-def/src/keys.rs5
-rw-r--r--crates/hir-def/src/lib.rs15
-rw-r--r--crates/hir-def/src/nameres/collector.rs17
-rw-r--r--crates/hir-def/src/nameres/tests/incremental.rs1
-rw-r--r--crates/hir-def/src/resolver.rs16
-rw-r--r--crates/hir-ty/src/diagnostics/decl_check.rs1
-rw-r--r--crates/hir-ty/src/infer.rs5
-rw-r--r--crates/hir-ty/src/lower.rs6
-rw-r--r--crates/hir-ty/src/utils.rs5
-rw-r--r--crates/hir/src/attrs.rs5
-rw-r--r--crates/hir/src/display.rs20
-rw-r--r--crates/hir/src/from_id.rs5
-rw-r--r--crates/hir/src/has_source.rs10
-rw-r--r--crates/hir/src/lib.rs39
-rw-r--r--crates/hir/src/semantics.rs5
-rw-r--r--crates/hir/src/semantics/source_to_def.rs17
-rw-r--r--crates/hir/src/source_analyzer.rs4
-rw-r--r--crates/hir/src/symbols.rs4
-rw-r--r--crates/ide-assists/src/handlers/fix_visibility.rs4
-rw-r--r--crates/ide-completion/src/completions/type.rs4
-rw-r--r--crates/ide-completion/src/context.rs1
-rw-r--r--crates/ide-completion/src/item.rs3
-rw-r--r--crates/ide-completion/src/render.rs3
-rw-r--r--crates/ide-db/src/active_parameter.rs1
-rw-r--r--crates/ide-db/src/defs.rs12
-rw-r--r--crates/ide-db/src/lib.rs2
-rw-r--r--crates/ide-db/src/rename.rs1
-rw-r--r--crates/ide-db/src/search.rs1
-rw-r--r--crates/ide/src/doc_links.rs2
-rw-r--r--crates/ide/src/hover/render.rs1
-rw-r--r--crates/ide/src/moniker.rs3
-rw-r--r--crates/ide/src/navigation_target.rs5
-rw-r--r--crates/ide/src/signature_help.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs1
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs1
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs4
47 files changed, 334 insertions, 75 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 79c2c188ff1..200072c172e 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 19d2fe956f0..68b57acca2a 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 c3c1dfd39ac..ee6e269fe55 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,
@@ -300,6 +292,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<TraitAliasData> {
+        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<Interned<TraitRef>>,
     pub self_ty: Interned<TypeRef>,
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index b23427a73b3..270cfa06e58 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<dyn AstDatabase> {
     #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
     fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>);
 
+    #[salsa::invoke(TraitAliasData::trait_alias_query)]
+    fn trait_alias_data(&self, e: TraitAliasId) -> Arc<TraitAliasData>;
+
     #[salsa::invoke(TypeAliasData::type_alias_data_query)]
     fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
 
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 5a0aa193388..e4912fa8a64 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<LocalTypeOrConstParamId> for GenericDefId {
-    type Value = Either<ast::TypeOrConstParam, ast::Trait>;
+    type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>;
     fn child_source(
         &self,
         db: &dyn DefDatabase,
@@ -453,11 +458,20 @@ impl HasChildSource<LocalTypeOrConstParamId> 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 63e92df0e72..07a68d1598c 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<ImportKind> {
         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 53a4173ff42..991e447033f 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 19d01630ef0..9da5b2d47c8 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<Const>,
     statics: Arena<Static>,
     traits: Arena<Trait>,
+    trait_aliases: Arena<TraitAlias>,
     impls: Arena<Impl>,
     type_aliases: Arena<TypeAlias>,
     mods: Arena<Mod>,
@@ -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,12 +676,19 @@ pub struct Trait {
     pub generic_params: Interned<GenericParams>,
     pub is_auto: bool,
     pub is_unsafe: bool,
-    /// This is [`None`] if this Trait is a trait alias.
-    pub items: Option<Box<[AssocItem]>>,
+    pub items: Box<[AssocItem]>,
     pub ast_id: FileAstId<ast::Trait>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
+pub struct TraitAlias {
+    pub name: Name,
+    pub visibility: RawVisibilityId,
+    pub generic_params: Interned<GenericParams>,
+    pub ast_id: FileAstId<ast::TraitAlias>,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Impl {
     pub generic_params: Interned<GenericParams>,
     pub target_trait: Option<Interned<TraitRef>>,
@@ -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 b64b4d11e37..495a8878c33 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<FileItemTreeId<TraitAlias>> {
+        let name = trait_alias_def.name()?.as_name();
+        let visibility = self.lower_visibility(trait_alias_def);
+        let generic_params = self.lower_generic_params(
+            HasImplicitSelf::Yes(trait_alias_def.type_bound_list()),
+            trait_alias_def,
+        );
+        let ast_id = self.source_ast_id_map.ast_id(trait_alias_def);
+
+        let alias = TraitAlias { name, visibility, generic_params, ast_id };
+        Some(id(self.data().trait_aliases.alloc(alias)))
     }
 
     fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 8f230b87d01..5f29997964b 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 72beec8186c..f30be6b64e3 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<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
@@ -21,6 +21,7 @@ pub const STATIC: Key<ast::Static, StaticId> = Key::new();
 pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
 pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
 pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
+pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new();
 pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
 pub const UNION: Key<ast::Union, UnionId> = Key::new();
 pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 2aab1ccd914..8c2e93f0905 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,
     },
 };
 
@@ -262,6 +262,11 @@ pub type TraitLoc = ItemLoc<Trait>;
 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<TraitAlias>;
+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<TypeAlias>;
 impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
@@ -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 e3704bf2164..70acc3442c3 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 f5190b76db0..13e6825f821 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 36d8b24e9c3..043d49f768f 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<TraitId> {
+        // 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<ValueNs> {
 
         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<TypeNs> {
         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<T: Into<AdtId> + 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 f7031a8546a..f4d1013ceb0 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 c77a5e07375..535e0ab1155 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 296c6c5b21f..23b15087e31 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<TraitRef> {
         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 f69cb6bacbd..34d957e26ef 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<Generic
         GenericDefId::TypeAliasId(it) => 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 54425d69b6b..db0b84ef088 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 66bf2a2900e..5aae92efd19 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 f825a72c0f5..43276919567 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<ModuleDefId> 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<ModuleDef> 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<GenericDef> 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<GenericDefId> 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 f8b01db3e32..a28b2d577aa 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<InFile<Self::Ast>> {
+        Some(self.id.lookup(db.upcast()).source(db.upcast()))
+    }
+}
 impl HasSource for TypeAlias {
     type Ast = ast::TypeAlias;
     fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
@@ -158,7 +164,7 @@ impl HasSource for Impl {
 }
 
 impl HasSource for TypeOrConstParam {
-    type Ast = Either<ast::TypeOrConstParam, ast::Trait>;
+    type Ast = Either<ast::TypeOrConstParam, ast::TraitOrAlias>;
     fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
         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 c64106d3afd..27f35bd2644 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),
@@ -1935,6 +1943,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 b3ba1c7d349..be2dffc29cc 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 2b5bfda1d43..ddfec20e3f9 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<ast::Trait>) -> Option<TraitId> {
         self.to_def(src, keys::TRAIT)
     }
+    pub(super) fn trait_alias_to_def(
+        &mut self,
+        src: InFile<ast::TraitAlias>,
+    ) -> Option<TraitAliasId> {
+        self.to_def(src, keys::TRAIT_ALIAS)
+    }
     pub(super) fn impl_to_def(&mut self, src: InFile<ast::Impl>) -> Option<ImplId> {
         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 61e58cb1c4a..ada529fa74c 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 fd78decda4e..a9afa1c6f45 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 d9e00435ecf..4c61678eab4 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 37849c251a4..69c05a76df4 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 ea54068b0f8..92e64cd1238 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 2f65491d85e..bb9fa7ccacc 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 d99ad5f9f04..c1f51aabb96 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 2b6b60547b3..0da4e729a8d 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 ed7f04fd8e7..cce33dcfe46 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<ModuleDef> 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<Definition> for Option<ItemInNs> {
             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 156bbb634e4..4c53ba3b830 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<FileSymbolKind> 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 84d70b258ff..4179f1bd4f3 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 c18a27f17d2..bcdaac4cf82 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 339bb281802..fae25f31023 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 749c224c462..c64b60d2936 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 af5e96d2381..349e79ecfdd 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 3aa799d43a8..9787724b45e 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<D> TryToNav for D
 where
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index f70ca55a508..d32ae83c8f7 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 892e6a9bb0a..390b7efdeb0 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 9139528c7ed..3c4cfc78152 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 3949f1189bd..a81c4ee0cbd 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 92029dc1de7..7d97b69f8ea 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,