about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2023-05-06 20:29:13 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2023-05-06 20:31:11 +0900
commitfa2340a4dfb70834259ad704f0b3a13021fa1b54 (patch)
tree2b3cca042f55a90dcb537dbeff7f7390f9770280
parentd7d89712032e367b0eb8bafe9192403eef1ef4b2 (diff)
downloadrust-fa2340a4dfb70834259ad704f0b3a13021fa1b54.tar.gz
rust-fa2340a4dfb70834259ad704f0b3a13021fa1b54.zip
Parse associated return type bounds
-rw-r--r--crates/hir-def/src/path/lower.rs4
-rw-r--r--crates/parser/src/grammar/generic_args.rs23
-rw-r--r--crates/parser/src/grammar/paths.rs1
-rw-r--r--crates/parser/src/grammar/types.rs9
-rw-r--r--crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast38
-rw-r--r--crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs1
-rw-r--r--crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast102
-rw-r--r--crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs1
-rw-r--r--crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast175
-rw-r--r--crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs4
-rw-r--r--crates/syntax/rust.ungram6
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs2
12 files changed, 361 insertions, 5 deletions
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index 7e4b7ac34bf..26d2706175c 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -189,6 +189,10 @@ pub(super) fn lower_generic_args(
                 args.push(GenericArg::Type(type_ref));
             }
             ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
+                if assoc_type_arg.param_list().is_some() {
+                    // We currently ignore associated return type bounds.
+                    continue;
+                }
                 if let Some(name_ref) = assoc_type_arg.name_ref() {
                     let name = name_ref.as_name();
                     let args = assoc_type_arg
diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs
index e583a4de711..b7d72b8d336 100644
--- a/crates/parser/src/grammar/generic_args.rs
+++ b/crates/parser/src/grammar/generic_args.rs
@@ -76,6 +76,29 @@ fn generic_arg(p: &mut Parser<'_>) -> bool {
                 }
             }
         }
