Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/item_tree/lower.rs8
-rw-r--r--crates/hir-def/src/path.rs3
-rw-r--r--crates/hir-def/src/path/lower.rs8
-rw-r--r--crates/syntax/rust.ungram2
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs54
5 files changed, 44 insertions, 31 deletions
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 077a1b619d..79249757d9 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -662,8 +662,12 @@ fn desugar_future_path(orig: TypeRef) -> Path {
let mut generic_args: Vec<_> =
std::iter::repeat(None).take(path.segments().len() - 1).collect();
let mut last = GenericArgs::empty();
- let binding =
- AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() };
+ let binding = AssociatedTypeBinding {
+ name: name![Output],
+ args: None,
+ type_ref: Some(orig),
+ bounds: Vec::new(),
+ };
last.bindings.push(binding);
generic_args.push(Some(Interned::new(last)));
diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index 2f13a9fbf0..592223f7d8 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -68,6 +68,9 @@ pub struct GenericArgs {
pub struct AssociatedTypeBinding {
/// The name of the associated type.
pub name: Name,
+ /// The generic arguments to the associated type. e.g. For `Trait<Assoc<'a, T> = &'a T>`, this
+ /// would be `['a, T]`.
+ pub args: Option<Interned<GenericArgs>>,
/// The type bound to this associated type (in `Item = T`, this would be the
/// `T`). This can be `None` if there are bounds instead.
pub type_ref: Option<TypeRef>,
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index 0428f1a398..cfa3a6baaf 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -163,6 +163,10 @@ pub(super) fn lower_generic_args(
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
if let Some(name_ref) = assoc_type_arg.name_ref() {
let name = name_ref.as_name();
+ let args = assoc_type_arg
+ .generic_arg_list()
+ .and_then(|args| lower_generic_args(lower_ctx, args))
+ .map(Interned::new);
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
l.bounds()
@@ -171,7 +175,7 @@ pub(super) fn lower_generic_args(
} else {
Vec::new()
};
- bindings.push(AssociatedTypeBinding { name, type_ref, bounds });
+ bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
}
}
ast::GenericArg::LifetimeArg(lifetime_arg) => {
@@ -214,6 +218,7 @@ fn lower_generic_args_from_fn_path(
let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty());
bindings.push(AssociatedTypeBinding {
name: name![Output],
+ args: None,
type_ref: Some(type_ref),
bounds: Vec::new(),
});
@@ -222,6 +227,7 @@ fn lower_generic_args_from_fn_path(
let type_ref = TypeRef::Tuple(Vec::new());
bindings.push(AssociatedTypeBinding {
name: name![Output],
+ args: None,
type_ref: Some(type_ref),
bounds: Vec::new(),
});
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 8947954354..5379732ac6 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -51,7 +51,7 @@ TypeArg =
Type
AssocTypeArg =
- NameRef GenericParamList? (':' TypeBoundList | ('=' Type | ConstArg))
+ NameRef GenericArgList? (':' TypeBoundList | ('=' Type | ConstArg))
LifetimeArg =
Lifetime
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 449402e5f5..6cfb98d92f 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -120,7 +120,7 @@ pub struct AssocTypeArg {
impl ast::HasTypeBounds for AssocTypeArg {}
impl AssocTypeArg {
pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
- pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+ pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
@@ -143,16 +143,6 @@ impl ConstArg {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericParamList {
- pub(crate) syntax: SyntaxNode,
-}
-impl GenericParamList {
- pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
- pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
- pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeBoundList {
pub(crate) syntax: SyntaxNode,
}
@@ -528,6 +518,16 @@ impl Abi {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct GenericParamList {
+ pub(crate) syntax: SyntaxNode,
+}
+impl GenericParamList {
+ pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+ pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
+ pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct WhereClause {
pub(crate) syntax: SyntaxNode,
}
@@ -1834,17 +1834,6 @@ impl AstNode for ConstArg {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
-impl AstNode for GenericParamList {
- fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
- fn cast(syntax: SyntaxNode) -> Option<Self> {
- if Self::can_cast(syntax.kind()) {
- Some(Self { syntax })
- } else {
- None
- }
- }
- fn syntax(&self) -> &SyntaxNode { &self.syntax }
-}
impl AstNode for TypeBoundList {
fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2153,6 +2142,17 @@ impl AstNode for Abi {
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
+impl AstNode for GenericParamList {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
impl AstNode for WhereClause {
fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4263,11 +4263,6 @@ impl std::fmt::Display for ConstArg {
std::fmt::Display::fmt(self.syntax(), f)
}
}
-impl std::fmt::Display for GenericParamList {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(self.syntax(), f)
- }
-}
impl std::fmt::Display for TypeBoundList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@@ -4408,6 +4403,11 @@ impl std::fmt::Display for Abi {
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for GenericParamList {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for WhereClause {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)