Add validation check for ambiguous trait objects

This commit is contained in:
Lukas Wirth 2020-10-06 23:46:26 +02:00
parent 87cb840a4e
commit 6f38552edb
5 changed files with 448 additions and 1 deletions

View File

@ -3,10 +3,11 @@
mod block;
use crate::{
ast, match_ast, AstNode, SyntaxError,
algo, ast, match_ast, AstNode, SyntaxError,
SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS},
SyntaxNode, SyntaxToken, TextSize, T,
};
use rowan::Direction;
use rustc_lexer::unescape::{
self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
};
@ -95,6 +96,9 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
ast::Visibility(it) => validate_visibility(it, &mut errors),
ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
ast::PathSegment(it) => validate_path_keywords(it, &mut errors),
ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors),
ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
_ => (),
}
}
@ -301,3 +305,42 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
return true;
}
}
fn validate_trait_object_ref_ty(ty: ast::RefType, errors: &mut Vec<SyntaxError>) {
if let Some(ast::Type::DynTraitType(ty)) = ty.ty() {
if let Some(err) = validate_trait_object_ty(ty) {
errors.push(err);
}
}
}
fn validate_trait_object_ptr_ty(ty: ast::PtrType, errors: &mut Vec<SyntaxError>) {
if let Some(ast::Type::DynTraitType(ty)) = ty.ty() {
if let Some(err) = validate_trait_object_ty(ty) {
errors.push(err);
}
}
}
fn validate_trait_object_fn_ptr_ret_ty(ty: ast::FnPtrType, errors: &mut Vec<SyntaxError>) {
if let Some(ast::Type::DynTraitType(ty)) = ty.ret_type().and_then(|ty| ty.ty()) {
if let Some(err) = validate_trait_object_ty(ty) {
errors.push(err);
}
}
}
fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
let tbl = ty.type_bound_list()?;
if tbl.bounds().count() > 1 {
let dyn_token = ty.dyn_token()?;
let potential_parentheses =
algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?;
let kind = potential_parentheses.kind();
if !matches!(kind, T!['('] | T![<] | T![=]) {
return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range()));
}
}
None
}

View File

@ -0,0 +1,192 @@
SOURCE_FILE@0..187
TYPE_ALIAS@0..35
TYPE_KW@0..4 "type"
WHITESPACE@4..5 " "
NAME@5..8
IDENT@5..8 "Foo"
GENERIC_PARAM_LIST@8..12
L_ANGLE@8..9 "<"
LIFETIME_PARAM@9..11
LIFETIME@9..11 "\'a"
R_ANGLE@11..12 ">"
WHITESPACE@12..13 " "
EQ@13..14 "="
WHITESPACE@14..15 " "
REF_TYPE@15..34
AMP@15..16 "&"
LIFETIME@16..18 "\'a"
WHITESPACE@18..19 " "
DYN_TRAIT_TYPE@19..34
DYN_KW@19..22 "dyn"
WHITESPACE@22..23 " "
TYPE_BOUND_LIST@23..34
TYPE_BOUND@23..27
PATH_TYPE@23..27
PATH@23..27
PATH_SEGMENT@23..27
NAME_REF@23..27
IDENT@23..27 "Send"
WHITESPACE@27..28 " "
PLUS@28..29 "+"
WHITESPACE@29..30 " "
TYPE_BOUND@30..34
PATH_TYPE@30..34
PATH@30..34
PATH_SEGMENT@30..34
NAME_REF@30..34
IDENT@30..34 "Sync"
SEMICOLON@34..35 ";"
WHITESPACE@35..36 "\n"
TYPE_ALIAS@36..70
TYPE_KW@36..40 "type"
WHITESPACE@40..41 " "
NAME@41..44
IDENT@41..44 "Foo"
WHITESPACE@44..45 " "
EQ@45..46 "="
WHITESPACE@46..47 " "
PTR_TYPE@47..69
STAR@47..48 "*"
CONST_KW@48..53 "const"
WHITESPACE@53..54 " "
DYN_TRAIT_TYPE@54..69
DYN_KW@54..57 "dyn"
WHITESPACE@57..58 " "
TYPE_BOUND_LIST@58..69
TYPE_BOUND@58..62
PATH_TYPE@58..62
PATH@58..62
PATH_SEGMENT@58..62
NAME_REF@58..62
IDENT@58..62 "Send"
WHITESPACE@62..63 " "
PLUS@63..64 "+"
WHITESPACE@64..65 " "
TYPE_BOUND@65..69
PATH_TYPE@65..69
PATH@65..69
PATH_SEGMENT@65..69
NAME_REF@65..69
IDENT@65..69 "Sync"
SEMICOLON@69..70 ";"
WHITESPACE@70..71 "\n"
TYPE_ALIAS@71..109
TYPE_KW@71..75 "type"
WHITESPACE@75..76 " "
NAME@76..79
IDENT@76..79 "Foo"
WHITESPACE@79..80 " "
EQ@80..81 "="
WHITESPACE@81..82 " "
FN_PTR_TYPE@82..108
FN_KW@82..84 "fn"
PARAM_LIST@84..86
L_PAREN@84..85 "("
R_PAREN@85..86 ")"
WHITESPACE@86..87 " "
RET_TYPE@87..108
THIN_ARROW@87..89 "->"
WHITESPACE@89..90 " "
DYN_TRAIT_TYPE@90..108
DYN_KW@90..93 "dyn"
WHITESPACE@93..94 " "
TYPE_BOUND_LIST@94..108
TYPE_BOUND@94..98
PATH_TYPE@94..98
PATH@94..98
PATH_SEGMENT@94..98
NAME_REF@94..98
IDENT@94..98 "Send"
WHITESPACE@98..99 " "
PLUS@99..100 "+"
WHITESPACE@100..101 " "
TYPE_BOUND@101..108
LIFETIME@101..108 "\'static"
SEMICOLON@108..109 ";"
WHITESPACE@109..110 "\n"
FN@110..186
FN_KW@110..112 "fn"
WHITESPACE@112..113 " "
NAME@113..117
IDENT@113..117 "main"
PARAM_LIST@117..119
L_PAREN@117..118 "("
R_PAREN@118..119 ")"
WHITESPACE@119..120 " "
BLOCK_EXPR@120..186
L_CURLY@120..121 "{"
WHITESPACE@121..126 "\n "
LET_STMT@126..184
LET_KW@126..129 "let"
WHITESPACE@129..130 " "
IDENT_PAT@130..131
NAME@130..131
IDENT@130..131 "b"
WHITESPACE@131..132 " "
EQ@132..133 "="
WHITESPACE@133..134 " "
CAST_EXPR@134..183
PAREN_EXPR@134..138
L_PAREN@134..135 "("
REF_EXPR@135..137
AMP@135..136 "&"
PATH_EXPR@136..137
PATH@136..137
PATH_SEGMENT@136..137
NAME_REF@136..137
IDENT@136..137 "a"
R_PAREN@137..138 ")"
WHITESPACE@138..139 " "
AS_KW@139..141 "as"
WHITESPACE@141..142 " "
REF_TYPE@142..183
AMP@142..143 "&"
DYN_TRAIT_TYPE@143..183
DYN_KW@143..146 "dyn"
WHITESPACE@146..147 " "
TYPE_BOUND_LIST@147..183
TYPE_BOUND@147..175
PATH_TYPE@147..175
PATH@147..175
PATH_SEGMENT@147..175
NAME_REF@147..150
IDENT@147..150 "Add"
GENERIC_ARG_LIST@150..175
L_ANGLE@150..151 "<"
TYPE_ARG@151..156
PATH_TYPE@151..156
PATH@151..156
PATH_SEGMENT@151..156
NAME_REF@151..156
IDENT@151..156 "Other"
COMMA@156..157 ","
WHITESPACE@157..158 " "
ASSOC_TYPE_ARG@158..174
NAME_REF@158..164
IDENT@158..164 "Output"
WHITESPACE@164..165 " "
EQ@165..166 "="
WHITESPACE@166..167 " "
PATH_TYPE@167..174
PATH@167..174
PATH_SEGMENT@167..174
NAME_REF@167..174
IDENT@167..174 "Addable"
R_ANGLE@174..175 ">"
WHITESPACE@175..176 " "
PLUS@176..177 "+"
WHITESPACE@177..178 " "
TYPE_BOUND@178..183
PATH_TYPE@178..183
PATH@178..183
PATH_SEGMENT@178..183
NAME_REF@178..183
IDENT@178..183 "Other"
SEMICOLON@183..184 ";"
WHITESPACE@184..185 "\n"
R_CURLY@185..186 "}"
WHITESPACE@186..187 "\n"
error 19..34: ambiguous `+` in a type
error 54..69: ambiguous `+` in a type
error 90..108: ambiguous `+` in a type
error 143..183: ambiguous `+` in a type

