use super::*;
pub(super) fn trait_def(p: &mut Parser) {
assert!(p.at(TRAIT_KW));
p.bump();
name_r(p, ITEM_RECOVERY_SET);
type_params::opt_type_param_list(p);
if p.at(COLON) {
type_params::bounds(p);
}
type_params::opt_where_clause(p);
if p.at(L_CURLY) {
trait_item_list(p);
} else {
p.error("expected `{`");
}
}
pub(crate) fn trait_item_list(p: &mut Parser) {
assert!(p.at(L_CURLY));
let m = p.start();
p.bump();
while !p.at(EOF) && !p.at(R_CURLY) {
if p.at(L_CURLY) {
error_block(p, "expected an item");
continue;
}
item_or_macro(p, true, ItemFlavor::Trait);
}
p.expect(R_CURLY);
m.complete(p, ITEM_LIST);
}
pub(super) fn impl_item(p: &mut Parser) {
assert!(p.at(IMPL_KW));
p.bump();
if choose_type_params_over_qpath(p) {
type_params::opt_type_param_list(p);
}
p.eat(EXCL);
impl_type(p);
if p.eat(FOR_KW) {
impl_type(p);
}
type_params::opt_where_clause(p);
if p.at(L_CURLY) {
impl_item_list(p);
} else {
p.error("expected `{`");
}
}
pub(crate) fn impl_item_list(p: &mut Parser) {
assert!(p.at(L_CURLY));
let m = p.start();
p.bump();
while !p.at(EOF) && !p.at(R_CURLY) {
if p.at(L_CURLY) {
error_block(p, "expected an item");
continue;
}
item_or_macro(p, true, ItemFlavor::Mod);
}
p.expect(R_CURLY);
m.complete(p, ITEM_LIST);
}
fn choose_type_params_over_qpath(p: &Parser) -> bool {
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)
}
pub(crate) fn impl_type(p: &mut Parser) {
if p.at(IMPL_KW) {
p.error("expected trait or type");
return;
}
types::type_(p);
}