@@ -2,9 +2,10 @@ use super::ObjectSafetyViolation;
22
33use crate :: infer:: InferCtxt ;
44use rustc_data_structures:: fx:: FxIndexSet ;
5- use rustc_errors:: { struct_span_err, DiagnosticBuilder , MultiSpan } ;
5+ use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder , MultiSpan } ;
66use rustc_hir as hir;
77use rustc_hir:: def_id:: { DefId , LocalDefId } ;
8+ use rustc_hir:: intravisit:: Map ;
89use rustc_middle:: ty:: print:: with_no_trimmed_paths;
910use rustc_middle:: ty:: { self , TyCtxt } ;
1011use rustc_span:: Span ;
@@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
4243pub fn report_object_safety_error < ' tcx > (
4344 tcx : TyCtxt < ' tcx > ,
4445 span : Span ,
46+ hir_id : Option < hir:: HirId > ,
4547 trait_def_id : DefId ,
4648 violations : & [ ObjectSafetyViolation ] ,
4749) -> DiagnosticBuilder < ' tcx > {
@@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>(
5961 ) ;
6062 err. span_label ( span, format ! ( "`{trait_str}` cannot be made into an object" ) ) ;
6163
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+ }
6282 let mut reported_violations = FxIndexSet :: default ( ) ;
6383 let mut multi_span = vec ! [ ] ;
6484 let mut messages = vec ! [ ] ;
0 commit comments