diff options
author | Lukas Wirth <lukastw97@gmail.com> | 2020-10-06 22:46:26 +0100 |
---|---|---|
committer | Lukas Wirth <lukastw97@gmail.com> | 2020-10-06 22:52:00 +0100 |
commit | 6f38552edb7be10d526aa6510200b547a301593f (patch) | |
tree | b5598c947e104c7020ee590ff33bb1b7717861ec /crates | |
parent | 87cb840a4e140a49946235823384694da58c2a5a (diff) |
Add validation check for ambiguous trait objects
Diffstat (limited to 'crates')
5 files changed, 448 insertions, 1 deletions
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 2dddaf09a..0f9a5e8ae 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs | |||
@@ -3,10 +3,11 @@ | |||
3 | mod block; | 3 | mod block; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | ast, match_ast, AstNode, SyntaxError, | 6 | algo, ast, match_ast, AstNode, SyntaxError, |
7 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS}, | 7 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS}, |
8 | SyntaxNode, SyntaxToken, TextSize, T, | 8 | SyntaxNode, SyntaxToken, TextSize, T, |
9 | }; | 9 | }; |
10 | use rowan::Direction; | ||
10 | use rustc_lexer::unescape::{ | 11 | use rustc_lexer::unescape::{ |
11 | self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode, | 12 | self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode, |
12 | }; | 13 | }; |
@@ -95,6 +96,9 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | |||
95 | ast::Visibility(it) => validate_visibility(it, &mut errors), | 96 | ast::Visibility(it) => validate_visibility(it, &mut errors), |
96 | ast::RangeExpr(it) => validate_range_expr(it, &mut errors), | 97 | ast::RangeExpr(it) => validate_range_expr(it, &mut errors), |
97 | ast::PathSegment(it) => validate_path_keywords(it, &mut errors), | 98 | ast::PathSegment(it) => validate_path_keywords(it, &mut errors), |
99 | ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors), | ||
100 | ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors), | ||
101 | ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors), | ||
98 | _ => (), | 102 | _ => (), |
99 | } | 103 | } |
100 | } | 104 | } |
@@ -301,3 +305,42 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro | |||
301 | return true; | 305 | return true; |
302 | } | 306 | } |
303 | } | 307 | } |
308 | |||
309 | fn validate_trait_object_ref_ty(ty: ast::RefType, errors: &mut Vec<SyntaxError>) { | ||
310 | if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { | ||
311 | if let Some(err) = validate_trait_object_ty(ty) { | ||
312 | errors.push(err); | ||
313 | } | ||
314 | } | ||
315 | } | ||
316 | |||
317 | fn validate_trait_object_ptr_ty(ty: ast::PtrType, errors: &mut Vec<SyntaxError>) { | ||
318 | if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { | ||
319 | if let Some(err) = validate_trait_object_ty(ty) { | ||
320 | errors.push(err); | ||
321 | } | ||
322 | } | ||
323 | } | ||
324 | |||
325 | fn validate_trait_object_fn_ptr_ret_ty(ty: ast::FnPtrType, errors: &mut Vec<SyntaxError>) { | ||
326 | if let Some(ast::Type::DynTraitType(ty)) = ty.ret_type().and_then(|ty| ty.ty()) { | ||
327 | if let Some(err) = validate_trait_object_ty(ty) { | ||
328 | errors.push(err); | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
333 | fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> { | ||
334 | let tbl = ty.type_bound_list()?; | ||
335 | |||
336 | if tbl.bounds().count() > 1 { | ||
337 | let dyn_token = ty.dyn_token()?; | ||
338 | let potential_parentheses = | ||
339 | algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; | ||
340 | let kind = potential_parentheses.kind(); | ||
341 | if !matches!(kind, T!['('] | T![<] | T![=]) { | ||
342 | return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); | ||
343 | } | ||
344 | } | ||
345 | None | ||
346 | } | ||
diff --git a/crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rast b/crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rast new file mode 100644 index 000000000..592741cdb --- /dev/null +++ b/crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rast | |||
@@ -0,0 +1,192 @@ | |||
1 | SOURCE_FILE@0..187 | ||
2 | TYPE_ALIAS@0..35 | ||
3 | TYPE_KW@0..4 "type" | ||
4 | WHITESPACE@4..5 " " | ||
5 | NAME@5..8 | ||
6 | IDENT@5..8 "Foo" | ||
7 | GENERIC_PARAM_LIST@8..12 | ||
8 | L_ANGLE@8..9 "<" | ||
9 | LIFETIME_PARAM@9..11 | ||
10 | LIFETIME@9..11 "\'a" | ||
11 | R_ANGLE@11..12 ">" | ||
12 | WHITESPACE@12..13 " " | ||
13 | EQ@13..14 "=" | ||
14 | WHITESPACE@14..15 " " | ||
15 | REF_TYPE@15..34 | ||
16 | AMP@15..16 "&" | ||
17 | LIFETIME@16..18 "\'a" | ||
18 | WHITESPACE@18..19 " " | ||
19 | DYN_TRAIT_TYPE@19..34 | ||
20 | DYN_KW@19..22 "dyn" | ||
21 | WHITESPACE@22..23 " " | ||
22 | TYPE_BOUND_LIST@23..34 | ||
23 | TYPE_BOUND@23..27 | ||
24 | PATH_TYPE@23..27 | ||
25 | PATH@23..27 | ||
26 | PATH_SEGMENT@23..27 | ||
27 | NAME_REF@23..27 | ||
28 | IDENT@23..27 "Send" | ||
29 | WHITESPACE@27..28 " " | ||
30 | PLUS@28..29 "+" | ||
31 | WHITESPACE@29..30 " " | ||
32 | TYPE_BOUND@30..34 | ||
33 | PATH_TYPE@30..34 | ||
34 | PATH@30..34 | ||
35 | PATH_SEGMENT@30..34 | ||
36 | NAME_REF@30..34 | ||
37 | IDENT@30..34 "Sync" | ||
38 | SEMICOLON@34..35 ";" | ||
39 | WHITESPACE@35..36 "\n" | ||
40 | TYPE_ALIAS@36..70 | ||
41 | TYPE_KW@36..40 "type" | ||
42 | WHITESPACE@40..41 " " | ||
43 | NAME@41..44 | ||
44 | IDENT@41..44 "Foo" | ||
45 | WHITESPACE@44..45 " " | ||
46 | EQ@45..46 "=" | ||
47 | WHITESPACE@46..47 " " | ||
48 | PTR_TYPE@47..69 | ||
49 | STAR@47..48 "*" | ||
50 | CONST_KW@48..53 "const" | ||
51 | WHITESPACE@53..54 " " | ||
52 | DYN_TRAIT_TYPE@54..69 | ||
53 | DYN_KW@54..57 "dyn" | ||
54 | WHITESPACE@57..58 " " | ||
55 | TYPE_BOUND_LIST@58..69 | ||
56 | TYPE_BOUND@58..62 | ||
57 | PATH_TYPE@58..62 | ||
58 | PATH@58..62 | ||
59 | PATH_SEGMENT@58..62 | ||
60 | NAME_REF@58..62 | ||
61 | IDENT@58..62 "Send" | ||
62 | WHITESPACE@62..63 " " | ||
63 | PLUS@63..64 "+" | ||
64 | WHITESPACE@64..65 " " | ||
65 | TYPE_BOUND@65..69 | ||
66 | PATH_TYPE@65..69 | ||
67 | PATH@65..69 | ||
68 | PATH_SEGMENT@65..69 | ||
69 | NAME_REF@65..69 | ||
70 | IDENT@65..69 "Sync" | ||
71 | SEMICOLON@69..70 ";" | ||
72 | WHITESPACE@70..71 "\n" | ||
73 | TYPE_ALIAS@71..109 | ||
74 | TYPE_KW@71..75 "type" | ||
75 | WHITESPACE@75..76 " " | ||
76 | NAME@76..79 | ||
77 | IDENT@76..79 "Foo" | ||
78 | WHITESPACE@79..80 " " | ||
79 | EQ@80..81 "=" | ||
80 | WHITESPACE@81..82 " " | ||
81 | FN_PTR_TYPE@82..108 | ||
82 | FN_KW@82..84 "fn" | ||
83 | PARAM_LIST@84..86 | ||
84 | L_PAREN@84..85 "(" | ||
85 | R_PAREN@85..86 ")" | ||
86 | WHITESPACE@86..87 " " | ||
87 | RET_TYPE@87..108 | ||
88 | THIN_ARROW@87..89 "->" | ||
89 | WHITESPACE@89..90 " " | ||
90 | DYN_TRAIT_TYPE@90..108 | ||
91 | DYN_KW@90..93 "dyn" | ||
92 | WHITESPACE@93..94 " " | ||
93 | TYPE_BOUND_LIST@94..108 | ||
94 | TYPE_BOUND@94..98 | ||
95 | PATH_TYPE@94..98 | ||
96 | PATH@94..98 | ||
97 | PATH_SEGMENT@94..98 | ||
98 | NAME_REF@94..98 | ||
99 | IDENT@94..98 "Send" | ||
100 | WHITESPACE@98..99 " " | ||
101 | PLUS@99..100 "+" | ||
102 | WHITESPACE@100..101 " " | ||
103 | TYPE_BOUND@101..108 | ||
104 | LIFETIME@101..108 "\'static" | ||
105 | SEMICOLON@108..109 ";" | ||
106 | WHITESPACE@109..110 "\n" | ||
107 | FN@110..186 | ||
108 | FN_KW@110..112 "fn" | ||
109 | WHITESPACE@112..113 " " | ||
110 | NAME@113..117 | ||
111 | IDENT@113..117 "main" | ||
112 | PARAM_LIST@117..119 | ||
113 | L_PAREN@117..118 "(" | ||
114 | R_PAREN@118..119 ")" | ||
115 | WHITESPACE@119..120 " " | ||
116 | BLOCK_EXPR@120..186 | ||
117 | L_CURLY@120..121 "{" | ||
118 | WHITESPACE@121..126 "\n " | ||
119 | LET_STMT@126..184 | ||
120 | LET_KW@126..129 "let" | ||
121 | WHITESPACE@129..130 " " | ||
122 | IDENT_PAT@130..131 | ||
123 | NAME@130..131 | ||
124 | IDENT@130..131 "b" | ||
125 | WHITESPACE@131..132 " " | ||
126 | EQ@132..133 "=" | ||
127 | WHITESPACE@133..134 " " | ||
128 | CAST_EXPR@134..183 | ||
129 | PAREN_EXPR@134..138 | ||
130 | L_PAREN@134..135 "(" | ||
131 | REF_EXPR@135..137 | ||
132 | AMP@135..136 "&" | ||
133 | PATH_EXPR@136..137 | ||
134 | PATH@136..137 | ||
135 | PATH_SEGMENT@136..137 | ||
136 | NAME_REF@136..137 | ||
137 | IDENT@136..137 "a" | ||
138 | R_PAREN@137..138 ")" | ||
139 | WHITESPACE@138..139 " " | ||
140 | AS_KW@139..141 "as" | ||
141 | WHITESPACE@141..142 " " | ||
142 | REF_TYPE@142..183 | ||
143 | AMP@142..143 "&" | ||
144 | DYN_TRAIT_TYPE@143..183 | ||
145 | DYN_KW@143..146 "dyn" | ||
146 | WHITESPACE@146..147 " " | ||
147 | TYPE_BOUND_LIST@147..183 | ||
148 | TYPE_BOUND@147..175 | ||
149 | PATH_TYPE@147..175 | ||
150 | PATH@147..175 | ||
151 | PATH_SEGMENT@147..175 | ||
152 | NAME_REF@147..150 | ||
153 | IDENT@147..150 "Add" | ||
154 | GENERIC_ARG_LIST@150..175 | ||
155 | L_ANGLE@150..151 "<" | ||
156 | TYPE_ARG@151..156 | ||
157 | PATH_TYPE@151..156 | ||
158 | PATH@151..156 | ||
159 | PATH_SEGMENT@151..156 | ||
160 | NAME_REF@151..156 | ||
161 | IDENT@151..156 "Other" | ||
162 | COMMA@156..157 "," | ||
163 | WHITESPACE@157..158 " " | ||
164 | ASSOC_TYPE_ARG@158..174 | ||
165 | NAME_REF@158..164 | ||
166 | IDENT@158..164 "Output" | ||
167 | WHITESPACE@164..165 " " | ||
168 | EQ@165..166 "=" | ||
169 | WHITESPACE@166..167 " " | ||
170 | PATH_TYPE@167..174 | ||
171 | PATH@167..174 | ||
172 | PATH_SEGMENT@167..174 | ||
173 | NAME_REF@167..174 | ||
174 | IDENT@167..174 "Addable" | ||
175 | R_ANGLE@174..175 ">" | ||
176 | WHITESPACE@175..176 " " | ||
177 | PLUS@176..177 "+" | ||
178 | WHITESPACE@177..178 " " | ||
179 | TYPE_BOUND@178..183 | ||
180 | PATH_TYPE@178..183 | ||
181 | PATH@178..183 | ||
182 | PATH_SEGMENT@178..183 | ||
183 | NAME_REF@178..183 | ||
184 | IDENT@178..183 "Other" | ||
185 | SEMICOLON@183..184 ";" | ||
186 | WHITESPACE@184..185 "\n" | ||
187 | R_CURLY@185..186 "}" | ||
188 | WHITESPACE@186..187 "\n" | ||
189 | error 19..34: ambiguous `+` in a type | ||
190 | error 54..69: ambiguous `+` in a type | ||
191 | error 90..108: ambiguous `+` in a type | ||
192 | error 143..183: ambiguous `+` in a type | ||
diff --git a/crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rs b/crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rs new file mode 100644 index 000000000..3a73d81bb --- /dev/null +++ b/crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rs | |||
@@ -0,0 +1,6 @@ | |||
1 | type Foo<'a> = &'a dyn Send + Sync; | ||
2 | type Foo = *const dyn Send + Sync; | ||
3 | type Foo = fn() -> dyn Send + 'static; | ||
4 | fn main() { | ||
5 | let b = (&a) as &dyn Add<Other, Output = Addable> + Other; | ||
6 | } | ||
diff --git a/crates/syntax/test_data/parser/ok/0069_multi_trait_object.rast b/crates/syntax/test_data/parser/ok/0069_multi_trait_object.rast new file mode 100644 index 000000000..0cd868a83 --- /dev/null +++ b/crates/syntax/test_data/parser/ok/0069_multi_trait_object.rast | |||
@@ -0,0 +1,200 @@ | |||
1 | SOURCE_FILE@0..195 | ||
2 | TYPE_ALIAS@0..37 | ||
3 | TYPE_KW@0..4 "type" | ||
4 | WHITESPACE@4..5 " " | ||
5 | NAME@5..8 | ||
6 | IDENT@5..8 "Foo" | ||
7 | GENERIC_PARAM_LIST@8..12 | ||
8 | L_ANGLE@8..9 "<" | ||
9 | LIFETIME_PARAM@9..11 | ||
10 | LIFETIME@9..11 "\'a" | ||
11 | R_ANGLE@11..12 ">" | ||
12 | WHITESPACE@12..13 " " | ||
13 | EQ@13..14 "=" | ||
14 | WHITESPACE@14..15 " " | ||
15 | REF_TYPE@15..36 | ||
16 | AMP@15..16 "&" | ||
17 | LIFETIME@16..18 "\'a" | ||
18 | WHITESPACE@18..19 " " | ||
19 | PAREN_TYPE@19..36 | ||
20 | L_PAREN@19..20 "(" | ||
21 | DYN_TRAIT_TYPE@20..35 | ||
22 | DYN_KW@20..23 "dyn" | ||
23 | WHITESPACE@23..24 " " | ||
24 | TYPE_BOUND_LIST@24..35 | ||
25 | TYPE_BOUND@24..28 | ||
26 | PATH_TYPE@24..28 | ||
27 | PATH@24..28 | ||
28 | PATH_SEGMENT@24..28 | ||
29 | NAME_REF@24..28 | ||
30 | IDENT@24..28 "Send" | ||
31 | WHITESPACE@28..29 " " | ||
32 | PLUS@29..30 "+" | ||
33 | WHITESPACE@30..31 " " | ||
34 | TYPE_BOUND@31..35 | ||
35 | PATH_TYPE@31..35 | ||
36 | PATH@31..35 | ||
37 | PATH_SEGMENT@31..35 | ||
38 | NAME_REF@31..35 | ||
39 | IDENT@31..35 "Sync" | ||
40 | R_PAREN@35..36 ")" | ||
41 | SEMICOLON@36..37 ";" | ||
42 | WHITESPACE@37..38 "\n" | ||
43 | TYPE_ALIAS@38..74 | ||
44 | TYPE_KW@38..42 "type" | ||
45 | WHITESPACE@42..43 " " | ||
46 | NAME@43..46 | ||
47 | IDENT@43..46 "Foo" | ||
48 | WHITESPACE@46..47 " " | ||
49 | EQ@47..48 "=" | ||
50 | WHITESPACE@48..49 " " | ||
51 | PTR_TYPE@49..73 | ||
52 | STAR@49..50 "*" | ||
53 | CONST_KW@50..55 "const" | ||
54 | WHITESPACE@55..56 " " | ||
55 | PAREN_TYPE@56..73 | ||
56 | L_PAREN@56..57 "(" | ||
57 | DYN_TRAIT_TYPE@57..72 | ||
58 | DYN_KW@57..60 "dyn" | ||
59 | WHITESPACE@60..61 " " | ||
60 | TYPE_BOUND_LIST@61..72 | ||
61 | TYPE_BOUND@61..65 | ||
62 | PATH_TYPE@61..65 | ||
63 | PATH@61..65 | ||
64 | PATH_SEGMENT@61..65 | ||
65 | NAME_REF@61..65 | ||
66 | IDENT@61..65 "Send" | ||
67 | WHITESPACE@65..66 " " | ||
68 | PLUS@66..67 "+" | ||
69 | WHITESPACE@67..68 " " | ||
70 | TYPE_BOUND@68..72 | ||
71 | PATH_TYPE@68..72 | ||
72 | PATH@68..72 | ||
73 | PATH_SEGMENT@68..72 | ||
74 | NAME_REF@68..72 | ||
75 | IDENT@68..72 "Sync" | ||
76 | R_PAREN@72..73 ")" | ||
77 | SEMICOLON@73..74 ";" | ||
78 | WHITESPACE@74..75 "\n" | ||
79 | TYPE_ALIAS@75..115 | ||
80 | TYPE_KW@75..79 "type" | ||
81 | WHITESPACE@79..80 " " | ||
82 | NAME@80..83 | ||
83 | IDENT@80..83 "Foo" | ||
84 | WHITESPACE@83..84 " " | ||
85 | EQ@84..85 "=" | ||
86 | WHITESPACE@85..86 " " | ||
87 | FN_PTR_TYPE@86..114 | ||
88 | FN_KW@86..88 "fn" | ||
89 | PARAM_LIST@88..90 | ||
90 | L_PAREN@88..89 "(" | ||
91 | R_PAREN@89..90 ")" | ||
92 | WHITESPACE@90..91 " " | ||
93 | RET_TYPE@91..114 | ||
94 | THIN_ARROW@91..93 "->" | ||
95 | WHITESPACE@93..94 " " | ||
96 | PAREN_TYPE@94..114 | ||
97 | L_PAREN@94..95 "(" | ||
98 | DYN_TRAIT_TYPE@95..113 | ||
99 | DYN_KW@95..98 "dyn" | ||
100 | WHITESPACE@98..99 " " | ||
101 | TYPE_BOUND_LIST@99..113 | ||
102 | TYPE_BOUND@99..103 | ||
103 | PATH_TYPE@99..103 | ||
104 | PATH@99..103 | ||
105 | PATH_SEGMENT@99..103 | ||
106 | NAME_REF@99..103 | ||
107 | IDENT@99..103 "Send" | ||
108 | WHITESPACE@103..104 " " | ||
109 | PLUS@104..105 "+" | ||
110 | WHITESPACE@105..106 " " | ||
111 | TYPE_BOUND@106..113 | ||
112 | LIFETIME@106..113 "\'static" | ||
113 | R_PAREN@113..114 ")" | ||
114 | SEMICOLON@114..115 ";" | ||
115 | WHITESPACE@115..116 "\n" | ||
116 | FN@116..194 | ||
117 | FN_KW@116..118 "fn" | ||
118 | WHITESPACE@118..119 " " | ||
119 | NAME@119..123 | ||
120 | IDENT@119..123 "main" | ||
121 | PARAM_LIST@123..125 | ||
122 | L_PAREN@123..124 "(" | ||
123 | R_PAREN@124..125 ")" | ||
124 | WHITESPACE@125..126 " " | ||
125 | BLOCK_EXPR@126..194 | ||
126 | L_CURLY@126..127 "{" | ||
127 | WHITESPACE@127..132 "\n " | ||
128 | LET_STMT@132..192 | ||
129 | LET_KW@132..135 "let" | ||
130 | WHITESPACE@135..136 " " | ||
131 | IDENT_PAT@136..137 | ||
132 | NAME@136..137 | ||
133 | IDENT@136..137 "b" | ||
134 | WHITESPACE@137..138 " " | ||
135 | EQ@138..139 "=" | ||
136 | WHITESPACE@139..140 " " | ||
137 | CAST_EXPR@140..191 | ||
138 | PAREN_EXPR@140..144 | ||
139 | L_PAREN@140..141 "(" | ||
140 | REF_EXPR@141..143 | ||
141 | AMP@141..142 "&" | ||
142 | PATH_EXPR@142..143 | ||
143 | PATH@142..143 | ||
144 | PATH_SEGMENT@142..143 | ||
145 | NAME_REF@142..143 | ||
146 | IDENT@142..143 "a" | ||
147 | R_PAREN@143..144 ")" | ||
148 | WHITESPACE@144..145 " " | ||
149 | AS_KW@145..147 "as" | ||
150 | WHITESPACE@147..148 " " | ||
151 | REF_TYPE@148..191 | ||
152 | AMP@148..149 "&" | ||
153 | PAREN_TYPE@149..191 | ||
154 | L_PAREN@149..150 "(" | ||
155 | DYN_TRAIT_TYPE@150..190 | ||
156 | DYN_KW@150..153 "dyn" | ||
157 | WHITESPACE@153..154 " " | ||
158 | TYPE_BOUND_LIST@154..190 | ||
159 | TYPE_BOUND@154..182 | ||
160 | PATH_TYPE@154..182 | ||
161 | PATH@154..182 | ||
162 | PATH_SEGMENT@154..182 | ||
163 | NAME_REF@154..157 | ||
164 | IDENT@154..157 "Add" | ||
165 | GENERIC_ARG_LIST@157..182 | ||
166 | L_ANGLE@157..158 "<" | ||
167 | TYPE_ARG@158..163 | ||
168 | PATH_TYPE@158..163 | ||
169 | PATH@158..163 | ||
170 | PATH_SEGMENT@158..163 | ||
171 | NAME_REF@158..163 | ||
172 | IDENT@158..163 "Other" | ||
173 | COMMA@163..164 "," | ||
174 | WHITESPACE@164..165 " " | ||
175 | ASSOC_TYPE_ARG@165..181 | ||
176 | NAME_REF@165..171 | ||
177 | IDENT@165..171 "Output" | ||
178 | WHITESPACE@171..172 " " | ||
179 | EQ@172..173 "=" | ||
180 | WHITESPACE@173..174 " " | ||
181 | PATH_TYPE@174..181 | ||
182 | PATH@174..181 | ||
183 | PATH_SEGMENT@174..181 | ||
184 | NAME_REF@174..181 | ||
185 | IDENT@174..181 "Addable" | ||
186 | R_ANGLE@181..182 ">" | ||
187 | WHITESPACE@182..183 " " | ||
188 | PLUS@183..184 "+" | ||
189 | WHITESPACE@184..185 " " | ||
190 | TYPE_BOUND@185..190 | ||
191 | PATH_TYPE@185..190 | ||
192 | PATH@185..190 | ||
193 | PATH_SEGMENT@185..190 | ||
194 | NAME_REF@185..190 | ||
195 | IDENT@185..190 "Other" | ||
196 | R_PAREN@190..191 ")" | ||
197 | SEMICOLON@191..192 ";" | ||
198 | WHITESPACE@192..193 "\n" | ||
199 | R_CURLY@193..194 "}" | ||
200 | WHITESPACE@194..195 "\n" | ||
diff --git a/crates/syntax/test_data/parser/ok/0069_multi_trait_object.rs b/crates/syntax/test_data/parser/ok/0069_multi_trait_object.rs new file mode 100644 index 000000000..97eb79c48 --- /dev/null +++ b/crates/syntax/test_data/parser/ok/0069_multi_trait_object.rs | |||
@@ -0,0 +1,6 @@ | |||
1 | type Foo<'a> = &'a (dyn Send + Sync); | ||
2 | type Foo = *const (dyn Send + Sync); | ||
3 | type Foo = fn() -> (dyn Send + 'static); | ||
4 | fn main() { | ||
5 | let b = (&a) as &(dyn Add<Other, Output = Addable> + Other); | ||
6 | } | ||