Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/generic_args.rs')
-rw-r--r--crates/parser/src/grammar/generic_args.rs41
1 files changed, 23 insertions, 18 deletions
diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs
index 4cac04a32a..b7d72b8d33 100644
--- a/crates/parser/src/grammar/generic_args.rs
+++ b/crates/parser/src/grammar/generic_args.rs
@@ -76,7 +76,29 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
}
}
}
- IDENT if p.nth(1) == T!['('] && p.nth_at(2, T![..]) => return_type_arg(p),
+ IDENT if p.nth_at(1, T!['(']) => {
+ let m = p.start();
+ name_ref(p);
+ params::param_list_fn_trait(p);
+ if p.at(T![:]) && !p.at(T![::]) {
+ // test associated_return_type_bounds
+ // fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}
+ generic_params::bounds(p);
+ m.complete(p, ASSOC_TYPE_ARG);
+ } else {
+ // test bare_dyn_types_with_paren_as_generic_args
+ // type A = S<Fn(i32)>;
+ // type A = S<Fn(i32) + Send>;
+ // type B = S<Fn(i32) -> i32>;
+ // type C = S<Fn(i32) -> i32 + Send>;
+ opt_ret_type(p);
+ let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
+ let m = paths::type_path_for_qualifier(p, m);
+ let m = m.precede(p).complete(p, PATH_TYPE);
+ let m = types::opt_type_bounds_as_dyn_trait_type(p, m);
+ m.precede(p).complete(p, TYPE_ARG);
+ }
+ }
_ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
_ => return false,
}
@@ -140,20 +162,3 @@ fn type_arg(p: &mut Parser<'_>) {
types::type_(p);
m.complete(p, TYPE_ARG);
}
-
-// test return_type_arg
-// type T = S<foo(..): Send>;
-pub(super) fn return_type_arg(p: &mut Parser<'_>) {
- let m = p.start();
- p.expect(IDENT);
- p.expect(T!['(']);
- p.expect(T![..]);
- p.expect(T![')']);
- if !p.at(T![:]) {
- p.error("expected :");
- m.abandon(p);
- return;
- }
- generic_params::bounds(p);
- m.complete(p, RETURN_TYPE_ARG);
-}