@@ -38,7 +38,9 @@ use rustc_span::{Span, DUMMY_SP};
38
38
use rustc_target:: spec:: abi;
39
39
use rustc_trait_selection:: traits;
40
40
use 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
+ } ;
42
44
use rustc_trait_selection:: traits:: wf:: object_region_bounds;
43
45
44
46
use smallvec:: SmallVec ;
@@ -2986,6 +2988,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2986
2988
Some ( r)
2987
2989
}
2988
2990
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
+
2989
3035
fn maybe_lint_bare_trait ( & self , self_ty : & hir:: Ty < ' _ > , in_path : bool ) {
2990
3036
let tcx = self . tcx ( ) ;
2991
3037
if let hir:: TyKind :: TraitObject ( [ poly_trait_ref, ..] , _, TraitObjectSyntax :: None ) =
@@ -3021,23 +3067,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3021
3067
if self_ty. span . edition ( ) >= Edition :: Edition2021 {
3022
3068
let msg = "trait objects must include the `dyn` keyword" ;
3023
3069
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 ( ) ;
3027
3076
} else {
3028
3077
let msg = "trait objects without an explicit `dyn` are deprecated" ;
3029
3078
tcx. struct_span_lint_hir (
3030
3079
BARE_TRAIT_OBJECTS ,
3031
3080
self_ty. hir_id ,
3032
3081
self_ty. span ,
3033
3082
|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 ( ) ;
3041
3091
} ,
3042
3092
) ;
3043
3093
}
0 commit comments