]> git.lizzy.rs Git - rust.git/commitdiff
Properly parse legacy trait objects with leading ForType
authorLukas Wirth <lukastw97@gmail.com>
Sun, 20 Dec 2020 20:53:55 +0000 (21:53 +0100)
committerLukas Wirth <lukastw97@gmail.com>
Sun, 20 Dec 2020 20:53:55 +0000 (21:53 +0100)
crates/parser/src/grammar/type_params.rs
crates/parser/src/grammar/types.rs
crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast [new file with mode: 0644]
crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs [new file with mode: 0644]

index 9c3f7c28a2ad8dfb322b85279d6c78644387ae35..4aeccd193c18e1a2e89ee96c0f220dfdcdd27ab4 100644 (file)
@@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
     p.eat(T![?]);
     match p.current() {
         LIFETIME_IDENT => lifetime(p),
-        T![for] => types::for_type(p),
+        T![for] => types::for_type(p, false),
         _ if paths::is_use_path_start(p) => types::path_type_(p, false),
         _ => {
             m.abandon(p);
index 36a15eace822e1ea326865c0c49dd0c8d551581d..94cbf7d85a0a5315ced6ffedf6a940dd8ab7b9af 100644 (file)
@@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
         T![&] => ref_type(p),
         T![_] => infer_type(p),
         T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
-        T![for] => for_type(p),
+        T![for] => for_type(p, allow_bounds),
         T![impl] => impl_trait_type(p),
         T![dyn] => dyn_trait_type(p),
         // Some path types are not allowed to have bounds (no plus)
@@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
 // type A = for<'a> fn() -> ();
 // type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
 // type Obj = for<'a> PartialEq<&'a i32>;
-pub(super) fn for_type(p: &mut Parser) {
+pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
     assert!(p.at(T![for]));
     let m = p.start();
     for_binder(p);
@@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
         }
     }
     type_no_bounds(p);
-    m.complete(p, FOR_TYPE);
+    let completed = m.complete(p, FOR_TYPE);
+
+    // test no_dyn_trait_leading_for
+    // type A = for<'a> Test<'a> + Send;
+    if allow_bounds {
+        opt_type_bounds_as_dyn_trait_type(p, completed);
+    }
 }
 
 // test impl_trait_type
@@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
     let path = m.complete(p, kind);
 
     if allow_bounds {
-        opt_path_type_bounds_as_dyn_trait_type(p, path);
+        opt_type_bounds_as_dyn_trait_type(p, path);
     }
 }
 
@@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
     // fn foo() -> Box<dyn T + 'f> {}
     let path = m.complete(p, PATH_TYPE);
     if allow_bounds {
-        opt_path_type_bounds_as_dyn_trait_type(p, path);
+        opt_type_bounds_as_dyn_trait_type(p, path);
     }
 }
 
-/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE
+/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
 /// with a TYPE_BOUND_LIST
-fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) {
+fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
+    assert!(matches!(
+        type_marker.kind(),
+        SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
+    ));
     if !p.at(T![+]) {
         return;
     }
 
     // First create a TYPE_BOUND from the completed PATH_TYPE
-    let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
+    let m = type_marker.precede(p).complete(p, TYPE_BOUND);
 
     // Next setup a marker for the TYPE_BOUND_LIST
     let m = m.precede(p);
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
new file mode 100644 (file)
index 0000000..edfcb28
--- /dev/null
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..34
+  TYPE_ALIAS@0..33
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    DYN_TRAIT_TYPE@9..32
+      TYPE_BOUND_LIST@9..32
+        TYPE_BOUND@9..25
+          FOR_TYPE@9..25
+            FOR_KW@9..12 "for"
+            GENERIC_PARAM_LIST@12..16
+              L_ANGLE@12..13 "<"
+              LIFETIME_PARAM@13..15
+                LIFETIME@13..15
+                  LIFETIME_IDENT@13..15 "\'a"
+              R_ANGLE@15..16 ">"
+            WHITESPACE@16..17 " "
+            PATH_TYPE@17..25
+              PATH@17..25
+                PATH_SEGMENT@17..25
+                  NAME_REF@17..21
+                    IDENT@17..21 "Test"
+                  GENERIC_ARG_LIST@21..25
+                    L_ANGLE@21..22 "<"
+                    LIFETIME_ARG@22..24
+                      LIFETIME@22..24
+                        LIFETIME_IDENT@22..24 "\'a"
+                    R_ANGLE@24..25 ">"
+        WHITESPACE@25..26 " "
+        PLUS@26..27 "+"
+        WHITESPACE@27..28 " "
+        TYPE_BOUND@28..32
+          PATH_TYPE@28..32
+            PATH@28..32
+              PATH_SEGMENT@28..32
+                NAME_REF@28..32
+                  IDENT@28..32 "Send"
+    SEMICOLON@32..33 ";"
+  WHITESPACE@33..34 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
new file mode 100644 (file)
index 0000000..47a71fd
--- /dev/null
@@ -0,0 +1 @@
+type A = for<'a> Test<'a> + Send;