mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Fix GenericArgs grammar
This commit is contained in:
parent
d21b5db891
commit
040b4c800d
4 changed files with 107 additions and 50 deletions
|
@ -79,19 +79,25 @@ impl<'a> SubstituteTypeParams<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
|
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
|
||||||
// trait ref, and then go from the types in the substs back to the syntax)
|
// trait ref, and then go from the types in the substs back to the syntax).
|
||||||
fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Vec<ast::Type>> {
|
fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Vec<ast::Type>> {
|
||||||
let target_trait = impl_def.target_trait()?;
|
let target_trait = impl_def.target_trait()?;
|
||||||
let path_type = match target_trait {
|
let path_type = match target_trait {
|
||||||
ast::Type::PathType(path) => path,
|
ast::Type::PathType(path) => path,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let type_arg_list = path_type.path()?.segment()?.generic_arg_list()?;
|
let generic_arg_list = path_type.path()?.segment()?.generic_arg_list()?;
|
||||||
|
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for type_arg in type_arg_list.type_args() {
|
for generic_arg in generic_arg_list.generic_args() {
|
||||||
let type_arg: ast::TypeArg = type_arg;
|
match generic_arg {
|
||||||
result.push(type_arg.ty()?);
|
ast::GenericArg::TypeArg(type_arg) => result.push(type_arg.ty()?),
|
||||||
|
ast::GenericArg::AssocTypeArg(_)
|
||||||
|
| ast::GenericArg::LifetimeArg(_)
|
||||||
|
| ast::GenericArg::ConstArg(_) => (),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(result)
|
Some(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,14 +151,14 @@ pub(super) fn lower_generic_args(
|
||||||
node: ast::GenericArgList,
|
node: ast::GenericArgList,
|
||||||
) -> Option<GenericArgs> {
|
) -> Option<GenericArgs> {
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
for type_arg in node.type_args() {
|
let mut bindings = Vec::new();
|
||||||
|
for generic_arg in node.generic_args() {
|
||||||
|
match generic_arg {
|
||||||
|
ast::GenericArg::TypeArg(type_arg) => {
|
||||||
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
|
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
|
||||||
args.push(GenericArg::Type(type_ref));
|
args.push(GenericArg::Type(type_ref));
|
||||||
}
|
}
|
||||||
// lifetimes ignored for now
|
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
|
||||||
let mut bindings = Vec::new();
|
|
||||||
for assoc_type_arg in node.assoc_type_args() {
|
|
||||||
let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
|
|
||||||
if let Some(name_ref) = assoc_type_arg.name_ref() {
|
if let Some(name_ref) = assoc_type_arg.name_ref() {
|
||||||
let name = name_ref.as_name();
|
let name = name_ref.as_name();
|
||||||
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
|
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
|
||||||
|
@ -170,13 +170,17 @@ pub(super) fn lower_generic_args(
|
||||||
bindings.push(AssociatedTypeBinding { name, type_ref, bounds });
|
bindings.push(AssociatedTypeBinding { name, type_ref, bounds });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if args.is_empty() && bindings.is_empty() {
|
// Lifetimes and constants are ignored for now.
|
||||||
None
|
ast::GenericArg::LifetimeArg(_) | ast::GenericArg::ConstArg(_) => (),
|
||||||
} else {
|
|
||||||
Some(GenericArgs { args, has_self_type: false, bindings })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.is_empty() && bindings.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(GenericArgs { args, has_self_type: false, bindings })
|
||||||
|
}
|
||||||
|
|
||||||
/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
|
/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
|
||||||
/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
|
/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
|
||||||
fn lower_generic_args_from_fn_path(
|
fn lower_generic_args_from_fn_path(
|
||||||
|
|
|
@ -46,10 +46,7 @@ pub struct GenericArgList {
|
||||||
impl GenericArgList {
|
impl GenericArgList {
|
||||||
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
|
pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
|
||||||
pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
|
pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
|
||||||
pub fn type_args(&self) -> AstChildren<TypeArg> { support::children(&self.syntax) }
|
pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
|
||||||
pub fn lifetime_args(&self) -> AstChildren<LifetimeArg> { support::children(&self.syntax) }
|
|
||||||
pub fn assoc_type_args(&self) -> AstChildren<AssocTypeArg> { support::children(&self.syntax) }
|
|
||||||
pub fn const_args(&self) -> AstChildren<ConstArg> { support::children(&self.syntax) }
|
|
||||||
pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
|
pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -86,15 +83,6 @@ impl TypeArg {
|
||||||
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
|
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct LifetimeArg {
|
|
||||||
pub(crate) syntax: SyntaxNode,
|
|
||||||
}
|
|
||||||
impl LifetimeArg {
|
|
||||||
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
|
|
||||||
support::token(&self.syntax, T![lifetime])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub struct AssocTypeArg {
|
pub struct AssocTypeArg {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
}
|
}
|
||||||
|
@ -105,6 +93,15 @@ impl AssocTypeArg {
|
||||||
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
|
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct LifetimeArg {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
impl LifetimeArg {
|
||||||
|
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
|
||||||
|
support::token(&self.syntax, T![lifetime])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstArg {
|
pub struct ConstArg {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
}
|
}
|
||||||
|
@ -1272,6 +1269,13 @@ impl MacroStmts {
|
||||||
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum GenericArg {
|
||||||
|
TypeArg(TypeArg),
|
||||||
|
AssocTypeArg(AssocTypeArg),
|
||||||
|
LifetimeArg(LifetimeArg),
|
||||||
|
ConstArg(ConstArg),
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
ArrayType(ArrayType),
|
ArrayType(ArrayType),
|
||||||
DynTraitType(DynTraitType),
|
DynTraitType(DynTraitType),
|
||||||
|
@ -1489,8 +1493,8 @@ impl AstNode for TypeArg {
|
||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
impl AstNode for LifetimeArg {
|
impl AstNode for AssocTypeArg {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
if Self::can_cast(syntax.kind()) {
|
if Self::can_cast(syntax.kind()) {
|
||||||
Some(Self { syntax })
|
Some(Self { syntax })
|
||||||
|
@ -1500,8 +1504,8 @@ impl AstNode for LifetimeArg {
|
||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
impl AstNode for AssocTypeArg {
|
impl AstNode for LifetimeArg {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
if Self::can_cast(syntax.kind()) {
|
if Self::can_cast(syntax.kind()) {
|
||||||
Some(Self { syntax })
|
Some(Self { syntax })
|
||||||
|
@ -2765,6 +2769,44 @@ impl AstNode for MacroStmts {
|
||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
|
impl From<TypeArg> for GenericArg {
|
||||||
|
fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) }
|
||||||
|
}
|
||||||
|
impl From<AssocTypeArg> for GenericArg {
|
||||||
|
fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) }
|
||||||
|
}
|
||||||
|
impl From<LifetimeArg> for GenericArg {
|
||||||
|
fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) }
|
||||||
|
}
|
||||||
|
impl From<ConstArg> for GenericArg {
|
||||||
|
fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
|
||||||
|
}
|
||||||
|
impl AstNode for GenericArg {
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
|
match kind {
|
||||||
|
TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
let res = match syntax.kind() {
|
||||||
|
TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
|
||||||
|
ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
|
||||||
|
LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
|
||||||
|
CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
GenericArg::TypeArg(it) => &it.syntax,
|
||||||
|
GenericArg::AssocTypeArg(it) => &it.syntax,
|
||||||
|
GenericArg::LifetimeArg(it) => &it.syntax,
|
||||||
|
GenericArg::ConstArg(it) => &it.syntax,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<ArrayType> for Type {
|
impl From<ArrayType> for Type {
|
||||||
fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
|
fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
|
||||||
}
|
}
|
||||||
|
@ -3380,6 +3422,11 @@ impl From<Item> for Stmt {
|
||||||
impl From<LetStmt> for Stmt {
|
impl From<LetStmt> for Stmt {
|
||||||
fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
|
fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for GenericArg {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::fmt::Display for Type {
|
impl std::fmt::Display for Type {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
@ -3470,12 +3517,12 @@ impl std::fmt::Display for TypeArg {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for LifetimeArg {
|
impl std::fmt::Display for AssocTypeArg {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for AssocTypeArg {
|
impl std::fmt::Display for LifetimeArg {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ PathSegment =
|
||||||
| '<' PathType ('as' PathType)? '>'
|
| '<' PathType ('as' PathType)? '>'
|
||||||
|
|
||||||
GenericArgList =
|
GenericArgList =
|
||||||
'::'? '<'
|
'::'? '<' (GenericArg (',' GenericArg)* ','?)? '>'
|
||||||
TypeArg*
|
|
||||||
LifetimeArg*
|
GenericArg =
|
||||||
AssocTypeArg*
|
TypeArg
|
||||||
ConstArg*
|
| AssocTypeArg
|
||||||
'>'
|
| LifetimeArg
|
||||||
|
| ConstArg
|
||||||
|
|
||||||
TypeArg =
|
TypeArg =
|
||||||
Type
|
Type
|
||||||
|
@ -27,7 +28,6 @@ LifetimeArg =
|
||||||
ConstArg =
|
ConstArg =
|
||||||
Literal | BlockExpr BlockExpr
|
Literal | BlockExpr BlockExpr
|
||||||
|
|
||||||
|
|
||||||
SourceFile =
|
SourceFile =
|
||||||
'shebang'?
|
'shebang'?
|
||||||
Attr*
|
Attr*
|
||||||
|
|
Loading…
Reference in a new issue