@@ -2,9 +2,10 @@ use super::ObjectSafetyViolation;
2
2
3
3
use crate :: infer:: InferCtxt ;
4
4
use rustc_data_structures:: fx:: FxIndexSet ;
5
- use rustc_errors:: { struct_span_err, DiagnosticBuilder , MultiSpan } ;
5
+ use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder , MultiSpan } ;
6
6
use rustc_hir as hir;
7
7
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
8
+ use rustc_hir:: intravisit:: Map ;
8
9
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
9
10
use rustc_middle:: ty:: { self , TyCtxt } ;
10
11
use rustc_span:: Span ;
@@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
42
43
pub fn report_object_safety_error < ' tcx > (
43
44
tcx : TyCtxt < ' tcx > ,
44
45
span : Span ,
46
+ hir_id : Option < hir:: HirId > ,
45
47
trait_def_id : DefId ,
46
48
violations : & [ ObjectSafetyViolation ] ,
47
49
) -> DiagnosticBuilder < ' tcx > {
@@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>(
59
61
) ;
60
62
err. span_label ( span, format ! ( "`{trait_str}` cannot be made into an object" ) ) ;
61
63
64
+ if let Some ( hir_id) = hir_id
65
+ && let Some ( hir:: Node :: Ty ( ty) ) = tcx. hir ( ) . find ( hir_id)
66
+ && let hir:: TyKind :: TraitObject ( [ trait_ref, ..] , ..) = ty. kind
67
+ {
68
+ let mut hir_id = hir_id;
69
+ while let hir:: Node :: Ty ( ty) = tcx. hir ( ) . get_parent ( hir_id) {
70
+ hir_id = ty. hir_id ;
71
+ }
72
+ if tcx. hir ( ) . get_parent ( hir_id) . fn_sig ( ) . is_some ( ) {
73
+ // Do not suggest `impl Trait` when dealing with things like super-traits.
74
+ err. span_suggestion_verbose (
75
+ ty. span . until ( trait_ref. span ) ,
76
+ "consider using an opaque type instead" ,
77
+ "impl " ,
78
+ Applicability :: MaybeIncorrect ,
79
+ ) ;
80
+ }
81
+ }
62
82
let mut reported_violations = FxIndexSet :: default ( ) ;
63
83
let mut multi_span = vec ! [ ] ;
64
84
let mut messages = vec ! [ ] ;
0 commit comments