impl type&trait

This commit is contained in:
Aleksey Kladov 2018-07-31 15:08:04 +03:00
parent 9dcb79a602
commit 346f6e4f7d
7 changed files with 92 additions and 13 deletions

View file

@ -14,7 +14,47 @@ pub(super) fn trait_item(p: &mut Parser) {
pub(super) fn impl_item(p: &mut Parser) {
assert!(p.at(IMPL_KW));
p.bump();
p.expect(IDENT);
if choose_type_params_over_qpath(p) {
type_params::list(p);
}
// TODO: never type
// impl ! {}
// test impl_item_neg
// impl !Send for X {}
p.eat(EXCL);
types::type_(p);
if p.eat(FOR_KW) {
types::type_(p);
}
type_params::where_clause(p);
p.expect(L_CURLY);
p.expect(R_CURLY);
}
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.
// The following combinations can only start generics,
// but not qualified paths (with one exception):
// `<` `>` - empty generic parameters
// `<` `#` - generic parameters with attributes
// `<` (LIFETIME|IDENT) `>` - single generic parameter
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
// `<` (LIFETIME|IDENT) `=` - generic parameter with a default
// The only truly ambiguous case is
// `<` IDENT `>` `::` IDENT ...
// we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
// because this is what almost always expected in practice, qualified paths in impls
// (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
if !p.at(L_ANGLE) {
return false;
}
if p.nth(1) == POUND || p.nth(1) == R_ANGLE {
return true;
}
(p.nth(1) == LIFETIME || p.nth(1) == IDENT)
&& (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
}

View file

@ -3,9 +3,13 @@ FILE@[0; 19)
UNSAFE_KW@[0; 6)
WHITESPACE@[6; 7)
IMPL_KW@[7; 11)
WHITESPACE@[11; 12)
IDENT@[12; 15) "Foo"
WHITESPACE@[15; 16)
PATH_TYPE@[11; 16)
PATH@[11; 16)
PATH_SEGMENT@[11; 16)
NAME_REF@[11; 16)
WHITESPACE@[11; 12)
IDENT@[12; 15) "Foo"
WHITESPACE@[15; 16)
L_CURLY@[16; 17)
R_CURLY@[17; 18)
WHITESPACE@[18; 19)

View file

@ -5,9 +5,13 @@ FILE@[0; 27)
DEFAULT_KW@[7; 14)
WHITESPACE@[14; 15)
IMPL_KW@[15; 19)
WHITESPACE@[19; 20)
IDENT@[20; 23) "Foo"
WHITESPACE@[23; 24)
PATH_TYPE@[19; 24)
PATH@[19; 24)
PATH_SEGMENT@[19; 24)
NAME_REF@[19; 24)
WHITESPACE@[19; 20)
IDENT@[20; 23) "Foo"
WHITESPACE@[23; 24)
L_CURLY@[24; 25)
R_CURLY@[25; 26)
WHITESPACE@[26; 27)

View file

@ -3,9 +3,13 @@ FILE@[0; 20)
DEFAULT_KW@[0; 7)
WHITESPACE@[7; 8)
IMPL_KW@[8; 12)
WHITESPACE@[12; 13)
IDENT@[13; 16) "Foo"
WHITESPACE@[16; 17)
PATH_TYPE@[12; 17)
PATH@[12; 17)
PATH_SEGMENT@[12; 17)
NAME_REF@[12; 17)
WHITESPACE@[12; 13)
IDENT@[13; 16) "Foo"
WHITESPACE@[16; 17)
L_CURLY@[17; 18)
R_CURLY@[18; 19)
WHITESPACE@[19; 20)

View file

@ -1,9 +1,13 @@
FILE@[0; 12)
IMPL_ITEM@[0; 12)
IMPL_KW@[0; 4)
WHITESPACE@[4; 5)
IDENT@[5; 8) "Foo"
WHITESPACE@[8; 9)
PATH_TYPE@[4; 9)
PATH@[4; 9)
PATH_SEGMENT@[4; 9)
NAME_REF@[4; 9)
WHITESPACE@[4; 5)
IDENT@[5; 8) "Foo"
WHITESPACE@[8; 9)
L_CURLY@[9; 10)
R_CURLY@[10; 11)
WHITESPACE@[11; 12)

View file

@ -0,0 +1 @@
impl !Send for X {}

View file

@ -0,0 +1,22 @@
FILE@[0; 20)
IMPL_ITEM@[0; 20)
IMPL_KW@[0; 4)
WHITESPACE@[4; 5)
EXCL@[5; 6)
PATH_TYPE@[6; 11)
PATH@[6; 11)
PATH_SEGMENT@[6; 11)
NAME_REF@[6; 11)
IDENT@[6; 10) "Send"
WHITESPACE@[10; 11)
FOR_KW@[11; 14)
PATH_TYPE@[14; 17)
PATH@[14; 17)
PATH_SEGMENT@[14; 17)
NAME_REF@[14; 17)
WHITESPACE@[14; 15)
IDENT@[15; 16) "X"
WHITESPACE@[16; 17)
L_CURLY@[17; 18)
R_CURLY@[18; 19)
WHITESPACE@[19; 20)