@@ -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,48 +2988,48 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2986
2988
Some ( r)
2987
2989
}
2988
2990
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.
2991
2992
fn maybe_lint_blanket_trait_impl < T : rustc_errors:: EmissionGuarantee > (
2992
2993
& self ,
2993
2994
self_ty : & hir:: Ty < ' _ > ,
2994
- diagnostic : & mut DiagnosticBuilder < ' _ , T > ,
2995
+ diag : & mut DiagnosticBuilder < ' _ , T > ,
2995
2996
) {
2996
2997
let tcx = self . tcx ( ) ;
2997
2998
let parent_id = tcx. hir ( ) . get_parent_item ( self_ty. hir_id ) ;
2998
2999
if let hir:: Node :: Item ( hir:: Item {
2999
3000
kind :
3000
3001
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, ..
3002
3003
} ) ,
3003
3004
..
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
3005
3006
{
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) )
3009
3020
} else {
3010
- trait_span
3021
+ ( generics . span , format ! ( "<{}: {}>" , param_name , impl_trait_name ) )
3011
3022
} ;
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
+ ) ;
3031
3033
}
3032
3034
}
3033
3035
@@ -3045,6 +3047,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3045
3047
. map_or ( false , |s| s. trim_end ( ) . ends_with ( '<' ) ) ;
3046
3048
3047
3049
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
+ } ;
3048
3055
let sugg = Vec :: from_iter ( [
3049
3056
(
3050
3057
self_ty. span . shrink_to_lo ( ) ,
@@ -3069,7 +3076,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3069
3076
let mut diag =
3070
3077
rustc_errors:: struct_span_err!( tcx. sess, self_ty. span, E0782 , "{}" , msg) ;
3071
3078
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
+ }
3073
3083
diag. emit ( ) ;
3074
3084
} else {
3075
3085
let msg = "trait objects without an explicit `dyn` are deprecated" ;
@@ -3084,7 +3094,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3084
3094
sugg,
3085
3095
Applicability :: MachineApplicable ,
3086
3096
) ;
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
+ }
3088
3101
diag. emit ( ) ;
3089
3102
} ,
3090
3103
) ;
0 commit comments