Skip to content

Commit

Permalink
(GRAM): allow empty type parameter lists
Browse files Browse the repository at this point in the history
This is valid Rust:
rust-lang/rust#32023
  • Loading branch information
matklad committed Mar 9, 2016
1 parent 07a4fb5 commit 5b033c9
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 6 deletions.
7 changes: 1 addition & 6 deletions src/main/kotlin/org/rust/lang/core/grammar/rust.bnf
Expand Up @@ -370,12 +370,7 @@ generic_params ::= [ generic_params_inner ]

private generic_params_inner ::= LT lifetimes [ COMMA [ type_params COMMA? ] ] GT
| LT type_params COMMA? GT
/* | LT lifetimes GTGT
| LT lifetimes COMMA GTGT */
/* | LT lifetimes COMMA type_params GTGT
| LT lifetimes COMMA type_params COMMA GTGT */
/* | LT type_params SHR
| LT type_params COMMA SHR */
| LT GT

lifetimes ::= lifetime_and_bounds (COMMA lifetime_and_bounds)*

Expand Down
Expand Up @@ -30,5 +30,6 @@ class RustCompleteParsingTestCase : RustParsingTestCaseBase("well-formed") {
fun testSuperPaths() = doTest(true)
fun testPrecedence() = doTest(true)
fun testWayTooManyParens() = doTest(true)
fun testEmptyGenerics() = doTest(true)
// @formatter:on
}
@@ -0,0 +1,23 @@
// Test that empty type parameter list (<>) is synonymous with
// no type parameters at all

struct S<>;
trait T<> {}
enum E<> { V }
impl<> T<> for S<> {}
impl T for E {}
fn foo<>() {}
fn bar() {}