View File

@ -0,0 +1,6 @@
type Foo<'a> = &'a dyn Send + Sync;
type Foo = *const dyn Send + Sync;
type Foo = fn() -> dyn Send + 'static;
fn main() {
let b = (&a) as &dyn Add<Other, Output = Addable> + Other;
}

View File

@ -0,0 +1,200 @@
SOURCE_FILE@0..195
TYPE_ALIAS@0..37
TYPE_KW@0..4 "type"
WHITESPACE@4..5 " "
NAME@5..8
IDENT@5..8 "Foo"
GENERIC_PARAM_LIST@8..12
L_ANGLE@8..9 "<"
LIFETIME_PARAM@9..11
LIFETIME@9..11 "\'a"
R_ANGLE@11..12 ">"
WHITESPACE@12..13 " "
EQ@13..14 "="
WHITESPACE@14..15 " "
REF_TYPE@15..36
AMP@15..16 "&"
LIFETIME@16..18 "\'a"
WHITESPACE@18..19 " "
PAREN_TYPE@19..36
L_PAREN@19..20 "("
DYN_TRAIT_TYPE@20..35
DYN_KW@20..23 "dyn"
WHITESPACE@23..24 " "
TYPE_BOUND_LIST@24..35
TYPE_BOUND@24..28
PATH_TYPE@24..28
PATH@24..28
PATH_SEGMENT@24..28
NAME_REF@24..28
IDENT@24..28 "Send"
WHITESPACE@28..29 " "
PLUS@29..30 "+"
WHITESPACE@30..31 " "
TYPE_BOUND@31..35
PATH_TYPE@31..35
PATH@31..35
PATH_SEGMENT@31..35
NAME_REF@31..35
IDENT@31..35 "Sync"
R_PAREN@35..36 ")"
SEMICOLON@36..37 ";"
WHITESPACE@37..38 "\n"
TYPE_ALIAS@38..74
TYPE_KW@38..42 "type"
WHITESPACE@42..43 " "
NAME@43..46
IDENT@43..46 "Foo"
WHITESPACE@46..47 " "
EQ@47..48 "="
WHITESPACE@48..49 " "
PTR_TYPE@49..73
STAR@49..50 "*"
CONST_KW@50..55 "const"
WHITESPACE@55..56 " "
PAREN_TYPE@56..73
L_PAREN@56..57 "("
DYN_TRAIT_TYPE@57..72
DYN_KW@57..60 "dyn"
WHITESPACE@60..61 " "
TYPE_BOUND_LIST@61..72
TYPE_BOUND@61..65
PATH_TYPE@61..65
PATH@61..65
PATH_SEGMENT@61..65
NAME_REF@61..65
IDENT@61..65 "Send"
WHITESPACE@65..66 " "
PLUS@66..67 "+"
WHITESPACE@67..68 " "
TYPE_BOUND@68..72
PATH_TYPE@68..72
PATH@68..72
PATH_SEGMENT@68..72
NAME_REF@68..72
IDENT@68..72 "Sync"
R_PAREN@72..73 ")"
SEMICOLON@73..74 ";"
WHITESPACE@74..75 "\n"
TYPE_ALIAS@75..115
TYPE_KW@75..79 "type"
WHITESPACE@79..80 " "
NAME@80..83
IDENT@80..83 "Foo"
WHITESPACE@83..84 " "
EQ@84..85 "="
WHITESPACE@85..86 " "
FN_PTR_TYPE@86..114
FN_KW@86..88 "fn"
PARAM_LIST@88..90
L_PAREN@88..89 "("
R_PAREN@89..90 ")"
WHITESPACE@90..91 " "
RET_TYPE@91..114
THIN_ARROW@91..93 "->"
WHITESPACE@93..94 " "
PAREN_TYPE@94..114
L_PAREN@94..95 "("
DYN_TRAIT_TYPE@95..113
DYN_KW@95..98 "dyn"
WHITESPACE@98..99 " "
TYPE_BOUND_LIST@99..113
TYPE_BOUND@99..103
PATH_TYPE@99..103
PATH@99..103
PATH_SEGMENT@99..103
NAME_REF@99..103
IDENT@99..103 "Send"
WHITESPACE@103..104 " "
PLUS@104..105 "+"
WHITESPACE@105..106 " "
TYPE_BOUND@106..113
LIFETIME@106..113 "\'static"
R_PAREN@113..114 ")"
SEMICOLON@114..115 ";"
WHITESPACE@115..116 "\n"
FN@116..194
FN_KW@116..118 "fn"
WHITESPACE@118..119 " "
NAME@119..123
IDENT@119..123 "main"
PARAM_LIST@123..125
L_PAREN@123..124 "("
R_PAREN@124..125 ")"
WHITESPACE@125..126 " "
BLOCK_EXPR@126..194
L_CURLY@126..127 "{"
WHITESPACE@127..132 "\n "
LET_STMT@132..192
LET_KW@132..135 "let"
WHITESPACE@135..136 " "
IDENT_PAT@136..137
NAME@136..137
IDENT@136..137 "b"
WHITESPACE@137..138 " "
EQ@138..139 "="
WHITESPACE@139..140 " "
CAST_EXPR@140..191
PAREN_EXPR@140..144
L_PAREN@140..141 "("
REF_EXPR@141..143
AMP@141..142 "&"
PATH_EXPR@142..143
PATH@142..143
PATH_SEGMENT@142..143
NAME_REF@142..143
IDENT@142..143 "a"
R_PAREN@143..144 ")"
WHITESPACE@144..145 " "
AS_KW@145..147 "as"
WHITESPACE@147..148 " "
REF_TYPE@148..191
AMP@148..149 "&"
PAREN_TYPE@149..191
L_PAREN@149..150 "("
DYN_TRAIT_TYPE@150..190
DYN_KW@150..153 "dyn"
WHITESPACE@153..154 " "
TYPE_BOUND_LIST@154..190
TYPE_BOUND@154..182
PATH_TYPE@154..182
PATH@154..182
PATH_SEGMENT@154..182
NAME_REF@154..157
IDENT@154..157 "Add"
GENERIC_ARG_LIST@157..182
L_ANGLE@157..158 "<"
TYPE_ARG@158..163
PATH_TYPE@158..163
PATH@158..163
PATH_SEGMENT@158..163
NAME_REF@158..163
IDENT@158..163 "Other"
COMMA@163..164 ","
WHITESPACE@164..165 " "
ASSOC_TYPE_ARG@165..181
NAME_REF@165..171
IDENT@165..171 "Output"
WHITESPACE@171..172 " "
EQ@172..173 "="
WHITESPACE@173..174 " "
PATH_TYPE@174..181
PATH@174..181
PATH_SEGMENT@174..181
NAME_REF@174..181
IDENT@174..181 "Addable"
R_ANGLE@181..182 ">"
WHITESPACE@182..183 " "
PLUS@183..184 "+"
WHITESPACE@184..185 " "
TYPE_BOUND@185..190
PATH_TYPE@185..190
PATH@185..190
PATH_SEGMENT@185..190
NAME_REF@185..190
IDENT@185..190 "Other"
R_PAREN@190..191 ")"
SEMICOLON@191..192 ";"
WHITESPACE@192..193 "\n"
R_CURLY@193..194 "}"
WHITESPACE@194..195 "\n"

View File

@ -0,0 +1,6 @@
type Foo<'a> = &'a (dyn Send + Sync);
type Foo = *const (dyn Send + Sync);
type Foo = fn() -> (dyn Send + 'static);
fn main() {
let b = (&a) as &(dyn Add<Other, Output = Addable> + Other);
}