Skip to content

Commit a184c83

Browse files
bors[bot]Veykril
andauthored
Merge #6160
6160: Add validation check for ambiguous trait objects r=matklad a=Veykril Fixes #285. Co-authored-by: Lukas Wirth <[email protected]>
2 parents 761c879 + 6f38552 commit a184c83

File tree

5 files changed

+448
-1
lines changed

5 files changed

+448
-1
lines changed

crates/syntax/src/validation.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
mod block;
44

55
use crate::{
6-
ast, match_ast, AstNode, SyntaxError,
6+
algo, ast, match_ast, AstNode, SyntaxError,
77
SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS},
88
SyntaxNode, SyntaxToken, TextSize, T,
99
};
10+
use rowan::Direction;
1011
use rustc_lexer::unescape::{
1112
self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
1213
};
@@ -95,6 +96,9 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
9596
ast::Visibility(it) => validate_visibility(it, &mut errors),
9697
ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
9798
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),
98102
_ => (),
99103
}
100104
}
@@ -301,3 +305,42 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
301305
return true;
302306
}
303307
}
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+
}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
2+
3+
4+
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
15+
16+
17+
18+
19+
20+
21+
22+
23+
24+
25+
26+
27+
28+
29+
30+
31+
32+
33+
34+
35+
36+
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+
63+
64+
65+
66+
67+
68+
69+
70+
71+
72+
73+
74+
75+
76+
77+
78+
79+
80+
81+
82+
83+
84+
85+
86+
87+
88+
89+
90+
91+
92+
93+
94+
95+
96+
97+
98+
99+
100+
101+
102+
103+
104+
[email protected] "\'static"
105+
106+
107+
108+
109+
110+
111+
112+
113+
114+
115+
116+
117+
118+
119+
120+
121+
122+
123+
124+
125+
126+
127+
128+
129+
130+
131+
132+
133+
134+
135+
136+
137+
138+
139+
140+
141+
142+
143+
144+
145+
146+
147+
148+
149+
150+
151+
152+
153+
154+
155+
156+
157+
158+
159+
160+
161+
162+
163+
164+
165+
166+
167+
168+
169+
170+
171+
172+
173+
174+
175+
176+
177+
178+
179+
180+
181+
182+
183+
184+
185+
186+
187+
188+
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
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

0 commit comments

Comments
 (0)