@@ -35,6 +35,7 @@ use rustc_span::def_id::DefIdSet;
35
35
use rustc_span:: symbol:: { kw, sym, Ident } ;
36
36
use rustc_span:: Symbol ;
37
37
use rustc_span:: { edit_distance, source_map, ExpnKind , FileName , MacroKind , Span } ;
38
+ use rustc_trait_selection:: infer:: InferCtxtExt ;
38
39
use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: OnUnimplementedNote ;
39
40
use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: TypeErrCtxtExt as _;
40
41
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -192,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
192
193
. span_if_local ( def_id)
193
194
. unwrap_or_else ( || self . tcx . def_span ( def_id) ) ;
194
195
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 ) ;
196
197
err. emit ( ) ;
197
198
}
198
199
@@ -2464,6 +2465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2464
2465
& self ,
2465
2466
err : & mut Diagnostic ,
2466
2467
valid_out_of_scope_traits : Vec < DefId > ,
2468
+ explain : bool ,
2467
2469
) -> bool {
2468
2470
if !valid_out_of_scope_traits. is_empty ( ) {
2469
2471
let mut candidates = valid_out_of_scope_traits;
@@ -2476,7 +2478,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2476
2478
. find ( |did| self . tcx . is_diagnostic_item ( sym:: TryInto , * * did) )
2477
2479
. copied ( ) ;
2478
2480
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
+ }
2480
2484
let msg = format ! (
2481
2485
"the following {traits_are} implemented but not in scope; \
2482
2486
perhaps add a `use` for {one_of_them}:",
@@ -2693,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2693
2697
}
2694
2698
}
2695
2699
}
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 ) {
2697
2701
return ;
2698
2702
}
2699
2703
@@ -2970,29 +2974,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2970
2974
( candidates, Vec :: new ( ) )
2971
2975
} ;
2972
2976
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
+ } ;
2973
2990
match & potential_candidates[ ..] {
2974
2991
[ ] => { }
2975
2992
[ 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
+ }
2989
3010
}
2990
3011
trait_infos => {
2991
3012
let mut msg = message ( param_type. map_or_else (
2992
3013
|| "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2993
3014
|param| format ! ( "restrict type parameter `{param}` with" ) ,
2994
3015
) ) ;
2995
3016
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
+ }
2996
3020
msg. push_str ( & format ! (
2997
3021
"\n candidate #{}: `{}`" ,
2998
3022
i + 1 ,
0 commit comments