@@ -7,7 +7,7 @@ pub mod suggestions;
7
7
use std:: { fmt, iter} ;
8
8
9
9
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
10
- use rustc_errors:: { Applicability , Diag , E0038 , E0276 , MultiSpan , struct_span_code_err} ;
10
+ use rustc_errors:: { Applicability , Diag , E0038 , E0276 , E0802 , MultiSpan , struct_span_code_err} ;
11
11
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
12
12
use rustc_hir:: intravisit:: Visitor ;
13
13
use rustc_hir:: { self as hir, LangItem } ;
@@ -428,10 +428,46 @@ pub fn report_dyn_incompatibility<'tcx>(
428
428
violations : & [ DynCompatibilityViolation ] ,
429
429
) -> Diag < ' tcx > {
430
430
let trait_str = tcx. def_path_str ( trait_def_id) ;
431
+
432
+ // Avoid errors diving into the details of the `AsyncFn` traits if this is
433
+ // a straightforward "`AsyncFn` is not yet dyn-compatible" error.
434
+ if let Some ( async_fn_trait_kind) = tcx. async_fn_trait_kind_from_def_id ( trait_def_id) {
435
+ let async_fn_trait_name = match async_fn_trait_kind {
436
+ ty:: ClosureKind :: Fn => "AsyncFn" ,
437
+ ty:: ClosureKind :: FnMut => "AsyncFnMut" ,
438
+ ty:: ClosureKind :: FnOnce => "AsyncFnOnce" ,
439
+ } ;
440
+
441
+ let mut err = struct_span_code_err ! (
442
+ tcx. dcx( ) ,
443
+ span,
444
+ E0802 ,
445
+ "the trait `{}` is not yet dyn-compatible" ,
446
+ async_fn_trait_name
447
+ ) ;
448
+ // Note: this check is quite imprecise.
449
+ // Comparing the DefIds or similar would be better, but we can't store
450
+ // DefIds in `DynCompatibilityViolation`.
451
+ if async_fn_trait_name == trait_str {
452
+ err. span_label ( span, format ! ( "`{async_fn_trait_name}` is not yet dyn compatible" ) ) ;
453
+ } else {
454
+ let trait_str = tcx. def_path_str ( trait_def_id) ;
455
+ err. span_label (
456
+ span,
457
+ format ! (
458
+ "`{trait_str}` inherits from `{async_fn_trait_name}` which is not yet dyn-compatible'"
459
+ ) ,
460
+ ) ;
461
+ }
462
+ attempt_dyn_to_impl_suggestion ( tcx, hir_id, & mut err) ;
463
+ return err;
464
+ }
465
+
431
466
let trait_span = tcx. hir ( ) . get_if_local ( trait_def_id) . and_then ( |node| match node {
432
467
hir:: Node :: Item ( item) => Some ( item. ident . span ) ,
433
468
_ => None ,
434
469
} ) ;
470
+
435
471
let mut err = struct_span_code_err ! (
436
472
tcx. dcx( ) ,
437
473
span,
@@ -441,24 +477,8 @@ pub fn report_dyn_incompatibility<'tcx>(
441
477
) ;
442
478
err. span_label ( span, format ! ( "`{trait_str}` cannot be made into an object" ) ) ;
443
479
444
- if let Some ( hir_id) = hir_id
445
- && let hir:: Node :: Ty ( ty) = tcx. hir_node ( hir_id)
446
- && let hir:: TyKind :: TraitObject ( [ trait_ref, ..] , ..) = ty. kind
447
- {
448
- let mut hir_id = hir_id;
449
- while let hir:: Node :: Ty ( ty) = tcx. parent_hir_node ( hir_id) {
450
- hir_id = ty. hir_id ;
451
- }
452
- if tcx. parent_hir_node ( hir_id) . fn_sig ( ) . is_some ( ) {
453
- // Do not suggest `impl Trait` when dealing with things like super-traits.
454
- err. span_suggestion_verbose (
455
- ty. span . until ( trait_ref. span ) ,
456
- "consider using an opaque type instead" ,
457
- "impl " ,
458
- Applicability :: MaybeIncorrect ,
459
- ) ;
460
- }
461
- }
480
+ attempt_dyn_to_impl_suggestion ( tcx, hir_id, & mut err) ;
481
+
462
482
let mut reported_violations = FxIndexSet :: default ( ) ;
463
483
let mut multi_span = vec ! [ ] ;
464
484
let mut messages = vec ! [ ] ;
@@ -583,3 +603,27 @@ pub fn report_dyn_incompatibility<'tcx>(
583
603
584
604
err
585
605
}
606
+
607
+ fn attempt_dyn_to_impl_suggestion ( tcx : TyCtxt < ' _ > , hir_id : Option < hir:: HirId > , err : & mut Diag < ' _ > ) {
608
+ let Some ( hir_id) = hir_id else { return } ;
609
+ let hir:: Node :: Ty ( ty) = tcx. hir_node ( hir_id) else { return } ;
610
+ let hir:: TyKind :: TraitObject ( [ trait_ref, ..] , ..) = ty. kind else { return } ;
611
+ // Get the top-most parent element which is a type.
612
+ let parent_ty_hir_id = tcx
613
+ . hir ( )
614
+ . parent_iter ( hir_id)
615
+ . take_while ( |( _id, node) | matches ! ( node, hir:: Node :: Ty ( _) ) )
616
+ . last ( )
617
+ . map ( |( id, _node) | id)
618
+ . unwrap_or ( hir_id) ;
619
+ if tcx. parent_hir_node ( parent_ty_hir_id) . fn_sig ( ) . is_none ( ) {
620
+ // Do not suggest `impl Trait` when dealing with things like super-traits.
621
+ return ;
622
+ }
623
+ err. span_suggestion_verbose (
624
+ ty. span . until ( trait_ref. span ) ,
625
+ "consider using an opaque type instead" ,
626
+ "impl " ,
627
+ Applicability :: MaybeIncorrect ,
628
+ ) ;
629
+ }
0 commit comments