@@ -38,7 +38,9 @@ use rustc_span::{Span, DUMMY_SP};
3838use rustc_target:: spec:: abi;
3939use rustc_trait_selection:: traits;
4040use rustc_trait_selection:: traits:: astconv_object_safety_violations;
41- use rustc_trait_selection:: traits:: error_reporting:: report_object_safety_error;
41+ use rustc_trait_selection:: traits:: error_reporting:: {
42+ report_object_safety_error, suggestions:: NextTypeParamName ,
43+ } ;
4244use rustc_trait_selection:: traits:: wf:: object_region_bounds;
4345
4446use smallvec:: SmallVec ;
@@ -2986,6 +2988,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
29862988 Some ( r)
29872989 }
29882990
2991+ /// Make sure that we are in the condition to suggest the blanket implementation.
2992+ fn maybe_lint_blanket_trait_impl < T : rustc_errors:: EmissionGuarantee > (
2993+ & self ,
2994+ self_ty : & hir:: Ty < ' _ > ,
2995+ diag : & mut DiagnosticBuilder < ' _ , T > ,
2996+ ) {
2997+ let tcx = self . tcx ( ) ;
2998+ let parent_id = tcx. hir ( ) . get_parent_item ( self_ty. hir_id ) ;
2999+ if let hir:: Node :: Item ( hir:: Item {
3000+ kind :
3001+ hir:: ItemKind :: Impl ( hir:: Impl {
3002+ self_ty : impl_self_ty, of_trait : Some ( of_trait_ref) , generics, ..
3003+ } ) ,
3004+ ..
3005+ } ) = tcx. hir ( ) . get_by_def_id ( parent_id) && self_ty. hir_id == impl_self_ty. hir_id
3006+ {
3007+ if !of_trait_ref. trait_def_id ( ) . map_or ( false , |def_id| def_id. is_local ( ) ) {
3008+ return ;
3009+ }
3010+ let of_trait_span = of_trait_ref. path . span ;
3011+ // make sure that we are not calling unwrap to abort during the compilation
3012+ let Ok ( impl_trait_name) = tcx. sess . source_map ( ) . span_to_snippet ( self_ty. span ) else { return ; } ;
3013+ let Ok ( of_trait_name) = tcx. sess . source_map ( ) . span_to_snippet ( of_trait_span) else { return ; } ;
3014+ // check if the trait has generics, to make a correct suggestion
3015+ let param_name = generics. params . next_type_param_name ( None ) ;
3016+
3017+ let add_generic_sugg = if let Some ( span) = generics. span_for_param_suggestion ( ) {
3018+ ( span, format ! ( ", {}: {}" , param_name, impl_trait_name) )
3019+ } else {
3020+ ( generics. span , format ! ( "<{}: {}>" , param_name, impl_trait_name) )
3021+ } ;
3022+ diag. multipart_suggestion (
3023+ format ! ( "alternatively use a blanket \
3024+ implementation to implement `{of_trait_name}` for \
3025+ all types that also implement `{impl_trait_name}`") ,
3026+ vec ! [
3027+ ( self_ty. span, param_name) ,
3028+ add_generic_sugg,
3029+ ] ,
3030+ Applicability :: MaybeIncorrect ,
3031+ ) ;
3032+ }
3033+ }
3034+
29893035 fn maybe_lint_bare_trait ( & self , self_ty : & hir:: Ty < ' _ > , in_path : bool ) {
29903036 let tcx = self . tcx ( ) ;
29913037 if let hir:: TyKind :: TraitObject ( [ poly_trait_ref, ..] , _, TraitObjectSyntax :: None ) =
@@ -3021,23 +3067,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
30213067 if self_ty. span . edition ( ) >= Edition :: Edition2021 {
30223068 let msg = "trait objects must include the `dyn` keyword" ;
30233069 let label = "add `dyn` keyword before this trait" ;
3024- rustc_errors:: struct_span_err!( tcx. sess, self_ty. span, E0782 , "{}" , msg)
3025- . multipart_suggestion_verbose ( label, sugg, Applicability :: MachineApplicable )
3026- . emit ( ) ;
3070+ let mut diag =
3071+ rustc_errors:: struct_span_err!( tcx. sess, self_ty. span, E0782 , "{}" , msg) ;
3072+ diag. multipart_suggestion_verbose ( label, sugg, Applicability :: MachineApplicable ) ;
3073+ // check if the impl trait that we are considering is a impl of a local trait
3074+ self . maybe_lint_blanket_trait_impl ( & self_ty, & mut diag) ;
3075+ diag. emit ( ) ;
30273076 } else {
30283077 let msg = "trait objects without an explicit `dyn` are deprecated" ;
30293078 tcx. struct_span_lint_hir (
30303079 BARE_TRAIT_OBJECTS ,
30313080 self_ty. hir_id ,
30323081 self_ty. span ,
30333082 |lint| {
3034- lint. build ( msg)
3035- . multipart_suggestion_verbose (
3036- "use `dyn`" ,
3037- sugg,
3038- Applicability :: MachineApplicable ,
3039- )
3040- . emit ( ) ;
3083+ let mut diag = lint. build ( msg) ;
3084+ diag. multipart_suggestion_verbose (
3085+ "use `dyn`" ,
3086+ sugg,
3087+ Applicability :: MachineApplicable ,
3088+ ) ;
3089+ self . maybe_lint_blanket_trait_impl :: < ( ) > ( & self_ty, & mut diag) ;
3090+ diag. emit ( ) ;
30413091 } ,
30423092 ) ;
30433093 }
0 commit comments