Files
rust/crates/libsyntax2/src/grammar/items/traits.rs

88 lines
2.6 KiB
Rust
Raw Normal View History

2018-02-04 13:39:24 +03:00
use super::*;
2018-07-31 18:24:30 +03:00
// test trait_item
// trait T<U>: Hash + Clone where U: Copy {}
2018-02-04 13:39:24 +03:00
pub(super) fn trait_item(p: &mut Parser) {
assert!(p.at(TRAIT_KW));
p.bump();
2018-02-10 14:15:04 +03:00
name(p);
2018-07-31 23:16:07 +03:00
type_params::type_param_list(p);
2018-07-31 18:24:30 +03:00
if p.at(COLON) {
type_params::bounds(p);
}
type_params::where_clause(p);
2018-02-04 13:39:24 +03:00
p.expect(L_CURLY);
2018-08-08 00:53:03 +03:00
// test trait_item_items
// impl F {
// type A: Clone;
// const B: i32;
// fn foo() {}
// fn bar(&self);
// }
while !p.at(EOF) && !p.at(R_CURLY) {
item_or_macro(p, true);
}
2018-02-04 13:39:24 +03:00
p.expect(R_CURLY);
}
2018-07-31 14:00:22 +03:00
// test impl_item
// impl Foo {}
2018-02-04 13:39:24 +03:00
pub(super) fn impl_item(p: &mut Parser) {
assert!(p.at(IMPL_KW));
p.bump();
2018-07-31 15:08:04 +03:00
if choose_type_params_over_qpath(p) {
2018-07-31 23:16:07 +03:00
type_params::type_param_list(p);
2018-07-31 15:08:04 +03:00
}
// 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);
2018-02-04 13:39:24 +03:00
p.expect(L_CURLY);
2018-07-31 18:03:50 +03:00
// test impl_item_items
// impl F {
// type A = i32;
// const B: i32 = 92;
// fn foo() {}
// fn bar(&self) {}
// }
while !p.at(EOF) && !p.at(R_CURLY) {
2018-08-05 14:08:46 +03:00
item_or_macro(p, true);
2018-07-31 18:03:50 +03:00
}
2018-02-04 13:39:24 +03:00
p.expect(R_CURLY);
}
2018-07-31 15:08:04 +03:00
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)
}