fn main() {
let _ = S;
let _ = S::<>;
let _ = E::V;
let _ = E::<>::V;
foo();
foo::<>();

// Test that we can supply <> to non generic things
bar::<>();
let _: i32<>;
}
@@ -0,0 +1,252 @@
FILE
PsiComment(<EOL_COMMENT>)('// Test that empty type parameter list (<>) is synonymous with')
PsiWhiteSpace('\n')
PsiComment(<EOL_COMMENT>)('// no type parameters at all')
PsiWhiteSpace('\n\n')
RustFileModItemImpl(FILE_MOD_ITEM)
RustStructItemImpl(STRUCT_ITEM)
PsiElement(struct)('struct')
PsiWhiteSpace(' ')
PsiElement(<IDENTIFIER>)('S')
RustGenericParamsImpl(GENERIC_PARAMS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiElement(;)(';')
PsiWhiteSpace('\n')
RustTraitItemImpl(TRAIT_ITEM)
PsiElement(trait)('trait')
PsiWhiteSpace(' ')
PsiElement(<IDENTIFIER>)('T')
RustGenericParamsImpl(GENERIC_PARAMS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiWhiteSpace(' ')
PsiElement({)('{')
PsiElement(})('}')
PsiWhiteSpace('\n')
RustEnumItemImpl(ENUM_ITEM)
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(<IDENTIFIER>)('E')
RustGenericParamsImpl(GENERIC_PARAMS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiWhiteSpace(' ')
PsiElement({)('{')
PsiWhiteSpace(' ')
RustEnumDefImpl(ENUM_DEF)
PsiElement(<IDENTIFIER>)('V')
PsiWhiteSpace(' ')
PsiElement(})('}')
PsiWhiteSpace('\n')
RustImplItemImpl(IMPL_ITEM)
PsiElement(impl)('impl')
RustGenericParamsImpl(GENERIC_PARAMS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiWhiteSpace(' ')
RustTraitRefImpl(TRAIT_REF)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('T')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiWhiteSpace(' ')
PsiElement(for)('for')
PsiWhiteSpace(' ')
RustTypeSumImpl(TYPE_SUM)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('S')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiWhiteSpace(' ')
PsiElement({)('{')
PsiElement(})('}')
PsiWhiteSpace('\n')
RustImplItemImpl(IMPL_ITEM)
PsiElement(impl)('impl')
PsiWhiteSpace(' ')
RustGenericParamsImpl(GENERIC_PARAMS)
<empty list>
RustTraitRefImpl(TRAIT_REF)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('T')
PsiWhiteSpace(' ')
PsiElement(for)('for')
PsiWhiteSpace(' ')
RustTypeSumImpl(TYPE_SUM)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('E')
PsiWhiteSpace(' ')
PsiElement({)('{')
PsiElement(})('}')
PsiWhiteSpace('\n')
RustFnItemImpl(FN_ITEM)
PsiElement(fn)('fn')
PsiWhiteSpace(' ')
PsiElement(<IDENTIFIER>)('foo')
RustGenericParamsImpl(GENERIC_PARAMS)
PsiElement(<)('<')
PsiElement(>)('>')
RustFnParamsImpl(FN_PARAMS)
PsiElement(()('(')
PsiElement())(')')
PsiWhiteSpace(' ')
RustBlockImpl(BLOCK)
PsiElement({)('{')
PsiElement(})('}')
PsiWhiteSpace('\n')
RustFnItemImpl(FN_ITEM)
PsiElement(fn)('fn')
PsiWhiteSpace(' ')
PsiElement(<IDENTIFIER>)('bar')
RustGenericParamsImpl(GENERIC_PARAMS)
<empty list>
RustFnParamsImpl(FN_PARAMS)
PsiElement(()('(')
PsiElement())(')')
PsiWhiteSpace(' ')
RustBlockImpl(BLOCK)
PsiElement({)('{')
PsiElement(})('}')
PsiWhiteSpace('\n\n')
RustFnItemImpl(FN_ITEM)
PsiElement(fn)('fn')
PsiWhiteSpace(' ')
PsiElement(<IDENTIFIER>)('main')
RustGenericParamsImpl(GENERIC_PARAMS)
<empty list>
RustFnParamsImpl(FN_PARAMS)
PsiElement(()('(')
PsiElement())(')')
PsiWhiteSpace(' ')
RustBlockImpl(BLOCK)
PsiElement({)('{')
PsiWhiteSpace('\n ')
RustDeclStmtImpl(DECL_STMT)
RustLetDeclImpl(LET_DECL)
PsiElement(let)('let')
PsiWhiteSpace(' ')
RustPatWildImpl(PAT_WILD)
PsiElement(_)('_')
PsiWhiteSpace(' ')
PsiElement(=)('=')
PsiWhiteSpace(' ')
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('S')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustDeclStmtImpl(DECL_STMT)
RustLetDeclImpl(LET_DECL)
PsiElement(let)('let')
PsiWhiteSpace(' ')
RustPatWildImpl(PAT_WILD)
PsiElement(_)('_')
PsiWhiteSpace(' ')
PsiElement(=)('=')
PsiWhiteSpace(' ')
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('S')
PsiElement(::)('::')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustDeclStmtImpl(DECL_STMT)
RustLetDeclImpl(LET_DECL)
PsiElement(let)('let')
PsiWhiteSpace(' ')
RustPatWildImpl(PAT_WILD)
PsiElement(_)('_')
PsiWhiteSpace(' ')
PsiElement(=)('=')
PsiWhiteSpace(' ')
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('E')
PsiElement(::)('::')
PsiElement(<IDENTIFIER>)('V')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustDeclStmtImpl(DECL_STMT)
RustLetDeclImpl(LET_DECL)
PsiElement(let)('let')
PsiWhiteSpace(' ')
RustPatWildImpl(PAT_WILD)
PsiElement(_)('_')
PsiWhiteSpace(' ')
PsiElement(=)('=')
PsiWhiteSpace(' ')
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('E')
PsiElement(::)('::')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiElement(::)('::')
PsiElement(<IDENTIFIER>)('V')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustExprStmtImpl(EXPR_STMT)
RustCallExprImpl(CALL_EXPR)
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('foo')
RustArgListImpl(ARG_LIST)
PsiElement(()('(')
PsiElement())(')')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustExprStmtImpl(EXPR_STMT)
RustCallExprImpl(CALL_EXPR)
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('foo')
PsiElement(::)('::')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
RustArgListImpl(ARG_LIST)
PsiElement(()('(')
PsiElement())(')')
PsiElement(;)(';')
PsiWhiteSpace('\n\n ')
PsiComment(<EOL_COMMENT>)('// Test that we can supply <> to non generic things')
PsiWhiteSpace('\n ')
RustExprStmtImpl(EXPR_STMT)
RustCallExprImpl(CALL_EXPR)
RustPathExprImpl(PATH_EXPR)
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('bar')
PsiElement(::)('::')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
RustArgListImpl(ARG_LIST)
PsiElement(()('(')
PsiElement())(')')
PsiElement(;)(';')
PsiWhiteSpace('\n ')
RustDeclStmtImpl(DECL_STMT)
RustLetDeclImpl(LET_DECL)
PsiElement(let)('let')
PsiWhiteSpace(' ')
RustPatWildImpl(PAT_WILD)
PsiElement(_)('_')
PsiElement(:)(':')
PsiWhiteSpace(' ')
RustPathPartImpl(PATH_PART)
PsiElement(<IDENTIFIER>)('i32')
RustGenericArgsImpl(GENERIC_ARGS)
PsiElement(<)('<')
PsiElement(>)('>')
PsiElement(;)(';')
PsiWhiteSpace('\n')
PsiElement(})('}')

0 comments on commit 5b033c9

Please sign in to comment.