Improve const generics parsing

- Handle const generics type args
- Fix issue with const generic as first parameter in trait impl
This commit is contained in:
Michael Chesser 2020-01-07 09:29:03 +10:30
parent c92a090f49
commit ce1b34fd59
9 changed files with 123 additions and 21 deletions

View file

@ -100,6 +100,8 @@ pub(crate) fn impl_item_list(p: &mut Parser) {
m.complete(p, ITEM_LIST); m.complete(p, ITEM_LIST);
} }
// test impl_type_params
// impl<const N: u32> Bar<N> {}
fn choose_type_params_over_qpath(p: &Parser) -> bool { fn choose_type_params_over_qpath(p: &Parser) -> bool {
// There's an ambiguity between generic parameters and qualified paths in impls. // There's an ambiguity between generic parameters and qualified paths in impls.
// If we see `<` it may start both, so we have to inspect some following tokens. // If we see `<` it may start both, so we have to inspect some following tokens.
@ -107,6 +109,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool {
// but not qualified paths (with one exception): // but not qualified paths (with one exception):
// `<` `>` - empty generic parameters // `<` `>` - empty generic parameters
// `<` `#` - generic parameters with attributes // `<` `#` - generic parameters with attributes
// `<` `const` - const generic parameters
// `<` (LIFETIME|IDENT) `>` - single generic parameter // `<` (LIFETIME|IDENT) `>` - single generic parameter
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
@ -119,7 +122,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool {
if !p.at(T![<]) { if !p.at(T![<]) {
return false; return false;
} }
if p.nth(1) == T![#] || p.nth(1) == T![>] { if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == CONST_KW {
return true; return true;
} }
(p.nth(1) == LIFETIME || p.nth(1) == IDENT) (p.nth(1) == LIFETIME || p.nth(1) == IDENT)

View file

@ -26,7 +26,7 @@ pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
} }
// test type_arg // test type_arg
// type A = B<'static, i32, Item=u64>; // type A = B<'static, i32, 1, { 2 }, Item=u64>;
fn type_arg(p: &mut Parser) { fn type_arg(p: &mut Parser) {
let m = p.start(); let m = p.start();
match p.current() { match p.current() {
@ -47,6 +47,14 @@ fn type_arg(p: &mut Parser) {
types::type_(p); types::type_(p);
m.complete(p, ASSOC_TYPE_ARG); m.complete(p, ASSOC_TYPE_ARG);
} }
T!['{'] => {
expressions::block(p);
m.complete(p, CONST_ARG);
}
k if k.is_literal() => {
p.bump(k);
m.complete(p, CONST_ARG);
}
_ => { _ => {
types::type_(p); types::type_(p);
m.complete(p, TYPE_ARG); m.complete(p, TYPE_ARG);

View file

@ -234,6 +234,7 @@ pub enum SyntaxKind {
LIFETIME_ARG, LIFETIME_ARG,
TYPE_ARG, TYPE_ARG,
ASSOC_TYPE_ARG, ASSOC_TYPE_ARG,
CONST_ARG,
PARAM_LIST, PARAM_LIST,
PARAM, PARAM,
SELF_PARAM, SELF_PARAM,

View file

@ -3114,6 +3114,9 @@ impl TypeArgList {
pub fn assoc_type_args(&self) -> AstChildren<AssocTypeArg> { pub fn assoc_type_args(&self) -> AstChildren<AssocTypeArg> {
AstChildren::new(&self.syntax) AstChildren::new(&self.syntax)
} }
pub fn const_arg(&self) -> AstChildren<ConstArg> {
AstChildren::new(&self.syntax)
}
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeArg { pub struct TypeArg {
@ -3196,6 +3199,36 @@ impl AstNode for LifetimeArg {
} }
impl LifetimeArg {} impl LifetimeArg {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ConstArg {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for ConstArg {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
CONST_ARG => true,
_ => false,
}
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl ConstArg {
pub fn literal(&self) -> Option<Literal> {
AstChildren::new(&self.syntax).next()
}
pub fn block_expr(&self) -> Option<BlockExpr> {
AstChildren::new(&self.syntax).next()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroItems { pub struct MacroItems {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }

View file

@ -1 +1 @@
type A = B<'static, i32, Item=u64>; type A = B<'static, i32, 1, { 2 }, Item=u64>;

View file

@ -1,5 +1,5 @@
SOURCE_FILE@[0; 36) SOURCE_FILE@[0; 46)
TYPE_ALIAS_DEF@[0; 35) TYPE_ALIAS_DEF@[0; 45)
TYPE_KW@[0; 4) "type" TYPE_KW@[0; 4) "type"
WHITESPACE@[4; 5) " " WHITESPACE@[4; 5) " "
NAME@[5; 6) NAME@[5; 6)
@ -7,12 +7,12 @@ SOURCE_FILE@[0; 36)
WHITESPACE@[6; 7) " " WHITESPACE@[6; 7) " "
EQ@[7; 8) "=" EQ@[7; 8) "="
WHITESPACE@[8; 9) " " WHITESPACE@[8; 9) " "
PATH_TYPE@[9; 34) PATH_TYPE@[9; 44)
PATH@[9; 34) PATH@[9; 44)
PATH_SEGMENT@[9; 34) PATH_SEGMENT@[9; 44)
NAME_REF@[9; 10) NAME_REF@[9; 10)
IDENT@[9; 10) "B" IDENT@[9; 10) "B"
TYPE_ARG_LIST@[10; 34) TYPE_ARG_LIST@[10; 44)
L_ANGLE@[10; 11) "<" L_ANGLE@[10; 11) "<"
LIFETIME_ARG@[11; 18) LIFETIME_ARG@[11; 18)
LIFETIME@[11; 18) "\'static" LIFETIME@[11; 18) "\'static"
@ -26,15 +26,30 @@ SOURCE_FILE@[0; 36)
IDENT@[20; 23) "i32" IDENT@[20; 23) "i32"
COMMA@[23; 24) "," COMMA@[23; 24) ","
WHITESPACE@[24; 25) " " WHITESPACE@[24; 25) " "
ASSOC_TYPE_ARG@[25; 33) CONST_ARG@[25; 26)
NAME_REF@[25; 29) INT_NUMBER@[25; 26) "1"
IDENT@[25; 29) "Item" COMMA@[26; 27) ","
EQ@[29; 30) "=" WHITESPACE@[27; 28) " "
PATH_TYPE@[30; 33) CONST_ARG@[28; 33)
PATH@[30; 33) BLOCK_EXPR@[28; 33)
PATH_SEGMENT@[30; 33) BLOCK@[28; 33)
NAME_REF@[30; 33) L_CURLY@[28; 29) "{"
IDENT@[30; 33) "u64" WHITESPACE@[29; 30) " "
R_ANGLE@[33; 34) ">" LITERAL@[30; 31)
SEMI@[34; 35) ";" INT_NUMBER@[30; 31) "2"
WHITESPACE@[35; 36) "\n" WHITESPACE@[31; 32) " "
R_CURLY@[32; 33) "}"
COMMA@[33; 34) ","
WHITESPACE@[34; 35) " "
ASSOC_TYPE_ARG@[35; 43)
NAME_REF@[35; 39)
IDENT@[35; 39) "Item"
EQ@[39; 40) "="
PATH_TYPE@[40; 43)
PATH@[40; 43)
PATH_SEGMENT@[40; 43)
NAME_REF@[40; 43)
IDENT@[40; 43) "u64"
R_ANGLE@[43; 44) ">"
SEMI@[44; 45) ";"
WHITESPACE@[45; 46) "\n"

View file

@ -0,0 +1 @@
impl<const N: u32> Bar<N> {}

View file

@ -0,0 +1,38 @@
SOURCE_FILE@[0; 29)
IMPL_BLOCK@[0; 28)
IMPL_KW@[0; 4) "impl"
TYPE_PARAM_LIST@[4; 18)
L_ANGLE@[4; 5) "<"
CONST_PARAM@[5; 17)
CONST_KW@[5; 10) "const"
WHITESPACE@[10; 11) " "
NAME@[11; 12)
IDENT@[11; 12) "N"
COLON@[12; 13) ":"
WHITESPACE@[13; 14) " "
PATH_TYPE@[14; 17)
PATH@[14; 17)
PATH_SEGMENT@[14; 17)
NAME_REF@[14; 17)
IDENT@[14; 17) "u32"
R_ANGLE@[17; 18) ">"
WHITESPACE@[18; 19) " "
PATH_TYPE@[19; 25)
PATH@[19; 25)
PATH_SEGMENT@[19; 25)
NAME_REF@[19; 22)
IDENT@[19; 22) "Bar"
TYPE_ARG_LIST@[22; 25)
L_ANGLE@[22; 23) "<"
TYPE_ARG@[23; 24)
PATH_TYPE@[23; 24)
PATH@[23; 24)
PATH_SEGMENT@[23; 24)
NAME_REF@[23; 24)
IDENT@[23; 24) "N"
R_ANGLE@[24; 25) ">"
WHITESPACE@[25; 26) " "
ITEM_LIST@[26; 28)
L_CURLY@[26; 27) "{"
R_CURLY@[27; 28) "}"
WHITESPACE@[28; 29) "\n"

View file

@ -206,6 +206,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
"LIFETIME_ARG", "LIFETIME_ARG",
"TYPE_ARG", "TYPE_ARG",
"ASSOC_TYPE_ARG", "ASSOC_TYPE_ARG",
"CONST_ARG",
"PARAM_LIST", "PARAM_LIST",
"PARAM", "PARAM",
"SELF_PARAM", "SELF_PARAM",
@ -511,10 +512,12 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
type_args: [TypeArg], type_args: [TypeArg],
lifetime_args: [LifetimeArg], lifetime_args: [LifetimeArg],
assoc_type_args: [AssocTypeArg], assoc_type_args: [AssocTypeArg],
const_arg: [ConstArg],
} }
struct TypeArg { TypeRef } struct TypeArg { TypeRef }
struct AssocTypeArg { NameRef, TypeRef } struct AssocTypeArg { NameRef, TypeRef }
struct LifetimeArg {} struct LifetimeArg {}
struct ConstArg { Literal, BlockExpr }
struct MacroItems: ModuleItemOwner, FnDefOwner { } struct MacroItems: ModuleItemOwner, FnDefOwner { }