@@ -35,6 +35,7 @@ use rustc_span::def_id::DefIdSet;
3535use rustc_span:: symbol:: { kw, sym, Ident } ;
3636use rustc_span:: Symbol ;
3737use rustc_span:: { edit_distance, source_map, ExpnKind , FileName , MacroKind , Span } ;
38+ use rustc_trait_selection:: infer:: InferCtxtExt ;
3839use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: OnUnimplementedNote ;
3940use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: TypeErrCtxtExt as _;
4041use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -192,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
192193 . span_if_local ( def_id)
193194 . unwrap_or_else ( || self . tcx . def_span ( def_id) ) ;
194195 err. span_label ( sp, format ! ( "private {kind} defined here" ) ) ;
195- self . suggest_valid_traits ( & mut err, out_of_scope_traits) ;
196+ self . suggest_valid_traits ( & mut err, out_of_scope_traits, true ) ;
196197 err. emit ( ) ;
197198 }
198199
@@ -2464,6 +2465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24642465 & self ,
24652466 err : & mut Diagnostic ,
24662467 valid_out_of_scope_traits : Vec < DefId > ,
2468+ explain : bool ,
24672469 ) -> bool {
24682470 if !valid_out_of_scope_traits. is_empty ( ) {
24692471 let mut candidates = valid_out_of_scope_traits;
@@ -2476,7 +2478,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24762478 . find ( |did| self . tcx . is_diagnostic_item ( sym:: TryInto , * * did) )
24772479 . copied ( ) ;
24782480
2479- err. help ( "items from traits can only be used if the trait is in scope" ) ;
2481+ if explain {
2482+ err. help ( "items from traits can only be used if the trait is in scope" ) ;
2483+ }
24802484 let msg = format ! (
24812485 "the following {traits_are} implemented but not in scope; \
24822486 perhaps add a `use` for {one_of_them}:",
@@ -2693,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26932697 }
26942698 }
26952699 }
2696- if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
2700+ if self . suggest_valid_traits ( err, valid_out_of_scope_traits, true ) {
26972701 return ;
26982702 }
26992703
@@ -2970,29 +2974,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29702974 ( candidates, Vec :: new ( ) )
29712975 } ;
29722976
2977+ let impls_trait = |def_id : DefId | {
2978+ let args = ty:: GenericArgs :: for_item ( self . tcx , def_id, |param, _| {
2979+ if param. index == 0 {
2980+ rcvr_ty. into ( )
2981+ } else {
2982+ self . infcx . var_for_def ( span, param)
2983+ }
2984+ } ) ;
2985+ self . infcx
2986+ . type_implements_trait ( def_id, args, self . param_env )
2987+ . must_apply_modulo_regions ( )
2988+ && param_type. is_none ( )
2989+ } ;
29732990 match & potential_candidates[ ..] {
29742991 [ ] => { }
29752992 [ trait_info] if trait_info. def_id . is_local ( ) => {
2976- err. subdiagnostic ( CandidateTraitNote {
2977- span : self . tcx . def_span ( trait_info. def_id ) ,
2978- trait_name : self . tcx . def_path_str ( trait_info. def_id ) ,
2979- item_name,
2980- action_or_ty : if trait_missing_method {
2981- "NONE" . to_string ( )
2982- } else {
2983- param_type. map_or_else (
2984- || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2985- ToString :: to_string,
2986- )
2987- } ,
2988- } ) ;
2993+ if impls_trait ( trait_info. def_id ) {
2994+ self . suggest_valid_traits ( err, vec ! [ trait_info. def_id] , false ) ;
2995+ } else {
2996+ err. subdiagnostic ( CandidateTraitNote {
2997+ span : self . tcx . def_span ( trait_info. def_id ) ,
2998+ trait_name : self . tcx . def_path_str ( trait_info. def_id ) ,
2999+ item_name,
3000+ action_or_ty : if trait_missing_method {
3001+ "NONE" . to_string ( )
3002+ } else {
3003+ param_type. map_or_else (
3004+ || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
3005+ ToString :: to_string,
3006+ )
3007+ } ,
3008+ } ) ;
3009+ }
29893010 }
29903011 trait_infos => {
29913012 let mut msg = message ( param_type. map_or_else (
29923013 || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
29933014 |param| format ! ( "restrict type parameter `{param}` with" ) ,
29943015 ) ) ;
29953016 for ( i, trait_info) in trait_infos. iter ( ) . enumerate ( ) {
3017+ if impls_trait ( trait_info. def_id ) {
3018+ self . suggest_valid_traits ( err, vec ! [ trait_info. def_id] , false ) ;
3019+ }
29963020 msg. push_str ( & format ! (
29973021 "\n candidate #{}: `{}`" ,
29983022 i + 1 ,
0 commit comments