2018-02-02 23:23:39 +03:00
|
|
|
use super::*;
|
|
|
|
|
|
2020-08-13 17:58:35 +02:00
|
|
|
pub(super) fn opt_generic_param_list(p: &mut Parser) {
|
2021-09-18 15:46:28 +03:00
|
|
|
if p.at(T![<]) {
|
|
|
|
|
generic_param_list(p);
|
2018-02-02 23:23:39 +03:00
|
|
|
}
|
2018-11-05 11:24:02 +03:00
|
|
|
}
|
|
|
|
|
|
2021-09-18 15:46:28 +03:00
|
|
|
// test generic_param_list
|
|
|
|
|
// fn f<T: Clone>() {}
|
2020-08-13 17:58:35 +02:00
|
|
|
fn generic_param_list(p: &mut Parser) {
|
2019-05-15 15:35:47 +03:00
|
|
|
assert!(p.at(T![<]));
|
2018-02-02 23:23:39 +03:00
|
|
|
let m = p.start();
|
2019-09-19 15:51:46 -04:00
|
|
|
p.bump(T![<]);
|
2018-02-02 23:23:39 +03:00
|
|
|
|
2019-05-15 15:35:47 +03:00
|
|
|
while !p.at(EOF) && !p.at(T![>]) {
|
2021-09-18 15:56:26 +03:00
|
|
|
generic_param(p);
|
2019-05-15 15:35:47 +03:00
|
|
|
if !p.at(T![>]) && !p.expect(T![,]) {
|
2018-02-02 23:23:39 +03:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-15 15:35:47 +03:00
|
|
|
p.expect(T![>]);
|
2020-07-30 15:36:21 +02:00
|
|
|
m.complete(p, GENERIC_PARAM_LIST);
|
2018-11-05 11:24:02 +03:00
|
|
|
}
|
2018-02-02 23:23:39 +03:00
|
|
|
|
2021-09-18 15:56:26 +03:00
|
|
|
fn generic_param(p: &mut Parser) {
|
|
|
|
|
let m = p.start();
|
|
|
|
|
// test generic_param_attribute
|
|
|
|
|
// fn foo<#[lt_attr] 'a, #[t_attr] T>() {}
|
|
|
|
|
attributes::outer_attrs(p);
|
|
|
|
|
match p.current() {
|
|
|
|
|
LIFETIME_IDENT => lifetime_param(p, m),
|
|
|
|
|
IDENT => type_param(p, m),
|
|
|
|
|
T![const] => const_param(p, m),
|
|
|
|
|
_ => {
|
|
|
|
|
m.abandon(p);
|
2021-10-03 23:39:43 +11:00
|
|
|
p.err_and_bump("expected type parameter");
|
2021-09-18 15:56:26 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-18 15:46:28 +03:00
|
|
|
// test lifetime_param
|
|
|
|
|
// fn f<'a: 'b>() {}
|
2019-02-17 22:19:21 +02:00
|
|
|
fn lifetime_param(p: &mut Parser, m: Marker) {
|
2020-12-15 19:23:51 +01:00
|
|
|
assert!(p.at(LIFETIME_IDENT));
|
|
|
|
|
lifetime(p);
|
2019-05-15 15:35:47 +03:00
|
|
|
if p.at(T![:]) {
|
2018-11-05 11:24:02 +03:00
|
|
|
lifetime_bounds(p);
|
2018-02-02 23:23:39 +03:00
|
|
|
}
|
2018-11-05 11:24:02 +03:00
|
|
|
m.complete(p, LIFETIME_PARAM);
|
|
|
|
|
}
|
2018-02-02 23:23:39 +03:00
|
|
|
|
2021-09-18 15:46:28 +03:00
|
|
|
// test type_param
|
|
|
|
|
// fn f<T: Clone>() {}
|
2019-02-17 22:19:21 +02:00
|
|
|
fn type_param(p: &mut Parser, m: Marker) {
|
2018-11-05 11:24:02 +03:00
|
|
|
assert!(p.at(IDENT));
|
|
|
|
|
name(p);
|
2019-05-15 15:35:47 +03:00
|
|
|
if p.at(T![:]) {
|
2018-11-05 11:24:02 +03:00
|
|
|
bounds(p);
|
|
|
|
|
}
|
2019-05-15 15:35:47 +03:00
|
|
|
if p.at(T![=]) {
|
2021-09-18 15:46:28 +03:00
|
|
|
// test type_param_default
|
|
|
|
|
// struct S<T = i32>;
|
2019-09-19 15:51:46 -04:00
|
|
|
p.bump(T![=]);
|
2021-10-03 23:39:43 +11:00
|
|
|
types::type_(p);
|
2018-02-02 23:23:39 +03:00
|
|
|
}
|
2018-11-05 11:24:02 +03:00
|
|
|
m.complete(p, TYPE_PARAM);
|
2018-02-02 23:23:39 +03:00
|
|
|
}
|
|
|
|
|
|
2019-12-22 00:38:23 +00:00
|
|
|
// test const_param
|
|
|
|
|
// struct S<const N: u32>;
|
2020-08-13 17:58:35 +02:00
|
|
|
fn const_param(p: &mut Parser, m: Marker) {
|
2019-12-22 00:38:23 +00:00
|
|
|
p.bump(T![const]);
|
|
|
|
|
name(p);
|
2021-07-17 22:41:04 +03:00
|
|
|
if p.at(T![:]) {
|
|
|
|
|
types::ascription(p);
|
|
|
|
|
} else {
|
|
|
|
|
p.error("missing type for const parameter");
|
|
|
|
|
}
|
2021-04-29 03:07:53 +02:00
|
|
|
|
|
|
|
|
if p.at(T![=]) {
|
2022-03-11 19:22:49 +00:00
|
|
|
// test const_param_default_literal
|
2021-09-18 15:46:28 +03:00
|
|
|
// struct A<const N: i32 = -1>;
|
2021-04-29 03:07:53 +02:00
|
|
|
p.bump(T![=]);
|
2022-03-11 19:22:49 +00:00
|
|
|
|
|
|
|
|
// test const_param_default_expression
|
|
|
|
|
// struct A<const N: i32 = { 1 }>;
|
2022-03-11 20:38:03 +00:00
|
|
|
generic_args::const_arg_expr(p);
|
2021-04-29 03:07:53 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-22 00:38:23 +00:00
|
|
|
m.complete(p, CONST_PARAM);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-08 19:26:38 +03:00
|
|
|
fn lifetime_bounds(p: &mut Parser) {
|
2019-05-15 15:35:47 +03:00
|
|
|
assert!(p.at(T![:]));
|
2019-09-19 15:51:46 -04:00
|
|
|
p.bump(T![:]);
|
2020-12-15 19:23:51 +01:00
|
|
|
while p.at(LIFETIME_IDENT) {
|
|
|
|
|
lifetime(p);
|
2019-05-15 15:35:47 +03:00
|
|
|
if !p.eat(T![+]) {
|
2018-08-08 19:26:38 +03:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-18 15:46:28 +03:00
|
|
|
// test type_param_bounds
|
2021-10-19 14:15:47 +02:00
|
|
|
// struct S<T: 'a + ?Sized + (Copy) + ~const Drop>;
|
2021-09-18 15:46:28 +03:00
|
|
|
pub(super) fn bounds(p: &mut Parser) {
|
|
|
|
|
assert!(p.at(T![:]));
|
|
|
|
|
p.bump(T![:]);
|
|
|
|
|
bounds_without_colon(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(super) fn bounds_without_colon(p: &mut Parser) {
|
|
|
|
|
let m = p.start();
|
|
|
|
|
bounds_without_colon_m(p, m);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-31 10:35:55 +03:00
|
|
|
pub(super) fn bounds_without_colon_m(p: &mut Parser, marker: Marker) -> CompletedMarker {
|
2019-03-30 17:23:54 +02:00
|
|
|
while type_bound(p) {
|
2019-05-15 15:35:47 +03:00
|
|
|
if !p.eat(T![+]) {
|
2018-07-31 18:24:30 +03:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-31 10:35:55 +03:00
|
|
|
marker.complete(p, TYPE_BOUND_LIST)
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-30 17:23:54 +02:00
|
|
|
fn type_bound(p: &mut Parser) -> bool {
|
|
|
|
|
let m = p.start();
|
2019-05-15 15:35:47 +03:00
|
|
|
let has_paren = p.eat(T!['(']);
|
2019-03-30 17:23:54 +02:00
|
|
|
match p.current() {
|
2020-12-15 19:23:51 +01:00
|
|
|
LIFETIME_IDENT => lifetime(p),
|
2020-12-20 21:53:55 +01:00
|
|
|
T![for] => types::for_type(p, false),
|
2021-10-19 14:15:47 +02:00
|
|
|
current => {
|
|
|
|
|
match current {
|
|
|
|
|
T![?] => p.bump_any(),
|
|
|
|
|
T![~] => {
|
|
|
|
|
p.bump_any();
|
|
|
|
|
p.expect(T![const]);
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
if paths::is_use_path_start(p) {
|
|
|
|
|
types::path_type_(p, false);
|
|
|
|
|
} else {
|
|
|
|
|
m.abandon(p);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-03-30 17:23:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if has_paren {
|
2019-05-15 15:35:47 +03:00
|
|
|
p.expect(T![')']);
|
2019-03-30 17:23:54 +02:00
|
|
|
}
|
|
|
|
|
m.complete(p, TYPE_BOUND);
|
|
|
|
|
|
|
|
|
|
true
|
2018-07-31 18:24:30 +03:00
|
|
|
}
|
|
|
|
|
|
2018-08-08 19:26:38 +03:00
|
|
|
// test where_clause
|
|
|
|
|
// fn foo()
|
|
|
|
|
// where
|
|
|
|
|
// 'a: 'b + 'c,
|
|
|
|
|
// T: Clone + Copy + 'static,
|
|
|
|
|
// Iterator::Item: 'a,
|
2018-12-21 17:20:38 +00:00
|
|
|
// <T as Iterator>::Item: 'a
|
2018-08-08 19:26:38 +03:00
|
|
|
// {}
|
2018-08-24 02:14:10 +03:00
|
|
|
pub(super) fn opt_where_clause(p: &mut Parser) {
|
2019-05-15 15:35:47 +03:00
|
|
|
if !p.at(T![where]) {
|
2018-08-08 19:26:38 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let m = p.start();
|
2019-09-19 15:51:46 -04:00
|
|
|
p.bump(T![where]);
|
2019-01-22 01:11:35 +01:00
|
|
|
|
2019-01-22 13:17:10 +01:00
|
|
|
while is_where_predicate(p) {
|
|
|
|
|
where_predicate(p);
|
2019-01-22 01:11:35 +01:00
|
|
|
|
2019-05-15 15:35:47 +03:00
|
|
|
let comma = p.eat(T![,]);
|
2019-01-22 01:11:35 +01:00
|
|
|
|
2021-09-18 15:46:28 +03:00
|
|
|
match p.current() {
|
|
|
|
|
T!['{'] | T![;] | T![=] => break,
|
|
|
|
|
_ => (),
|
2019-01-22 13:17:10 +01:00
|
|
|
}
|
2019-01-22 01:11:35 +01:00
|
|
|
|
2019-01-22 13:17:10 +01:00
|
|
|
if !comma {
|
|
|
|
|
p.error("expected comma");
|
2018-08-08 19:26:38 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-22 01:11:35 +01:00
|
|
|
|
2018-08-08 19:26:38 +03:00
|
|
|
m.complete(p, WHERE_CLAUSE);
|
|
|
|
|
|
2021-09-18 15:46:28 +03:00
|
|
|
fn is_where_predicate(p: &mut Parser) -> bool {
|
|
|
|
|
match p.current() {
|
|
|
|
|
LIFETIME_IDENT => true,
|
|
|
|
|
T![impl] => false,
|
|
|
|
|
token => types::TYPE_FIRST.contains(token),
|
|
|
|
|
}
|
2019-01-22 13:17:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-08 19:26:38 +03:00
|
|
|
fn where_predicate(p: &mut Parser) {
|
|
|
|
|
let m = p.start();
|
2018-11-05 11:24:02 +03:00
|
|
|
match p.current() {
|
2020-12-15 19:23:51 +01:00
|
|
|
LIFETIME_IDENT => {
|
|
|
|
|
lifetime(p);
|
2019-05-15 15:35:47 +03:00
|
|
|
if p.at(T![:]) {
|
2019-03-24 19:45:11 +02:00
|
|
|
bounds(p);
|
2018-11-05 11:24:02 +03:00
|
|
|
} else {
|
|
|
|
|
p.error("expected colon");
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-24 01:48:44 +03:00
|
|
|
T![impl] => {
|
2019-01-22 01:11:35 +01:00
|
|
|
p.error("expected lifetime or type");
|
|
|
|
|
}
|
2018-11-05 11:24:02 +03:00
|
|
|
_ => {
|
2020-06-10 11:30:48 +01:00
|
|
|
if p.at(T![for]) {
|
2021-09-18 15:46:28 +03:00
|
|
|
// test where_pred_for
|
|
|
|
|
// fn for_trait<F>()
|
|
|
|
|
// where
|
|
|
|
|
// for<'a> F: Fn(&'a str)
|
|
|
|
|
// { }
|
2020-06-10 11:30:48 +01:00
|
|
|
types::for_binder(p);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-22 01:11:35 +01:00
|
|
|
types::type_(p);
|
|
|
|
|
|
2019-05-15 15:35:47 +03:00
|
|
|
if p.at(T![:]) {
|
2018-11-05 11:24:02 +03:00
|
|
|
bounds(p);
|
|
|
|
|
} else {
|
|
|
|
|
p.error("expected colon");
|
|
|
|
|
}
|
2018-08-13 18:23:14 +03:00
|
|
|
}
|
2018-02-02 23:23:39 +03:00
|
|
|
}
|
2018-08-08 19:26:38 +03:00
|
|
|
m.complete(p, WHERE_PRED);
|
2018-02-02 23:23:39 +03:00
|
|
|
}
|