about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-12-04 11:02:49 +0000
committerGitHub <noreply@github.com>2024-12-04 11:02:49 +0000
commit609621db7fc830d4cc81fa9aeb4aca297f9fb158 (patch)
tree349e065ca7783fe176bcbf118260f90730c95368 /src
parent1b54eea983c1f89056a54ca2dce67d0d1700ae6d (diff)
parent2b4dc9caac1c05ae53e0d09907c40de1b1a75392 (diff)
downloadrust-609621db7fc830d4cc81fa9aeb4aca297f9fb158.tar.gz
rust-609621db7fc830d4cc81fa9aeb4aca297f9fb158.zip
Merge pull request #18593 from Veykril/push-nokqpzuqtmww
Fix parsing of parenthesized type args and RTN
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs94
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs65
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/params.rs18
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs100
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/types.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs32
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast33
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast79
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast39
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast111
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast175
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast461
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast48
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast128
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs3
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast49
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast43
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast10
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast60
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast57
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast8
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast8
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram5
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs38
44 files changed, 1020 insertions, 698 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
index 553e615b94f..37c94a5f118 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
@@ -48,7 +48,7 @@ pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<
                     .or_else(|| {
                         lower_generic_args_from_fn_path(
                             ctx,
-                            segment.param_list(),
+                            segment.parenthesized_arg_list(),
                             segment.ret_type(),
                         )
                     });
