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);
}
// test impl_type_params
// impl<const N: u32> Bar<N> {}
fn choose_type_params_over_qpath(p: &Parser) -> bool {
// 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.
@ -107,6 +109,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool {
// but not qualified paths (with one exception):
// `<` `>` - empty generic parameters
// `<` `#` - generic parameters with attributes
// `<` `const` - const generic parameters
// `<` (LIFETIME|IDENT) `>` - single generic parameter
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
@ -119,7 +122,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool {
if !p.at(T![<]) {
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;
}
(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
// type A = B<'static, i32, Item=u64>;
// type A = B<'static, i32, 1, { 2 }, Item=u64>;
fn type_arg(p: &mut Parser) {
let m = p.start();
match p.current() {
@ -47,6 +47,14 @@ fn type_arg(p: &mut Parser) {
types::type_(p);
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);
m.complete(p, TYPE_ARG);

View file

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

View file

@ -3114,6 +3114,9 @@ impl TypeArgList {
pub fn assoc_type_args(&self) -> AstChildren<AssocTypeArg> {
AstChildren::new(&self.syntax)
}
pub fn const_arg(&self) -> AstChildren<ConstArg> {
AstChildren::new(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeArg {
@ -3196,6 +3199,36 @@ impl AstNode for LifetimeArg {
}
impl LifetimeArg {}
#[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(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)
TYPE_ALIAS_DEF@[0; 35)
SOURCE_FILE@[0; 46)
TYPE_ALIAS_DEF@[0; 45)
TYPE_KW@[0; 4) "type"
WHITESPACE@[4; 5) " "
NAME@[5; 6)
@ -7,12 +7,12 @@ SOURCE_FILE@[0; 36)
WHITESPACE@[6; 7) " "
EQ@[7; 8) "="
WHITESPACE@[8; 9) " "
PATH_TYPE@[9; 34)
PATH@[9; 34)
PATH_SEGMENT@[9; 34)
PATH_TYPE@[9; 44)
PATH@[9; 44)
PATH_SEGMENT@[9; 44)
NAME_REF@[9; 10)
IDENT@[9; 10) "B"
TYPE_ARG_LIST@[10; 34)
TYPE_ARG_LIST@[10; 44)
L_ANGLE@[10; 11) "<"
LIFETIME_ARG@[11; 18)
LIFETIME@[11; 18) "\'static"
@ -26,15 +26,30 @@ SOURCE_FILE@[0; 36)
IDENT@[20; 23) "i32"
COMMA@[23; 24) ","
WHITESPACE@[24; 25) " "
ASSOC_TYPE_ARG@[25; 33)
NAME_REF@[25; 29)
IDENT@[25; 29) "Item"
EQ@[29; 30) "="
PATH_TYPE@[30; 33)
PATH@[30; 33)
PATH_SEGMENT@[30; 33)
NAME_REF@[30; 33)
IDENT@[30; 33) "u64"
R_ANGLE@[33; 34) ">"
SEMI@[34; 35) ";"
WHITESPACE@[35; 36) "\n"
CONST_ARG@[25; 26)
INT_NUMBER@[25; 26) "1"
COMMA@[26; 27) ","
WHITESPACE@[27; 28) " "
CONST_ARG@[28; 33)
BLOCK_EXPR@[28; 33)
BLOCK@[28; 33)
L_CURLY@[28; 29) "{"
WHITESPACE@[29; 30) " "
LITERAL@[30; 31)
INT_NUMBER@[30; 31) "2"
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",
"TYPE_ARG",
"ASSOC_TYPE_ARG",
"CONST_ARG",
"PARAM_LIST",
"PARAM",
"SELF_PARAM",
@ -511,10 +512,12 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
type_args: [TypeArg],
lifetime_args: [LifetimeArg],
assoc_type_args: [AssocTypeArg],
const_arg: [ConstArg],
}
struct TypeArg { TypeRef }
struct AssocTypeArg { NameRef, TypeRef }
struct LifetimeArg {}
struct ConstArg { Literal, BlockExpr }
struct MacroItems: ModuleItemOwner, FnDefOwner { }