From 346f6e4f7d364b009d0feb66162314abfd06c81b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Jul 2018 15:08:04 +0300 Subject: impl type&trait --- src/parser/grammar/items/traits.rs | 42 +++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'src/parser/grammar') diff --git a/src/parser/grammar/items/traits.rs b/src/parser/grammar/items/traits.rs index 7fd011ffd..c7450b761 100644 --- a/src/parser/grammar/items/traits.rs +++ b/src/parser/grammar/items/traits.rs @@ -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 ::absolute::Path { ... }`) + // because this is what almost always expected in practice, qualified paths in impls + // (`impl ::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) +} -- cgit v1.2.3