Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/regression.rs11
-rw-r--r--crates/parser/src/grammar/paths.rs5
-rw-r--r--crates/parser/src/syntax_kind/generated.rs2
-rw-r--r--crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast42
-rw-r--r--crates/parser/test_data/parser/inline/ok/call_expr.rast46
-rw-r--r--crates/parser/test_data/parser/inline/ok/qual_paths.rast62
-rw-r--r--crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast9
-rw-r--r--crates/parser/test_data/parser/inline/ok/where_clause.rast31
-rw-r--r--crates/parser/test_data/parser/ok/0036_fully_qualified.rast31
-rw-r--r--crates/parser/test_data/parser/ok/0042_ufcs_call_list.rast15
-rw-r--r--crates/parser/test_data/parser/ok/0067_where_for_pred.rast31
-rw-r--r--crates/syntax/rust.ungram7
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs66
-rw-r--r--crates/syntax/src/ast/node_ext.rs23
14 files changed, 223 insertions, 158 deletions
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index cb4fcd887d..2cc3ca8c75 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -931,11 +931,12 @@ pub fn new() {
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs
index 770827c6b0..e628bcc056 100644
--- a/crates/parser/src/grammar/paths.rs
+++ b/crates/parser/src/grammar/paths.rs
@@ -89,7 +89,9 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
// test qual_paths
// type X = <A as B>::Output;
// fn foo() { <usize as Default>::default(); }
- if first && p.eat(T![<]) {
+ if first && p.at(T![<]) {
+ let m = p.start();
+ p.bump(T![<]);
// test_err angled_path_without_qual
// type X = <()>;
// type Y = <A as B>;
@@ -102,6 +104,7 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
}
}
p.expect(T![>]);
+ m.complete(p, TYPE_ANCHOR);
if !p.at(T![::]) {
p.error("expected `::`");
}
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index b1727509b1..f534546ea0 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -291,6 +291,7 @@ pub enum SyntaxKind {
TUPLE_STRUCT_PAT,
TUPLE_TYPE,
TYPE_ALIAS,
+ TYPE_ANCHOR,
TYPE_ARG,
TYPE_BOUND,
TYPE_BOUND_LIST,
@@ -463,6 +464,7 @@ impl SyntaxKind {
| TUPLE_STRUCT_PAT
| TUPLE_TYPE
| TYPE_ALIAS
+ | TYPE_ANCHOR
| TYPE_ARG
| TYPE_BOUND
| TYPE_BOUND_LIST
diff --git a/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast b/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast
index 0529e9750e..53fbe0b615 100644
--- a/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast
+++ b/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast
@@ -10,11 +10,12 @@ SOURCE_FILE
PATH_TYPE
PATH
PATH_SEGMENT
- L_ANGLE "<"
- TUPLE_TYPE
- L_PAREN "("
- R_PAREN ")"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ TUPLE_TYPE
+ L_PAREN "("
+ R_PAREN ")"
+ R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
TYPE_ALIAS
@@ -28,21 +29,22 @@ SOURCE_FILE
PATH_TYPE
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "A"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "B"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "A"
+ WHITESPACE " "
+ AS_KW "as"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "B"
+ R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
error 13: expected `::`
diff --git a/crates/parser/test_data/parser/inline/ok/call_expr.rast b/crates/parser/test_data/parser/inline/ok/call_expr.rast
index 19cc8d5ac7..7c1d894f7e 100644
--- a/crates/parser/test_data/parser/inline/ok/call_expr.rast
+++ b/crates/parser/test_data/parser/inline/ok/call_expr.rast
@@ -88,13 +88,14 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Foo"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Foo"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
@@ -119,21 +120,22 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Foo"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Trait"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Foo"
+ WHITESPACE " "
+ AS_KW "as"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Trait"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/parser/test_data/parser/inline/ok/qual_paths.rast b/crates/parser/test_data/parser/inline/ok/qual_paths.rast
index 8c66cfe599..10f8a6a751 100644
--- a/crates/parser/test_data/parser/inline/ok/qual_paths.rast
+++ b/crates/parser/test_data/parser/inline/ok/qual_paths.rast
@@ -11,21 +11,22 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "A"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "B"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "A"
+ WHITESPACE " "
+ AS_KW "as"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "B"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
@@ -51,21 +52,22 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "usize"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Default"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "usize"
+ WHITESPACE " "
+ AS_KW "as"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Default"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast b/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast
index 297f7575ca..3d27afa5ec 100644
--- a/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast
+++ b/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast
@@ -19,10 +19,11 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- INFER_TYPE
- UNDERSCORE "_"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ INFER_TYPE
+ UNDERSCORE "_"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/parser/test_data/parser/inline/ok/where_clause.rast b/crates/parser/test_data/parser/inline/ok/where_clause.rast
index a3cbe457e1..9adfe2caa7 100644
--- a/crates/parser/test_data/parser/inline/ok/where_clause.rast
+++ b/crates/parser/test_data/parser/inline/ok/where_clause.rast
@@ -84,21 +84,22 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "T"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Iterator"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ WHITESPACE " "
+ AS_KW "as"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Iterator"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/parser/test_data/parser/ok/0036_fully_qualified.rast b/crates/parser/test_data/parser/ok/0036_fully_qualified.rast
index 9382020e2f..2fecb1cc47 100644
--- a/crates/parser/test_data/parser/ok/0036_fully_qualified.rast
+++ b/crates/parser/test_data/parser/ok/0036_fully_qualified.rast
@@ -45,21 +45,22 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "S"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Iterator"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "S"
+ WHITESPACE " "
+ AS_KW "as"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Iterator"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/parser/test_data/parser/ok/0042_ufcs_call_list.rast b/crates/parser/test_data/parser/ok/0042_ufcs_call_list.rast
index a536b0e881..d1d1ffacf0 100644
--- a/crates/parser/test_data/parser/ok/0042_ufcs_call_list.rast
+++ b/crates/parser/test_data/parser/ok/0042_ufcs_call_list.rast
@@ -107,13 +107,14 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Foo"
- R_ANGLE ">"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Foo"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/parser/test_data/parser/ok/0067_where_for_pred.rast b/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
index cd3b21ae94..8bf1090f9c 100644
--- a/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
+++ b/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
@@ -288,26 +288,27 @@ SOURCE_FILE
PATH
PATH
PATH_SEGMENT
- L_ANGLE "<"
- REF_TYPE
- AMP "&"
- LIFETIME
- LIFETIME_IDENT "'a"
+ TYPE_ANCHOR
+ L_ANGLE "<"
+ REF_TYPE
+ AMP "&"
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ WHITESPACE " "
+ AS_KW "as"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
- IDENT "T"
- WHITESPACE " "
- AS_KW "as"
- WHITESPACE " "
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Baz"
- R_ANGLE ">"
+ IDENT "Baz"
+ R_ANGLE ">"
COLON2 "::"
PATH_SEGMENT
NAME_REF
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 10abca7d35..c81da06682 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -39,7 +39,10 @@ PathSegment =
| NameRef GenericArgList?
| NameRef ParenthesizedArgList RetType?
| NameRef ReturnTypeSyntax
-| '<' Type ('as' PathType)? '>'
+| TypeAnchor
+
+TypeAnchor =
+ '<' Type ('as' PathType)? '>'
ReturnTypeSyntax =
'(' '..' ')'
@@ -98,7 +101,7 @@ WhereClause =
'where' predicates:(WherePred (',' WherePred)* ','?)
WherePred =
- ('for' GenericParamList)? (Lifetime | Type) ':' TypeBoundList?
+ ('for' GenericParamList)? (Lifetime | Type) ':' TypeBoundList?
//*************************//
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index cd9f4dba89..04c7e8a578 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1232,21 +1232,13 @@ impl PathSegment {
support::child(&self.syntax)
}
#[inline]
- pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
- #[inline]
pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
#[inline]
pub fn return_type_syntax(&self) -> Option<ReturnTypeSyntax> { support::child(&self.syntax) }
#[inline]
- pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+ pub fn type_anchor(&self) -> Option<TypeAnchor> { support::child(&self.syntax) }
#[inline]
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
- #[inline]
- pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
- #[inline]
- pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
- #[inline]
- pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
}
pub struct PathType {
pub(crate) syntax: SyntaxNode,
@@ -1739,6 +1731,21 @@ impl TypeAlias {
#[inline]
pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
}
+pub struct TypeAnchor {
+ pub(crate) syntax: SyntaxNode,
+}
+impl TypeAnchor {
+ #[inline]
+ pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
+ #[inline]
+ pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+ #[inline]
+ pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+ #[inline]
+ pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+ #[inline]
+ pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+}
pub struct TypeArg {
pub(crate) syntax: SyntaxNode,
}
@@ -7108,6 +7115,42 @@ impl fmt::Debug for TypeAlias {
f.debug_struct("TypeAlias").field("syntax", &self.syntax).finish()
}
}
+impl AstNode for TypeAnchor {
+ #[inline]
+ fn kind() -> SyntaxKind
+ where
+ Self: Sized,
+ {
+ TYPE_ANCHOR
+ }
+ #[inline]
+ fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ANCHOR }
+ #[inline]
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) {
+ Some(Self { syntax })
+ } else {
+ None
+ }
+ }
+ #[inline]
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl hash::Hash for TypeAnchor {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
+}
+impl Eq for TypeAnchor {}
+impl PartialEq for TypeAnchor {
+ fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
+}
+impl Clone for TypeAnchor {
+ fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
+}
+impl fmt::Debug for TypeAnchor {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("TypeAnchor").field("syntax", &self.syntax).finish()
+ }
+}
impl AstNode for TypeArg {
#[inline]
fn kind() -> SyntaxKind
@@ -10624,6 +10667,11 @@ impl std::fmt::Display for TypeAlias {
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for TypeAnchor {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for TypeArg {
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 b9ccd34cff..dcf853427e 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -276,18 +276,15 @@ impl ast::PathSegment {
_ => PathSegmentKind::Name(name_ref),
}
} else {
- match self.syntax().first_child_or_token()?.kind() {
- T![<] => {
- // <T> or <T as Trait>
- // T is any TypeRef, Trait has to be a PathType
- let mut type_refs =
- self.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
- let type_ref = type_refs.next().and_then(ast::Type::cast);
- let trait_ref = type_refs.next().and_then(ast::PathType::cast);
- PathSegmentKind::Type { type_ref, trait_ref }
- }
- _ => return None,
- }
+ let anchor = self.type_anchor()?;
+ // FIXME: Move this over to `ast::TypeAnchor`
+ // <T> or <T as Trait>
+ // T is any TypeRef, Trait has to be a PathType
+ let mut type_refs =
+ anchor.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
+ let type_ref = type_refs.next().and_then(ast::Type::cast);
+ let trait_ref = type_refs.next().and_then(ast::PathType::cast);
+ PathSegmentKind::Type { type_ref, trait_ref }
};
Some(res)
}
@@ -473,7 +470,7 @@ impl ast::Impl {
// [#15778](https://github.com/rust-lang/rust-analyzer/issues/15778)
impl ast::PathSegment {
pub fn qualifying_trait(&self) -> Option<ast::PathType> {
- let mut path_types = support::children(self.syntax());
+ let mut path_types = support::children(self.type_anchor()?.syntax());
let first = path_types.next()?;
path_types.next().or(Some(first))
}