+        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,
     }
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs
index 26490aa97e0..01b8f9e9187 100644
--- a/crates/parser/src/grammar/paths.rs
+++ b/crates/parser/src/grammar/paths.rs
@@ -136,6 +136,7 @@ fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
         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![::]);
             }
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 26dac87956c..93ef4835027 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -337,13 +337,16 @@ pub(super) fn path_type_(p: &mut Parser<'_>, allow_bounds: bool) {
 
 /// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
 /// with a TYPE_BOUND_LIST
-fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedMarker) {
+pub(super) fn opt_type_bounds_as_dyn_trait_type(
+    p: &mut Parser<'_>,
+    type_marker: CompletedMarker,
+) -> CompletedMarker {
     assert!(matches!(
         type_marker.kind(),
         SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
     ));
     if !p.at(T![+]) {
-        return;
+        return type_marker;
     }
 
     // First create a TYPE_BOUND from the completed PATH_TYPE
@@ -360,5 +363,5 @@ fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser<'_>, type_marker: CompletedM
     let m = generic_params::bounds_without_colon_m(p, m);
 
     // Finally precede everything with DYN_TRAIT_TYPE
-    m.precede(p).complete(p, DYN_TRAIT_TYPE);
+    m.precede(p).complete(p, DYN_TRAIT_TYPE)
 }
diff --git a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
index b47a5a5c147..67277d0639a 100644
--- a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
+++ b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
@@ -41,3 +41,41 @@ SOURCE_FILE
             IDENT "End"
     SEMICOLON ";"
   WHITESPACE "\n"
+  TYPE_ALIAS
+    TYPE_KW "type"
+    WHITESPACE " "
+    NAME
+      IDENT "GenericArg"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PATH_TYPE
+      PATH
+        PATH_SEGMENT
+          NAME_REF
+            IDENT "S"
+          GENERIC_ARG_LIST
+            L_ANGLE "<"
+            TYPE_ARG
+              PATH_TYPE
+                PATH
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "Start"
+                      PARAM_LIST
+                        L_PAREN "("
+                        PARAM
+                          PATH_TYPE
+                            PATH
+                              PATH_SEGMENT
+                                NAME_REF
+                                  IDENT "Middle"
+                        R_PAREN ")"
+                  COLON2 "::"
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "End"
+            R_ANGLE ">"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
index 8efd93a7ff6..8c54f6704b3 100644
--- a/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
+++ b/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
@@ -1 +1,2 @@
 type F = Start::(Middle) -> (Middle)::End;
+type GenericArg = S<Start(Middle)::End>;
diff --git a/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast
new file mode 100644
index 00000000000..2fa52068c9b
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast
@@ -0,0 +1,102 @@
+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 "Foo"
+                  GENERIC_ARG_LIST
+                    L_ANGLE "<"
+                    ASSOC_TYPE_ARG
+                      NAME_REF
+                        IDENT "foo"
+                      PARAM_LIST
+                        L_PAREN "("
+                        R_PAREN ")"
+                      COLON ":"
+                      WHITESPACE " "
+                      TYPE_BOUND_LIST
+                        TYPE_BOUND
+                          PATH_TYPE
+                            PATH
+                              PATH_SEGMENT
+                                NAME_REF
+                                  IDENT "Send"
+                    COMMA ","
+                    WHITESPACE " "
+                    ASSOC_TYPE_ARG
+                      NAME_REF
+                        IDENT "bar"
+                      PARAM_LIST
+                        L_PAREN "("
+                        PARAM
+                          PATH_TYPE
+                            PATH
+                              PATH_SEGMENT
+                                NAME_REF
+                                  IDENT "i32"
+                        R_PAREN ")"
+                      COLON ":"
+                      WHITESPACE " "
+                      TYPE_BOUND_LIST
+                        TYPE_BOUND
+                          PATH_TYPE
+                            PATH
+                              PATH_SEGMENT
+                                NAME_REF
+                                  IDENT "Send"
+                    COMMA ","
+                    WHITESPACE " "
+                    ASSOC_TYPE_ARG
+                      NAME_REF
+                        IDENT "baz"
+                      PARAM_LIST
+                        L_PAREN "("
+                        PARAM
+                          PATH_TYPE
+                            PATH
+                              PATH_SEGMENT
+                                NAME_REF
+                                  IDENT "i32"
+                        COMMA ","
+                        WHITESPACE " "
+                        PARAM
+                          PATH_TYPE
+                            PATH
+                              PATH_SEGMENT
+                                NAME_REF
+                                  IDENT "i32"
+                        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/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs
new file mode 100644
index 00000000000..42029ac5927
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs
@@ -0,0 +1 @@
+fn foo<T: Foo<foo(): Send, bar(i32): Send, baz(i32, i32): Send>>() {}
diff --git a/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast
new file mode 100644
index 00000000000..d5f97bad898
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast
@@ -0,0 +1,175 @@
+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/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs
new file mode 100644
index 00000000000..800002b1b82
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs
@@ -0,0 +1,4 @@
+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/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 1c15a606f95..4c9027dec68 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -51,7 +51,9 @@ TypeArg =
   Type
 
 AssocTypeArg =
-  NameRef GenericArgList? (':' TypeBoundList | ('=' Type | ConstArg))
+  NameRef
+  (GenericArgList | ParamList RetType?)?
+  (':' TypeBoundList | ('=' Type | ConstArg))
 
 LifetimeArg =
   Lifetime
@@ -581,7 +583,7 @@ ImplTraitType =
   'impl' TypeBoundList
 
 DynTraitType =
-  'dyn' TypeBoundList
+  'dyn'? TypeBoundList
 
 TypeBoundList =
   bounds:(TypeBound ('+' TypeBound)* '+'?)
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 0e84aca5c7d..61f6a04c98d 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -121,6 +121,8 @@ impl ast::HasTypeBounds for AssocTypeArg {}
 impl AssocTypeArg {
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }