Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/generic_params.rs')
-rw-r--r--crates/parser/src/grammar/generic_params.rs26
1 files changed, 15 insertions, 11 deletions
diff --git a/crates/parser/src/grammar/generic_params.rs b/crates/parser/src/grammar/generic_params.rs
index 92311238c2..9d4fdbfaf2 100644
--- a/crates/parser/src/grammar/generic_params.rs
+++ b/crates/parser/src/grammar/generic_params.rs
@@ -56,7 +56,7 @@ fn generic_param(p: &mut Parser<'_>, m: Marker) -> bool {
fn lifetime_param(p: &mut Parser<'_>, m: Marker) {
assert!(p.at(LIFETIME_IDENT));
lifetime(p);
- if p.at(T![:]) {
+ if p.eat(T![:]) {
lifetime_bounds(p);
}
m.complete(p, LIFETIME_PARAM);
@@ -106,14 +106,19 @@ fn const_param(p: &mut Parser<'_>, m: Marker) {
}
fn lifetime_bounds(p: &mut Parser<'_>) {
- assert!(p.at(T![:]));
- p.bump(T![:]);
- while p.at(LIFETIME_IDENT) {
- lifetime(p);
+ let marker = p.start();
+ while {
+ if !matches!(p.current(), LIFETIME_IDENT | T![>] | T![,]) {
+ p.error("expected lifetime");
+ }
+
+ type_bound(p)
+ } {
if !p.eat(T![+]) {
break;
}
}
+ marker.complete(p, TYPE_BOUND_LIST);
}
// test type_param_bounds
@@ -145,6 +150,9 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
T![for] => types::for_type(p, false),
// test precise_capturing
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
+
+ // test_err precise_capturing_invalid
+ // type T = impl use<self, 1>;
T![use] if p.nth_at(1, T![<]) => {
p.bump_any();
let m = p.start();
@@ -156,14 +164,10 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
|| "expected identifier or lifetime".into(),
TokenSet::new(&[T![Self], IDENT, LIFETIME_IDENT]),
|p| {
- if p.at(T![Self]) {
- let m = p.start();
- p.bump(T![Self]);
- m.complete(p, NAME_REF);
- } else if p.at(LIFETIME_IDENT) {
+ if p.at(LIFETIME_IDENT) {
lifetime(p);
} else {
- name_ref(p);
+ name_ref_or_upper_self(p);
}
true
},