@@ -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,48 +2988,48 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
29862988 Some ( r)
29872989 }
29882990
2989- /// make sure that we are in the condition to suggest the blanket implementation, if we are in the
2990- /// case of suggest it, use the function `err_reporter` to report the error or suggestion.
2991+ /// Make sure that we are in the condition to suggest the blanket implementation.
29912992 fn maybe_lint_blanket_trait_impl < T : rustc_errors:: EmissionGuarantee > (
29922993 & self ,
29932994 self_ty : & hir:: Ty < ' _ > ,
2994- diagnostic : & mut DiagnosticBuilder < ' _ , T > ,
2995+ diag : & mut DiagnosticBuilder < ' _ , T > ,
29952996 ) {
29962997 let tcx = self . tcx ( ) ;
29972998 let parent_id = tcx. hir ( ) . get_parent_item ( self_ty. hir_id ) ;
29982999 if let hir:: Node :: Item ( hir:: Item {
29993000 kind :
30003001 hir:: ItemKind :: Impl ( hir:: Impl {
3001- self_ty : impl_self_typ , of_trait : Some ( trait_ref ) , generics, ..
3002+ self_ty : impl_self_ty , of_trait : Some ( of_trait_ref ) , generics, ..
30023003 } ) ,
30033004 ..
3004- } ) = tcx. hir ( ) . get_by_def_id ( parent_id) && self_ty. hir_id == impl_self_typ . hir_id
3005+ } ) = tcx. hir ( ) . get_by_def_id ( parent_id) && self_ty. hir_id == impl_self_ty . hir_id
30053006 {
3006- let trait_span = trait_ref. path . span ;
3007- let target_span = if let Some ( span) = generics. span_for_param_suggestion ( ) {
3008- span
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+ let param_name = generics. params . next_type_param_name ( Some ( & impl_trait_name) ) ;
3019+ ( span, format ! ( ", {}: {}" , param_name, impl_trait_name) )
30093020 } else {
3010- trait_span
3021+ ( generics . span , format ! ( "<{}: {}>" , param_name , impl_trait_name ) )
30113022 } ;
3012- let is_local = trait_ref. trait_def_id ( ) . map_or ( false , |def_id| def_id. is_local ( ) ) ;
3013- if is_local {
3014- let trait_name = tcx. sess . source_map ( ) . span_to_snippet ( trait_span) . unwrap ( ) ;
3015- let self_name = tcx. sess . source_map ( ) . span_to_snippet ( self_ty. span ) . unwrap ( ) ;
3016- let blanket_msg = format ! (
3017- "use a blanket implementation to implement {} for all types that also implement {}" ,
3018- trait_name, self_name
3019- ) ;
3020- let blanket_sugg = vec ! [
3021- ( target_span, "<T: " . to_owned( ) ) ,
3022- ( trait_span. shrink_to_hi( ) , format!( "{}>" , self_name) ) ,
3023- ( self_ty. span, "T" . to_owned( ) ) ,
3024- ] ;
3025- diagnostic. multipart_suggestion (
3026- blanket_msg,
3027- blanket_sugg,
3028- Applicability :: Unspecified ,
3029- ) ;
3030- }
3023+ diag. multipart_suggestion (
3024+ format ! ( "alternatively use a blanket \
3025+ implementation to implement `{of_trait_name}` for \
3026+ all types that also implement `{impl_trait_name}`") ,
3027+ vec ! [
3028+ ( self_ty. span, param_name) ,
3029+ add_generic_sugg,
3030+ ] ,
3031+ Applicability :: MaybeIncorrect ,
3032+ ) ;
30313033 }
30323034 }
30333035
@@ -3045,6 +3047,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
30453047 . map_or ( false , |s| s. trim_end ( ) . ends_with ( '<' ) ) ;
30463048
30473049 let is_global = poly_trait_ref. trait_ref . path . is_global ( ) ;
3050+ let is_local = if let Some ( def_id) = poly_trait_ref. trait_ref . trait_def_id ( ) {
3051+ def_id. is_local ( )
3052+ } else {
3053+ false
3054+ } ;
30483055 let sugg = Vec :: from_iter ( [
30493056 (
30503057 self_ty. span . shrink_to_lo ( ) ,
@@ -3069,7 +3076,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
30693076 let mut diag =
30703077 rustc_errors:: struct_span_err!( tcx. sess, self_ty. span, E0782 , "{}" , msg) ;
30713078 diag. multipart_suggestion_verbose ( label, sugg, Applicability :: MachineApplicable ) ;
3072- self . maybe_lint_blanket_trait_impl ( & self_ty, & mut diag) ;
3079+ // check if the impl trait that we are considering is a impl of a local trait
3080+ if is_local {
3081+ self . maybe_lint_blanket_trait_impl ( & self_ty, & mut diag) ;
3082+ }
30733083 diag. emit ( ) ;
30743084 } else {
30753085 let msg = "trait objects without an explicit `dyn` are deprecated" ;
@@ -3084,7 +3094,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
30843094 sugg,
30853095 Applicability :: MachineApplicable ,
30863096 ) ;
3087- self . maybe_lint_blanket_trait_impl :: < ( ) > ( & self_ty, & mut diag) ;
3097+ // check if the impl trait that we are considering is a impl of a local trait
3098+ if is_local {
3099+ self . maybe_lint_blanket_trait_impl :: < ( ) > ( & self_ty, & mut diag) ;
3100+ }
30883101 diag. emit ( ) ;
30893102 } ,
30903103 ) ;
0 commit comments