aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2020-10-06 22:46:26 +0100
committerLukas Wirth <lukastw97@gmail.com>2020-10-06 22:52:00 +0100
commit6f38552edb7be10d526aa6510200b547a301593f (patch)
treeb5598c947e104c7020ee590ff33bb1b7717861ec /crates
parent87cb840a4e140a49946235823384694da58c2a5a (diff)
Add validation check for ambiguous trait objects
Diffstat (limited to 'crates')
-rw-r--r--crates/syntax/src/validation.rs45
-rw-r--r--crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rast192
-rw-r--r--crates/syntax/test_data/parser/err/0046_ambiguous_trait_object.rs6
-rw-r--r--crates/syntax/test_data/parser/ok/0069_multi_trait_object.rast200
-rw-r--r--crates/syntax/test_data/parser/ok/0069_multi_trait_object.rs6
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 @@
3mod block; 3mod block;
4 4
5use crate::{ 5use 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};
10use rowan::Direction;
10use rustc_lexer::unescape::{ 11use 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
309fn 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
317fn 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
325fn 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
333fn 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 @@
1SOURCE_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"
189error 19..34: ambiguous `+` in a type
190error 54..69: ambiguous `+` in a type
191error 90..108: ambiguous `+` in a type
192error 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 @@
1type Foo<'a> = &'a dyn Send + Sync;
2type Foo = *const dyn Send + Sync;
3type Foo = fn() -> dyn Send + 'static;
4fn 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 @@
1SOURCE_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 @@
1type Foo<'a> = &'a (dyn Send + Sync);
2type Foo = *const (dyn Send + Sync);
3type Foo = fn() -> (dyn Send + 'static);
4fn main() {
5 let b = (&a) as &(dyn Add<Other, Output = Addable> + Other);
6}