aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-10-06 22:46:26 +0100
committerLukas Wirth <[email protected]>2020-10-06 22:52:00 +0100
commit6f38552edb7be10d526aa6510200b547a301593f (patch)
treeb5598c947e104c7020ee590ff33bb1b7717861ec /crates/syntax/src
parent87cb840a4e140a49946235823384694da58c2a5a (diff)
Add validation check for ambiguous trait objects
Diffstat (limited to 'crates/syntax/src')
-rw-r--r--crates/syntax/src/validation.rs45
1 files changed, 44 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}