@@ -36,6 +36,7 @@ use rustc_span::def_id::DefIdSet;
3636use rustc_span:: symbol:: { kw, sym, Ident } ;
3737use rustc_span:: Symbol ;
3838use rustc_span:: { edit_distance, source_map, ExpnKind , FileName , MacroKind , Span } ;
39+ use rustc_trait_selection:: infer:: InferCtxtExt ;
3940use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: OnUnimplementedNote ;
4041use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: TypeErrCtxtExt as _;
4142use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -193,7 +194,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193194 . span_if_local ( def_id)
194195 . unwrap_or_else ( || self . tcx . def_span ( def_id) ) ;
195196 err. span_label ( sp, format ! ( "private {kind} defined here" ) ) ;
196- self . suggest_valid_traits ( & mut err, out_of_scope_traits) ;
197+ self . suggest_valid_traits ( & mut err, out_of_scope_traits, true ) ;
197198 err. emit ( ) ;
198199 }
199200
@@ -2450,6 +2451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24502451 & self ,
24512452 err : & mut Diagnostic ,
24522453 valid_out_of_scope_traits : Vec < DefId > ,
2454+ explain : bool ,
24532455 ) -> bool {
24542456 if !valid_out_of_scope_traits. is_empty ( ) {
24552457 let mut candidates = valid_out_of_scope_traits;
@@ -2462,7 +2464,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24622464 . find ( |did| self . tcx . is_diagnostic_item ( sym:: TryInto , * * did) )
24632465 . copied ( ) ;
24642466
2465- err. help ( "items from traits can only be used if the trait is in scope" ) ;
2467+ if explain {
2468+ err. help ( "items from traits can only be used if the trait is in scope" ) ;
2469+ }
24662470 let msg = format ! (
24672471 "the following {traits_are} implemented but not in scope; \
24682472 perhaps add a `use` for {one_of_them}:",
@@ -2679,7 +2683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26792683 }
26802684 }
26812685 }
2682- if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
2686+ if self . suggest_valid_traits ( err, valid_out_of_scope_traits, true ) {
26832687 return ;
26842688 }
26852689
@@ -2959,26 +2963,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29592963 match & potential_candidates[ ..] {
29602964 [ ] => { }
29612965 [ trait_info] if trait_info. def_id . is_local ( ) => {
2962- err. subdiagnostic ( CandidateTraitNote {
2963- span : self . tcx . def_span ( trait_info. def_id ) ,
2964- trait_name : self . tcx . def_path_str ( trait_info. def_id ) ,
2965- item_name,
2966- action_or_ty : if trait_missing_method {
2967- "NONE" . to_string ( )
2968- } else {
2969- param_type. map_or_else (
2970- || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2971- ToString :: to_string,
2972- )
2973- } ,
2974- } ) ;
2966+ let args =
2967+ ty:: GenericArgs :: for_item ( self . tcx , trait_info. def_id , |param, _| {
2968+ if param. index == 0 {
2969+ rcvr_ty. into ( )
2970+ } else {
2971+ self . infcx . var_for_def ( span, param)
2972+ }
2973+ } ) ;
2974+ if self
2975+ . infcx
2976+ . type_implements_trait ( trait_info. def_id , args, self . param_env )
2977+ . must_apply_modulo_regions ( )
2978+ && param_type. is_none ( )
2979+ {
2980+ self . suggest_valid_traits ( err, vec ! [ trait_info. def_id] , false ) ;
2981+ } else {
2982+ err. subdiagnostic ( CandidateTraitNote {
2983+ span : self . tcx . def_span ( trait_info. def_id ) ,
2984+ trait_name : self . tcx . def_path_str ( trait_info. def_id ) ,
2985+ item_name,
2986+ action_or_ty : if trait_missing_method {
2987+ "NONE" . to_string ( )
2988+ } else {
2989+ param_type. map_or_else (
2990+ || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2991+ ToString :: to_string,
2992+ )
2993+ } ,
2994+ } ) ;
2995+ }
29752996 }
29762997 trait_infos => {
29772998 let mut msg = message ( param_type. map_or_else (
29782999 || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
29793000 |param| format ! ( "restrict type parameter `{param}` with" ) ,
29803001 ) ) ;
29813002 for ( i, trait_info) in trait_infos. iter ( ) . enumerate ( ) {
3003+ let args =
3004+ ty:: GenericArgs :: for_item ( self . tcx , trait_info. def_id , |param, _| {
3005+ if param. index == 0 {
3006+ rcvr_ty. into ( )
3007+ } else {
3008+ self . infcx . var_for_def ( span, param)
3009+ }
3010+ } ) ;
3011+ if self
3012+ . infcx
3013+ . type_implements_trait ( trait_info. def_id , args, self . param_env )
3014+ . must_apply_modulo_regions ( )
3015+ && param_type. is_none ( )
3016+ {
3017+ self . suggest_valid_traits ( err, vec ! [ trait_info. def_id] , false ) ;
3018+ }
29823019 msg. push_str ( & format ! (
29833020 "\n candidate #{}: `{}`" ,
29843021 i + 1 ,
0 commit comments