@@ -37,7 +37,6 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec<SyntaxError>) {
37
37
ast:: FnPtrType ( it) => validate_trait_object_fn_ptr_ret_ty( it, errors) ,
38
38
ast:: MacroRules ( it) => validate_macro_rules( it, errors) ,
39
39
ast:: LetExpr ( it) => validate_let_expr( it, errors) ,
40
- ast:: ImplTraitType ( it) => validate_impl_object_ty( it, errors) ,
41
40
_ => ( ) ,
42
41
}
43
42
}
@@ -316,26 +315,50 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
316
315
}
317
316
318
317
fn validate_trait_object_ref_ty ( ty : ast:: RefType , errors : & mut Vec < SyntaxError > ) {
319
- if let Some ( ast:: Type :: DynTraitType ( ty) ) = ty. ty ( ) {
320
- if let Some ( err) = validate_trait_object_ty ( ty) {
321
- errors. push ( err) ;
318
+ match ty. ty ( ) {
319
+ Some ( ast:: Type :: DynTraitType ( ty) ) => {
320
+ if let Some ( err) = validate_trait_object_ty ( ty) {
321
+ errors. push ( err) ;
322
+ }
323
+ }
324
+ Some ( ast:: Type :: ImplTraitType ( ty) ) => {
325
+ if let Some ( err) = validate_impl_object_ty ( ty) {
326
+ errors. push ( err) ;
327
+ }
322
328
}
329
+ _ => ( ) ,
323
330
}
324
331
}
325
332
326
333
fn validate_trait_object_ptr_ty ( ty : ast:: PtrType , errors : & mut Vec < SyntaxError > ) {
327
- if let Some ( ast:: Type :: DynTraitType ( ty) ) = ty. ty ( ) {
328
- if let Some ( err) = validate_trait_object_ty ( ty) {
329
- errors. push ( err) ;
334
+ match ty. ty ( ) {
335
+ Some ( ast:: Type :: DynTraitType ( ty) ) => {
336
+ if let Some ( err) = validate_trait_object_ty ( ty) {
337
+ errors. push ( err) ;
338
+ }
330
339
}
340
+ Some ( ast:: Type :: ImplTraitType ( ty) ) => {
341
+ if let Some ( err) = validate_impl_object_ty ( ty) {
342
+ errors. push ( err) ;
343
+ }
344
+ }
345
+ _ => ( ) ,
331
346
}
332
347
}
333
348
334
349
fn validate_trait_object_fn_ptr_ret_ty ( ty : ast:: FnPtrType , errors : & mut Vec < SyntaxError > ) {
335
- if let Some ( ast:: Type :: DynTraitType ( ty) ) = ty. ret_type ( ) . and_then ( |ty| ty. ty ( ) ) {
336
- if let Some ( err) = validate_trait_object_ty ( ty) {
337
- errors. push ( err) ;
350
+ match ty. ret_type ( ) . and_then ( |ty| ty. ty ( ) ) {
351
+ Some ( ast:: Type :: DynTraitType ( ty) ) => {
352
+ if let Some ( err) = validate_trait_object_ty ( ty) {
353
+ errors. push ( err) ;
354
+ }
355
+ }
356
+ Some ( ast:: Type :: ImplTraitType ( ty) ) => {
357
+ if let Some ( err) = validate_impl_object_ty ( ty) {
358
+ errors. push ( err) ;
359
+ }
338
360
}
361
+ _ => ( ) ,
339
362
}
340
363
}
341
364
@@ -353,6 +376,7 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
353
376
let preceding_token =
354
377
algo:: skip_trivia_token ( dyn_token. prev_token ( ) ?, Direction :: Prev ) ?;
355
378
379
+ // FIXME: This is not a validation error, this is a context dependent parse error
356
380
if !matches ! ( preceding_token. kind( ) , T ![ '(' ] | T ![ <] | T ![ =] ) {
357
381
return Some ( SyntaxError :: new ( "ambiguous `+` in a type" , ty. syntax ( ) . text_range ( ) ) ) ;
358
382
}
@@ -362,41 +386,27 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
362
386
}
363
387
}
364
388
365
- fn validate_impl_object_ty ( ty : ast:: ImplTraitType , errors : & mut Vec < SyntaxError > ) {
366
- let Some ( bound_list) = ty. type_bound_list ( ) else {
367
- errors. push ( SyntaxError :: new (
368
- "At least one trait must be specified" ,
369
- ty. syntax ( ) . text_range ( ) ,
370
- ) ) ;
371
- return ;
372
- } ;
373
-
374
- let bounds: Vec < _ > = bound_list. bounds ( ) . collect ( ) ;
389
+ fn validate_impl_object_ty ( ty : ast:: ImplTraitType ) -> Option < SyntaxError > {
390
+ let tbl = ty. type_bound_list ( ) ?;
391
+ let bounds_count = tbl. bounds ( ) . count ( ) ;
375
392
376
- if !bounds . iter ( ) . any ( |b| ! matches ! ( b . kind ( ) , ast :: TypeBoundKind :: Lifetime ( _ ) ) ) {
377
- errors . push ( SyntaxError :: new (
378
- "At least one trait must be specified " ,
393
+ match bounds_count {
394
+ 0 => Some ( SyntaxError :: new (
395
+ "At least one trait is required for an object type " ,
379
396
ty. syntax ( ) . text_range ( ) ,
380
- ) ) ;
381
- return ;
382
- }
383
-
384
- if bounds. len ( ) == 1 {
385
- return ;
386
- }
387
-
388
- let Some ( preceding_token) = ty
389
- . impl_token ( )
390
- . and_then ( |token| token. prev_token ( ) )
391
- . and_then ( |prev| algo:: skip_trivia_token ( prev, Direction :: Prev ) )
392
- else {
393
- return ;
394
- } ;
397
+ ) ) ,
398
+ _ if bounds_count > 1 => {
399
+ let impl_token = ty. impl_token ( ) ?;
400
+ let preceding_token =
401
+ algo:: skip_trivia_token ( impl_token. prev_token ( ) ?, Direction :: Prev ) ?;
395
402
396
- if !matches ! ( preceding_token. kind( ) , T ![ '(' ] | T ![ <] | T ![ =] )
397
- && matches ! ( preceding_token. kind( ) , T ![ & ] )
398
- {
399
- errors. push ( SyntaxError :: new ( "ambiguous `+` in a type" , ty. syntax ( ) . text_range ( ) ) ) ;
403
+ // FIXME: This is not a validation error, this is a context dependent parse error
404
+ if !matches ! ( preceding_token. kind( ) , T ![ '(' ] | T ![ <] | T ![ =] ) {
405
+ return Some ( SyntaxError :: new ( "ambiguous `+` in a type" , ty. syntax ( ) . text_range ( ) ) ) ;
406
+ }
407
+ None
408
+ }
409
+ _ => None ,
400
410
}
401
411
}
402
412
0 commit comments