@@ -247,12 +247,12 @@ pub(super) fn lower_generic_args(
 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
 fn lower_generic_args_from_fn_path(
     ctx: &mut LowerCtx<'_>,
-    params: Option<ast::ParamList>,
+    args: Option<ast::ParenthesizedArgList>,
     ret_type: Option<ast::RetType>,
 ) -> Option<GenericArgs> {
-    let params = params?;
+    let params = args?;
     let mut param_types = Vec::new();
-    for param in params.params() {
+    for param in params.type_args() {
         let type_ref = TypeRef::from_ast_opt(ctx, param.ty());
         param_types.push(type_ref);
     }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 49b3ca290f0..a508f2fedd6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -286,7 +286,8 @@ impl Ctx<'_> {
             return None;
         }
         if path.segment().map_or(false, |s| {
-            s.param_list().is_some() || (s.self_token().is_some() && path.parent_path().is_none())
+            s.parenthesized_arg_list().is_some()
+                || (s.self_token().is_some() && path.parent_path().is_none())
         }) {
             // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
             // don't try to qualify sole `self` either, they are usually locals, but are returned as modules due to namespace clashing
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index 6569f0f5552..4edc3633fbe 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -359,8 +359,8 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
                 )?;
                 self.attempt_match_opt(
                     phase,
-                    pattern_segment.param_list(),
-                    code_segment.param_list(),
+                    pattern_segment.parenthesized_arg_list(),
+                    code_segment.parenthesized_arg_list(),
                 )?;
             }
             if matches!(phase, Phase::Second(_)) {
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
index 2163c959b18..1fdd6989917 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs
@@ -41,7 +41,15 @@ pub(super) fn fn_hints(
         fd,
         config,
         file_id,
-        param_list,
+        param_list.params().filter_map(|it| {
+            Some((
+                it.pat().and_then(|it| match it {
+                    ast::Pat::IdentPat(p) => p.name(),
+                    _ => None,
+                }),
+                it.ty()?,
+            ))
+        }),
         generic_param_list,
         ret_type,
         self_param,
@@ -90,7 +98,15 @@ pub(super) fn fn_ptr_hints(
         fd,
         config,
         file_id,
-        param_list,
+        param_list.params().filter_map(|it| {
+            Some((
+                it.pat().and_then(|it| match it {
+                    ast::Pat::IdentPat(p) => p.name(),
+                    _ => None,
+                }),
+                it.ty()?,
+            ))
+        }),
         generic_param_list,
         ret_type,
         None,
@@ -148,7 +164,7 @@ pub(super) fn fn_path_hints(
         fd,
         config,
         file_id,
-        param_list,
+        param_list.type_args().filter_map(|it| Some((None, it.ty()?))),
         generic_param_list,
         ret_type,
         None,
@@ -177,8 +193,8 @@ pub(super) fn fn_path_hints(
     )
 }
 
-fn path_as_fn(path: &ast::Path) -> Option<(ast::ParamList, Option<ast::RetType>)> {
-    path.segment().and_then(|it| it.param_list().zip(Some(it.ret_type())))
+fn path_as_fn(path: &ast::Path) -> Option<(ast::ParenthesizedArgList, Option<ast::RetType>)> {
+    path.segment().and_then(|it| it.parenthesized_arg_list().zip(Some(it.ret_type())))
 }
 
 fn hints_(
@@ -187,7 +203,7 @@ fn hints_(
     FamousDefs(_, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
-    param_list: ast::ParamList,
+    params: impl Iterator<Item = (Option<ast::Name>, ast::Type)>,
     generic_param_list: Option<ast::GenericParamList>,
     ret_type: Option<ast::RetType>,
     self_param: Option<ast::SelfParam>,
@@ -217,45 +233,34 @@ fn hints_(
             let is_elided = is_elided(&lifetime);
             acc.push((None, self_param.amp_token(), lifetime, is_elided));
         }
-        param_list
-            .params()
-            .filter_map(|it| {
-                Some((
-                    it.pat().and_then(|it| match it {
-                        ast::Pat::IdentPat(p) => p.name(),
-                        _ => None,
-                    }),
-                    it.ty()?,
-                ))
-            })
-            .for_each(|(name, ty)| {
-                // FIXME: check path types
-                walk_ty(&ty, &mut |ty| match ty {
-                    ast::Type::RefType(r) => {
-                        let lifetime = r.lifetime();
-                        let is_elided = is_elided(&lifetime);
-                        acc.push((name.clone(), r.amp_token(), lifetime, is_elided));
-                        false
-                    }
-                    ast::Type::FnPtrType(_) => {
+        params.for_each(|(name, ty)| {
+            // FIXME: check path types
+            walk_ty(&ty, &mut |ty| match ty {
+                ast::Type::RefType(r) => {
+                    let lifetime = r.lifetime();
+                    let is_elided = is_elided(&lifetime);
+                    acc.push((name.clone(), r.amp_token(), lifetime, is_elided));
+                    false
+                }
+                ast::Type::FnPtrType(_) => {
+                    is_trivial = false;
+                    true
+                }
+                ast::Type::PathType(t) => {
+                    if t.path()
+                        .and_then(|it| it.segment())
+                        .and_then(|it| it.parenthesized_arg_list())
+                        .is_some()
+                    {
                         is_trivial = false;
                         true
+                    } else {
+                        false
                     }
-                    ast::Type::PathType(t) => {
-                        if t.path()
-                            .and_then(|it| it.segment())
-                            .and_then(|it| it.param_list())
-                            .is_some()
-                        {
-                            is_trivial = false;
-                            true
-                        } else {
-                            false
-                        }
-                    }
-                    _ => false,
-                })
-            });
+                }
+                _ => false,
+            })
+        });
         acc
     };
 
@@ -339,7 +344,10 @@ fn hints_(
                     true
                 }
                 ast::Type::PathType(t) => {
-                    if t.path().and_then(|it| it.segment()).and_then(|it| it.param_list()).is_some()
+                    if t.path()
+                        .and_then(|it| it.segment())
+                        .and_then(|it| it.parenthesized_arg_list())
+                        .is_some()
                     {
                         is_trivial = false;
                         true
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index e565874a421..349bce09390 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -525,7 +525,7 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
         p.bump(T![.]);
     }
     name_ref(p);
-    generic_args::opt_generic_arg_list(p, true);
+    generic_args::opt_generic_arg_list_expr(p);
     if p.at(T!['(']) {
         arg_list(p);
     } else {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
index 77379ef1471..737010985b2 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
@@ -1,14 +1,13 @@
 use super::*;
 
-// test_err generic_arg_list_recover
-// type T = T<0, ,T>;
-pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: bool) {
+// test_err generic_arg_list_recover_expr
+// const _: () = T::<0, ,T>;
+// const _: () = T::<0, ,T>();
+pub(super) fn opt_generic_arg_list_expr(p: &mut Parser<'_>) {
     let m;
     if p.at(T![::]) && p.nth(2) == T![<] {
         m = p.start();
         p.bump(T![::]);
-    } else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
-        m = p.start();
     } else {
         return;
     }
@@ -25,7 +24,7 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: boo
     m.complete(p, GENERIC_ARG_LIST);
 }
 
-const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
+pub(crate) const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
     LIFETIME_IDENT,
     IDENT,
     T!['{'],
@@ -47,20 +46,23 @@ const GENERIC_ARG_RECOVERY_SET: TokenSet = TokenSet::new(&[T![>], T![,]]);
 
 // test generic_arg
 // type T = S<i32>;
-fn generic_arg(p: &mut Parser<'_>) -> bool {
+pub(crate) fn generic_arg(p: &mut Parser<'_>) -> bool {
     match p.current() {
         LIFETIME_IDENT if !p.nth_at(1, T![+]) => lifetime_arg(p),
         T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
         k if k.is_literal() => const_arg(p),
-        // test associated_type_bounds
-        // fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
+        // test generic_arg_bounds
+        // type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
+        // type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
+        // type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
+        // type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;
 
         // test macro_inside_generic_arg
         // type A = Foo<syn::Token![_]>;
-        IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) && !p.nth_at(1, T![::]) => {
+        IDENT => {
             let m = p.start();
             name_ref(p);
-            opt_generic_arg_list(p, false);
+            paths::opt_path_type_args(p);
             match p.current() {
                 T![=] => {
                     p.bump_any();
@@ -88,45 +90,26 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
                 }
                 // test assoc_type_bound
                 // type T = StreamingIterator<Item<'a>: Clone>;
+                // type T = StreamingIterator<Item(T): Clone>;
                 T![:] if !p.at(T![::]) => {
                     generic_params::bounds(p);
                     m.complete(p, ASSOC_TYPE_ARG);
                 }
+                // Turned out to be just a normal path type (mirror `path_or_macro_type`)
                 _ => {
                     let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
                     let m = paths::type_path_for_qualifier(p, m);
-                    m.precede(p).complete(p, PATH_TYPE).precede(p).complete(p, TYPE_ARG);
+                    let m = if p.at(T![!]) && !p.at(T![!=]) {
+                        let m = m.precede(p);
+                        items::macro_call_after_excl(p);
+                        m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_TYPE)
+                    } else {
+                        m.precede(p).complete(p, PATH_TYPE)
+                    };
+                    types::opt_type_bounds_as_dyn_trait_type(p, m).precede(p).complete(p, TYPE_ARG);
                 }
             }
         }
-        IDENT if p.nth_at(1, T!['(']) => {
-            let m = p.start();
-            name_ref(p);
-            if p.nth_at(1, T![..]) {
-                let rtn = p.start();
-                p.bump(T!['(']);
-                p.bump(T![..]);
-                p.expect(T![')']);
-                rtn.complete(p, RETURN_TYPE_SYNTAX);
-                // test return_type_syntax_assoc_type_bound
-                // fn foo<T: Trait<method(..): Send>>() {}
-                generic_params::bounds(p);
-                m.complete(p, ASSOC_TYPE_ARG);
-            } else {
-                params::param_list_fn_trait(p);
-                // 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,
     }
@@ -190,7 +173,7 @@ pub(super) fn const_arg(p: &mut Parser<'_>) {
     m.complete(p, CONST_ARG);
 }
 
-fn type_arg(p: &mut Parser<'_>) {
+pub(crate) fn type_arg(p: &mut Parser<'_>) {
     let m = p.start();
     types::type_(p);
     m.complete(p, TYPE_ARG);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
index c535267c165..51ffcd07069 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
@@ -14,12 +14,6 @@ pub(super) fn param_list_fn_def(p: &mut Parser<'_>) {
     list_(p, Flavor::FnDef);
 }
 
-// test param_list_opt_patterns
-// fn foo<F: FnMut(&mut Foo<'a>)>(){}
-pub(super) fn param_list_fn_trait(p: &mut Parser<'_>) {
-    list_(p, Flavor::FnTrait);
-}
-
 pub(super) fn param_list_fn_ptr(p: &mut Parser<'_>) {
     list_(p, Flavor::FnPointer);
 }
@@ -28,10 +22,9 @@ pub(super) fn param_list_closure(p: &mut Parser<'_>) {
     list_(p, Flavor::Closure);
 }
 
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 enum Flavor {
-    FnDef,   // Includes trait fn params; omitted param idents are not supported
-    FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
+    FnDef, // Includes trait fn params; omitted param idents are not supported
     FnPointer,
     Closure,
 }
@@ -41,7 +34,7 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
 
     let (bra, ket) = match flavor {
         Closure => (T![|], T![|]),
-        FnDef | FnTrait | FnPointer => (T!['('], T![')']),
+        FnDef | FnPointer => (T!['('], T![')']),
     };
 
     let list_marker = p.start();
@@ -119,11 +112,6 @@ fn param(p: &mut Parser<'_>, m: Marker, flavor: Flavor) {
                 }
             }
         }
-        // test value_parameters_no_patterns
-        // type F = Box<Fn(i32, &i32, &i32, ())>;
-        Flavor::FnTrait => {
-            types::type_(p);
-        }
         // test fn_pointer_param_ident_path
         // type Foo = fn(Bar::Baz);
         // type Qux = fn(baz: Bar::Baz);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
index 15b35296423..b3652f7cd3f 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
@@ -110,7 +110,7 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
         match p.current() {
             IDENT => {
                 name_ref(p);
-                opt_path_type_args(p, mode);
+                opt_path_args(p, mode);
             }
             // test crate_path
             // use crate::foo;
@@ -142,38 +142,74 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
     Some(m.complete(p, PATH_SEGMENT))
 }
 
-fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
+pub(crate) fn opt_path_type_args(p: &mut Parser<'_>) {
+    // test typepathfn_with_coloncolon
+    // type F = Start::(Middle) -> (Middle)::End;
+    // type GenericArg = S<Start(Middle)::End>;
+    let m;
+    if p.at(T![::]) && matches!(p.nth(2), T![<] | T!['(']) {
+        m = p.start();
+        p.bump(T![::]);
+    } else if (p.current() == T![<] && p.nth(1) != T![=]) || p.current() == T!['('] {
+        m = p.start();
+    } else {
+        return;
+    }
+    let current = p.current();
+    if current == T![<] {
+        // test_err generic_arg_list_recover
+        // type T = T<0, ,T>;
+        // type T = T::<0, ,T>;
+        delimited(
+            p,
+            T![<],
+            T![>],
+            T![,],
+            || "expected generic argument".into(),
+            generic_args::GENERIC_ARG_FIRST,
+            generic_args::generic_arg,
+        );
+        m.complete(p, GENERIC_ARG_LIST);
+    } else if p.nth_at(1, T![..]) {
+        // test return_type_syntax_in_path
+        // fn foo<T>()
+        // where
+        //     T::method(..): Send,
+        //     method(..): Send,
+        //     method::(..): Send,
+        // {}
+        p.bump(T!['(']);
+        p.bump(T![..]);
+        p.expect(T![')']);
+        m.complete(p, RETURN_TYPE_SYNTAX);
+    } else {
+        // test path_fn_trait_args
+        // type F = Box<Fn(i32) -> ()>;
+        // type F = Box<::Fn(i32) -> ()>;
+        // type F = Box<Fn::(i32) -> ()>;
+        // type F = Box<::Fn::(i32) -> ()>;
+        delimited(
+            p,
+            T!['('],
+            T![')'],
+            T![,],
+            || "expected type".into(),
+            types::TYPE_FIRST,
+            |p| {
+                let progress = types::TYPE_FIRST.contains(p.current());
+                generic_args::type_arg(p);
+                progress
+            },
+        );
+        m.complete(p, PARENTHESIZED_ARG_LIST);
+        opt_ret_type(p);
+    }
+}
+
+fn opt_path_args(p: &mut Parser<'_>, mode: Mode) {
     match mode {
         Mode::Use | Mode::Attr | Mode::Vis => {}
-        Mode::Type => {
-            // test typepathfn_with_coloncolon
-            // type F = Start::(Middle) -> (Middle)::End;
-            // type GenericArg = S<Start(Middle)::End>;
-            if p.at(T![::]) && p.nth_at(2, T!['(']) {
-                p.bump(T![::]);
-            }
-            if p.at(T!['(']) {
-                if p.nth_at(1, T![..]) {
-                    // test return_type_syntax_in_path
-                    // fn foo<T>()
-                    // where
-                    //     T::method(..): Send,
-                    // {}
-                    let rtn = p.start();
-                    p.bump(T!['(']);
-                    p.bump(T![..]);
-                    p.expect(T![')']);
-                    rtn.complete(p, RETURN_TYPE_SYNTAX);
-                } else {
-                    // test path_fn_trait_args
-                    // type F = Box<Fn(i32) -> ()>;
-                    params::param_list_fn_trait(p);
-                    opt_ret_type(p);
-                }
-            } else {
-                generic_args::opt_generic_arg_list(p, false);
-            }
-        }
-        Mode::Expr => generic_args::opt_generic_arg_list(p, true),
+        Mode::Type => opt_path_type_args(p),
+        Mode::Expr => generic_args::opt_generic_arg_list_expr(p),
     }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
index f4e57d3d6f3..35198ccbe35 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
@@ -50,7 +50,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
         // Some path types are not allowed to have bounds (no plus)
         T![<] => path_type_bounds(p, allow_bounds),
         T![ident] if !p.edition().at_least_2018() && is_dyn_weak(p) => dyn_trait_type_weak(p),
-        _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds),
+        _ if paths::is_path_start(p) => path_or_macro_type(p, allow_bounds),
         LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
         _ => {
             p.err_recover("expected type", TYPE_RECOVERY_SET);
@@ -337,7 +337,7 @@ pub(super) fn path_type(p: &mut Parser<'_>) {
 // test macro_call_type
 // type A = foo!();
 // type B = crate::foo!();
-fn path_or_macro_type_(p: &mut Parser<'_>, allow_bounds: bool) {
+fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
     assert!(paths::is_path_start(p));
     let r = p.start();
     let m = p.start();
diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
index 21730244a33..0c9c6ffd715 100644
--- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
@@ -256,6 +256,7 @@ pub enum SyntaxKind {
     OR_PAT,
     PARAM,
     PARAM_LIST,
+    PARENTHESIZED_ARG_LIST,
     PAREN_EXPR,
     PAREN_PAT,
     PAREN_TYPE,
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
index 3db8b51a4ba..6d114037bf9 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
@@ -39,10 +39,6 @@ mod ok {
     #[test]
     fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); }
     #[test]
-    fn associated_type_bounds() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs");
-    }
-    #[test]
     fn async_trait_bound() {
         run_and_expect_no_errors("test_data/parser/inline/ok/async_trait_bound.rs");
     }
@@ -59,12 +55,6 @@ mod ok {
         );
     }
     #[test]
-    fn bare_dyn_types_with_paren_as_generic_args() {
-        run_and_expect_no_errors(
-            "test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs",
-        );
-    }
-    #[test]
     fn become_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/become_expr.rs"); }
     #[test]
     fn bind_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/bind_pat.rs"); }
@@ -281,6 +271,10 @@ mod ok {
     #[test]
     fn generic_arg() { run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg.rs"); }
     #[test]
+    fn generic_arg_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg_bounds.rs");
+    }
+    #[test]
     fn generic_param_attribute() {
         run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_attribute.rs");
     }
@@ -423,10 +417,6 @@ mod ok {
     #[test]
     fn param_list() { run_and_expect_no_errors("test_data/parser/inline/ok/param_list.rs"); }
     #[test]
-    fn param_list_opt_patterns() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/param_list_opt_patterns.rs");
-    }
-    #[test]
     fn param_list_vararg() {
         run_and_expect_no_errors("test_data/parser/inline/ok/param_list_vararg.rs");
     }
@@ -521,12 +511,6 @@ mod ok {
     #[test]
     fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); }
     #[test]
-    fn return_type_syntax_assoc_type_bound() {
-        run_and_expect_no_errors(
-            "test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs",
-        );
-    }
-    #[test]
     fn return_type_syntax_in_path() {
         run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs");
     }
@@ -685,10 +669,6 @@ mod ok {
     #[test]
     fn use_tree_star() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_star.rs"); }
     #[test]
-    fn value_parameters_no_patterns() {
-        run_and_expect_no_errors("test_data/parser/inline/ok/value_parameters_no_patterns.rs");
-    }
-    #[test]
     fn variant_discriminant() {
         run_and_expect_no_errors("test_data/parser/inline/ok/variant_discriminant.rs");
     }
@@ -754,6 +734,10 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover.rs");
     }
     #[test]
+    fn generic_arg_list_recover_expr() {
+        run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover_expr.rs");
+    }
+    #[test]
     fn generic_param_list_recover() {
         run_and_expect_errors("test_data/parser/inline/err/generic_param_list_recover.rs");
     }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
index 4cf5a3386b9..16183ce9ef5 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
@@ -30,4 +30,37 @@ SOURCE_FILE
             R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "T"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "T"
+          GENERIC_ARG_LIST
+            COLON2 "::"
+            L_ANGLE "<"
+            CONST_ARG
+              LITERAL
+                INT_NUMBER "0"
+            COMMA ","
+            WHITESPACE " "
+            ERROR
+              COMMA ","
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "T"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
 error 14: expected generic argument
+error 35: expected generic argument
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
index 7d849aa1bee..aa65a0673a4 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
@@ -1 +1,2 @@
 type T = T<0, ,T>;
+type T = T::<0, ,T>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast
new file mode 100644
index 00000000000..de403d30494
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rast
@@ -0,0 +1,79 @@
+SOURCE_FILE
+  CONST
+    CONST_KW "const"
+    WHITESPACE " "
+    UNDERSCORE "_"
+    COLON ":"
+    WHITESPACE " "
+    TUPLE_TYPE
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_EXPR
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "T"
+          GENERIC_ARG_LIST
+            COLON2 "::"
+            L_ANGLE "<"
+            CONST_ARG
+              LITERAL
+                INT_NUMBER "0"
+            COMMA ","
+            WHITESPACE " "
+            ERROR
+              COMMA ","
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "T"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  CONST
+    CONST_KW "const"
+    WHITESPACE " "
+    UNDERSCORE "_"
+    COLON ":"
+    WHITESPACE " "
+    TUPLE_TYPE
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    CALL_EXPR
+      PATH_EXPR
+        PATH
+          PATH_SEGMENT
+            NAME_REF
+              IDENT "T"
+            GENERIC_ARG_LIST
+              COLON2 "::"
+              L_ANGLE "<"
+              CONST_ARG
+                LITERAL
+                  INT_NUMBER "0"
+              COMMA ","
+              WHITESPACE " "
+              ERROR
+                COMMA ","
+              TYPE_ARG
+                PATH_TYPE
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "T"
+              R_ANGLE ">"
+      ARG_LIST
+        L_PAREN "("
+        R_PAREN ")"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 21: expected generic argument
+error 47: expected generic argument
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs
new file mode 100644
index 00000000000..74cc63ac4a0
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover_expr.rs
@@ -0,0 +1,2 @@
+const _: () = T::<0, ,T>;
+const _: () = T::<0, ,T>();
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
index f2e4e01069c..0f62e1dd184 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
@@ -35,3 +35,42 @@ SOURCE_FILE
             R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "T"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "StreamingIterator"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Clone"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
index daae97e4fd5..83fea1c6c87 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
@@ -1 +1,2 @@
 type T = StreamingIterator<Item<'a>: Clone>;
+type T = StreamingIterator<Item(T): Clone>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast
deleted file mode 100644
index 8cbc98c51ca..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast
+++ /dev/null
@@ -1,111 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "print_all"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "T"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "Iterator"
-                  GENERIC_ARG_LIST
-                    L_ANGLE "<"
-                    TYPE_ARG
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                    COMMA ","
-                    WHITESPACE " "
-                    TYPE_ARG
-                      PATH_TYPE
-                        PATH
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "Item"
-                          COLON2 "::"
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                    COMMA ","
-                    WHITESPACE " "
-                    TYPE_ARG
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                            GENERIC_ARG_LIST
-                              COLON2 "::"
-                              L_ANGLE "<"
-                              CONST_ARG
-                                LITERAL
-                                  TRUE_KW "true"
-                              R_ANGLE ">"
-                    COMMA ","
-                    WHITESPACE " "
-                    ASSOC_TYPE_ARG
-                      NAME_REF
-                        IDENT "Item"
-                      COLON ":"
-                      WHITESPACE " "
-                      TYPE_BOUND_LIST
-                        TYPE_BOUND
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "Display"
-                    COMMA ","
-                    WHITESPACE " "
-                    ASSOC_TYPE_ARG
-                      NAME_REF
-                        IDENT "Item"
-                      GENERIC_ARG_LIST
-                        L_ANGLE "<"
-                        LIFETIME_ARG
-                          LIFETIME
-                            LIFETIME_IDENT "'a"
-                        R_ANGLE ">"
-                      WHITESPACE " "
-                      EQ "="
-                      WHITESPACE " "
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "Item"
-                    R_ANGLE ">"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      PARAM
-        IDENT_PAT
-          NAME
-            IDENT "printables"
-        COLON ":"
-        WHITESPACE " "
-        PATH_TYPE
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "T"
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs
deleted file mode 100644
index 0f7a2d16083..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
index ebf758286a7..df0ba55d03d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
@@ -23,9 +23,9 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "Fn"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
                         REF_TYPE
                           AMP "&"
                           PATH_TYPE
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast
deleted file mode 100644
index d5f97bad898..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast
+++ /dev/null
@@ -1,175 +0,0 @@
-SOURCE_FILE
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "A"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              PATH_TYPE
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "Fn"
-                    PARAM_LIST
-                      L_PAREN "("
-                      PARAM
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "i32"
-                      R_PAREN ")"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "A"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              DYN_TRAIT_TYPE
-                TYPE_BOUND_LIST
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Fn"
-                          PARAM_LIST
-                            L_PAREN "("
-                            PARAM
-                              PATH_TYPE
-                                PATH
-                                  PATH_SEGMENT
-                                    NAME_REF
-                                      IDENT "i32"
-                            R_PAREN ")"
-                  WHITESPACE " "
-                  PLUS "+"
-                  WHITESPACE " "
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Send"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "B"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              PATH_TYPE
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "Fn"
-                    PARAM_LIST
-                      L_PAREN "("
-                      PARAM
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "i32"
-                      R_PAREN ")"
-                    WHITESPACE " "
-                    RET_TYPE
-                      THIN_ARROW "->"
-                      WHITESPACE " "
-                      PATH_TYPE
-                        PATH
-                          PATH_SEGMENT
-                            NAME_REF
-                              IDENT "i32"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "C"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "S"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              DYN_TRAIT_TYPE
-                TYPE_BOUND_LIST
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Fn"
-                          PARAM_LIST
-                            L_PAREN "("
-                            PARAM
-                              PATH_TYPE
-                                PATH
-                                  PATH_SEGMENT
-                                    NAME_REF
-                                      IDENT "i32"
-                            R_PAREN ")"
-                          WHITESPACE " "
-                          RET_TYPE
-                            THIN_ARROW "->"
-                            WHITESPACE " "
-                            PATH_TYPE
-                              PATH
-                                PATH_SEGMENT
-                                  NAME_REF
-                                    IDENT "i32"
-                  WHITESPACE " "
-                  PLUS "+"
-                  WHITESPACE " "
-                  TYPE_BOUND
-                    PATH_TYPE
-                      PATH
-                        PATH_SEGMENT
-                          NAME_REF
-                            IDENT "Send"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs
deleted file mode 100644
index 800002b1b82..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-type A = S<Fn(i32)>;
-type A = S<Fn(i32) + Send>;
-type B = S<Fn(i32) -> i32>;
-type C = S<Fn(i32) -> i32 + Send>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast
new file mode 100644
index 00000000000..fee5913acaa
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rast
@@ -0,0 +1,461 @@
+SOURCE_FILE
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "Plain"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "Item"
+                  COLON2 "::"
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "GenericArgs"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    GENERIC_ARG_LIST
+                      L_ANGLE "<"
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_ANGLE ">"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    GENERIC_ARG_LIST
+                      COLON2 "::"
+                      L_ANGLE "<"
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_ANGLE ">"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                COLON2 "::"
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              GENERIC_ARG_LIST
+                COLON2 "::"
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_ANGLE ">"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "ParenthesizedArgs"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    PARENTHESIZED_ARG_LIST
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    PARENTHESIZED_ARG_LIST
+                      COLON2 "::"
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "T"
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                COLON2 "::"
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              PARENTHESIZED_ARG_LIST
+                COLON2 "::"
+                L_PAREN "("
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "T"
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "RTN"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Foo"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    RETURN_TYPE_SYNTAX
+                      L_PAREN "("
+                      DOT2 ".."
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+                    RETURN_TYPE_SYNTAX
+                      L_PAREN "("
+                      DOT2 ".."
+                      R_PAREN ")"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              COLON ":"
+              WHITESPACE " "
+              TYPE_BOUND_LIST
+                TYPE_BOUND
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "Bound"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            COMMA ","
+            WHITESPACE " "
+            ASSOC_TYPE_ARG
+              NAME_REF
+                IDENT "Item"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+              WHITESPACE " "
+              EQ "="
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Item"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs
new file mode 100644
index 00000000000..1abd0aeb592
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg_bounds.rs
@@ -0,0 +1,4 @@
+type Plain = Foo<Item, Item::Item, Item: Bound, Item = Item>;
+type GenericArgs = Foo<Item<T>, Item::<T>, Item<T>: Bound, Item::<T>: Bound, Item<T> = Item, Item::<T> = Item>;
+type ParenthesizedArgs = Foo<Item(T), Item::(T), Item(T): Bound, Item::(T): Bound, Item(T) = Item, Item::(T) = Item>;
+type RTN = Foo<Item(..), Item(..), Item(..): Bound, Item(..): Bound, Item(..) = Item, Item(..) = Item>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast
deleted file mode 100644
index e9d93a0d0a4..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast
+++ /dev/null
@@ -1,48 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "F"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "FnMut"
-                  PARAM_LIST
-                    L_PAREN "("
-                    PARAM
-                      REF_TYPE
-                        AMP "&"
-                        MUT_KW "mut"
-                        WHITESPACE " "
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "Foo"
-                              GENERIC_ARG_LIST
-                                L_ANGLE "<"
-                                LIFETIME_ARG
-                                  LIFETIME
-                                    LIFETIME_IDENT "'a"
-                                R_ANGLE ">"
-                    R_PAREN ")"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs
deleted file mode 100644
index 9b93442c0f2..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn foo<F: FnMut(&mut Foo<'a>)>(){}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
index fd83daf841f..924f7ba2c9d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
@@ -20,9 +20,133 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "Fn"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "i32"
+                      R_PAREN ")"
+                    WHITESPACE " "
+                    RET_TYPE
+                      THIN_ARROW "->"
+                      WHITESPACE " "
+                      TUPLE_TYPE
+                        L_PAREN "("
+                        R_PAREN ")"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "F"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Box"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    COLON2 "::"
+                    NAME_REF
+                      IDENT "Fn"
+                    PARENTHESIZED_ARG_LIST
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "i32"
+                      R_PAREN ")"
+                    WHITESPACE " "
+                    RET_TYPE
+                      THIN_ARROW "->"
+                      WHITESPACE " "
+                      TUPLE_TYPE
+                        L_PAREN "("
+                        R_PAREN ")"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "F"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Box"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "Fn"
+                    PARENTHESIZED_ARG_LIST
+                      COLON2 "::"
+                      L_PAREN "("
+                      TYPE_ARG
+                        PATH_TYPE
+                          PATH
+                            PATH_SEGMENT
+                              NAME_REF
+                                IDENT "i32"
+                      R_PAREN ")"
+                    WHITESPACE " "
+                    RET_TYPE
+                      THIN_ARROW "->"
+                      WHITESPACE " "
+                      TUPLE_TYPE
+                        L_PAREN "("
+                        R_PAREN ")"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "F"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "Box"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    COLON2 "::"
+                    NAME_REF
+                      IDENT "Fn"
+                    PARENTHESIZED_ARG_LIST
+                      COLON2 "::"
+                      L_PAREN "("
+                      TYPE_ARG
                         PATH_TYPE
                           PATH
                             PATH_SEGMENT
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
index 17ed20e5b13..7aa655d7ea9 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
@@ -1 +1,4 @@
 type F = Box<Fn(i32) -> ()>;
+type F = Box<::Fn(i32) -> ()>;
+type F = Box<Fn::(i32) -> ()>;
+type F = Box<::Fn::(i32) -> ()>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast
deleted file mode 100644
index 30e0e73bbd6..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rast
+++ /dev/null
@@ -1,49 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "T"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "Trait"
-                  GENERIC_ARG_LIST
-                    L_ANGLE "<"
-                    ASSOC_TYPE_ARG
-                      NAME_REF
-                        IDENT "method"
-                      RETURN_TYPE_SYNTAX
-                        L_PAREN "("
-                        DOT2 ".."
-                        R_PAREN ")"
-                      COLON ":"
-                      WHITESPACE " "
-                      TYPE_BOUND_LIST
-                        TYPE_BOUND
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "Send"
-                    R_ANGLE ">"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs
deleted file mode 100644
index 8a4cf4c3a07..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_assoc_type_bound.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn foo<T: Trait<method(..): Send>>() {}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast
index 501dccd79db..15a0558b53d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rast
@@ -42,6 +42,49 @@ SOURCE_FILE
                   NAME_REF
                     IDENT "Send"
       COMMA ","
+      WHITESPACE "\n    "
+      WHERE_PRED
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "method"
+              RETURN_TYPE_SYNTAX
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+        COLON ":"
+        WHITESPACE " "
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            PATH_TYPE
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "Send"
+      COMMA ","
+      WHITESPACE "\n    "
+      WHERE_PRED
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "method"
+              RETURN_TYPE_SYNTAX
+                COLON2 "::"
+                L_PAREN "("
+                DOT2 ".."
+                R_PAREN ")"
+        COLON ":"
+        WHITESPACE " "
+        TYPE_BOUND_LIST
+          TYPE_BOUND
+            PATH_TYPE
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "Send"
+      COMMA ","
     WHITESPACE "\n"
     BLOCK_EXPR
       STMT_LIST
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs
index a9b63fb01c8..64b48c1638e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_type_syntax_in_path.rs
@@ -1,4 +1,6 @@
 fn foo<T>()
 where
     T::method(..): Send,
+    method(..): Send,
+    method::(..): Send,
 {}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
index 67277d0639a..fb442bfb739 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
@@ -13,10 +13,10 @@ SOURCE_FILE
           PATH_SEGMENT
             NAME_REF
               IDENT "Start"
-            COLON2 "::"
-            PARAM_LIST
+            PARENTHESIZED_ARG_LIST
+              COLON2 "::"
               L_PAREN "("
-              PARAM
+              TYPE_ARG
                 PATH_TYPE
                   PATH
                     PATH_SEGMENT
@@ -63,9 +63,9 @@ SOURCE_FILE
                     PATH_SEGMENT
                       NAME_REF
                         IDENT "Start"
-                      PARAM_LIST
+                      PARENTHESIZED_ARG_LIST
                         L_PAREN "("
-                        PARAM
+                        TYPE_ARG
                           PATH_TYPE
                             PATH
                               PATH_SEGMENT
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast
deleted file mode 100644
index 902b06484c8..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast
+++ /dev/null
@@ -1,60 +0,0 @@
-SOURCE_FILE
-  TYPE_ALIAS
-    TYPE_KW "type"
-    WHITESPACE " "
-    NAME
-      IDENT "F"
-    WHITESPACE " "
-    EQ "="
-    WHITESPACE " "
-    PATH_TYPE
-      PATH
-        PATH_SEGMENT
-          NAME_REF
-            IDENT "Box"
-          GENERIC_ARG_LIST
-            L_ANGLE "<"
-            TYPE_ARG
-              PATH_TYPE
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      IDENT "Fn"
-                    PARAM_LIST
-                      L_PAREN "("
-                      PARAM
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "i32"
-                      COMMA ","
-                      WHITESPACE " "
-                      PARAM
-                        REF_TYPE
-                          AMP "&"
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "i32"
-                      COMMA ","
-                      WHITESPACE " "
-                      PARAM
-                        REF_TYPE
-                          AMP "&"
-                          PATH_TYPE
-                            PATH
-                              PATH_SEGMENT
-                                NAME_REF
-                                  IDENT "i32"
-                      COMMA ","
-                      WHITESPACE " "
-                      PARAM
-                        TUPLE_TYPE
-                          L_PAREN "("
-                          R_PAREN ")"
-                      R_PAREN ")"
-            R_ANGLE ">"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs
deleted file mode 100644
index 93636e926e1..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs
+++ /dev/null
@@ -1 +0,0 @@
-type F = Box<Fn(i32, &i32, &i32, ())>;
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
index 8407e99f614..0cc365efbe6 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
@@ -40,9 +40,9 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
-                    PARAM
+                    TYPE_ARG
                       REF_TYPE
                         AMP "&"
                         LIFETIME
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast
index fad574a4769..c22d99f1ae1 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0045_block_attrs.rast
@@ -180,7 +180,7 @@ SOURCE_FILE
                       PATH_SEGMENT
                         NAME_REF
                           IDENT "Fn"
-                        PARAM_LIST
+                        PARENTHESIZED_ARG_LIST
                           L_PAREN "("
                           R_PAREN ")"
                         WHITESPACE " "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast
index f8b11e7782c..eafee90db42 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rast
@@ -138,63 +138,6 @@ SOURCE_FILE
       WHITESPACE " "
       R_CURLY "}"
   WHITESPACE "\n\n"
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    GENERIC_PARAM_LIST
-      L_ANGLE "<"
-      TYPE_PARAM
-        NAME
-          IDENT "F"
-        COLON ":"
-        WHITESPACE " "
-        TYPE_BOUND_LIST
-          TYPE_BOUND
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "FnMut"
-                  PARAM_LIST
-                    L_PAREN "("
-                    PARAM
-                      ATTR
-                        POUND "#"
-                        L_BRACK "["
-                        META
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "attr"
-                        R_BRACK "]"
-                      WHITESPACE " "
-                      REF_TYPE
-                        AMP "&"
-                        MUT_KW "mut"
-                        WHITESPACE " "
-                        PATH_TYPE
-                          PATH
-                            PATH_SEGMENT
-                              NAME_REF
-                                IDENT "Foo"
-                              GENERIC_ARG_LIST
-                                L_ANGLE "<"
-                                LIFETIME_ARG
-                                  LIFETIME
-                                    LIFETIME_IDENT "'a"
-                                R_ANGLE ">"
-                    R_PAREN ")"
-      R_ANGLE ">"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        R_CURLY "}"
-  WHITESPACE "\n\n"
   TRAIT
     TRAIT_KW "trait"
     WHITESPACE " "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs
index de350d8587a..0a0100e5d00 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs
@@ -3,8 +3,6 @@ fn g2(#[attr1] x: u8) {}
 
 extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
 
-fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
-
 trait Foo {
     fn bar(#[attr] _: u64, # [attr] mut x: i32);
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast
index 4e1e31f3767..31cca601ca2 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0054_qual_path_in_type_arg.rast
@@ -58,9 +58,9 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "FnMut"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
                         PATH_TYPE
                           PATH
                             PATH
@@ -101,9 +101,9 @@ SOURCE_FILE
                   PATH_SEGMENT
                     NAME_REF
                       IDENT "FnMut"
-                    PARAM_LIST
+                    PARENTHESIZED_ARG_LIST
                       L_PAREN "("
-                      PARAM
+                      TYPE_ARG
                         REF_TYPE
                           AMP "&"
                           PATH_TYPE
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
index ba7b6042a9e..d7ee11077cd 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
@@ -32,7 +32,7 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
                     R_PAREN ")"
                   WHITESPACE " "
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
index 136fce93d7e..cd3b21ae94f 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0067_where_for_pred.rast
@@ -40,9 +40,9 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
-                    PARAM
+                    TYPE_ARG
                       REF_TYPE
                         AMP "&"
                         LIFETIME
@@ -165,9 +165,9 @@ SOURCE_FILE
                 PATH_SEGMENT
                   NAME_REF
                     IDENT "Fn"
-                  PARAM_LIST
+                  PARENTHESIZED_ARG_LIST
                     L_PAREN "("
-                    PARAM
+                    TYPE_ARG
                       REF_TYPE
                         AMP "&"
                         LIFETIME
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index 02c59646a99..30428329dd9 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -37,7 +37,7 @@ Path =
 PathSegment =
   '::'? NameRef
 | NameRef GenericArgList?
-| NameRef ParamList RetType?
+| NameRef ParenthesizedArgList RetType?
 | NameRef ReturnTypeSyntax
 | '<' Type ('as' PathType)? '>'
 
@@ -49,6 +49,9 @@ ReturnTypeSyntax =
 //        Generics         //
 //*************************//
 
+ParenthesizedArgList =
+  '::'? '(' (TypeArg (',' TypeArg)* ','?)? ')'
+
 GenericArgList =
   '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>'
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index 23d2b355a94..01dcb646b37 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -1363,6 +1363,21 @@ impl ParenType {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ParenthesizedArgList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ParenthesizedArgList {
+    #[inline]
+    pub fn type_args(&self) -> AstChildren<TypeArg> { support::children(&self.syntax) }
+    #[inline]
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    #[inline]
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    #[inline]
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Path {
     pub(crate) syntax: SyntaxNode,
 }
@@ -1403,7 +1418,9 @@ impl PathSegment {
     #[inline]
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     #[inline]
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn parenthesized_arg_list(&self) -> Option<ParenthesizedArgList> {
+        support::child(&self.syntax)
+    }
     #[inline]
     pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
     #[inline]
@@ -3760,6 +3777,20 @@ impl AstNode for ParenType {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl AstNode for ParenthesizedArgList {
+    #[inline]
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PARENTHESIZED_ARG_LIST }
+    #[inline]
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    #[inline]
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
 impl AstNode for Path {
     #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
@@ -7097,6 +7128,11 @@ impl std::fmt::Display for ParenType {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for ParenthesizedArgList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for Path {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)