@@ -36,6 +36,7 @@ use rustc_span::def_id::DefIdSet;
36
36
use rustc_span:: symbol:: { kw, sym, Ident } ;
37
37
use rustc_span:: Symbol ;
38
38
use rustc_span:: { edit_distance, source_map, ExpnKind , FileName , MacroKind , Span } ;
39
+ use rustc_trait_selection:: infer:: InferCtxtExt ;
39
40
use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: OnUnimplementedNote ;
40
41
use rustc_trait_selection:: traits:: error_reporting:: on_unimplemented:: TypeErrCtxtExt as _;
41
42
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -193,7 +194,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193
194
. span_if_local ( def_id)
194
195
. unwrap_or_else ( || self . tcx . def_span ( def_id) ) ;
195
196
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 ) ;
197
198
err. emit ( ) ;
198
199
}
199
200
@@ -2450,6 +2451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2450
2451
& self ,
2451
2452
err : & mut Diagnostic ,
2452
2453
valid_out_of_scope_traits : Vec < DefId > ,
2454
+ explain : bool ,
2453
2455
) -> bool {
2454
2456
if !valid_out_of_scope_traits. is_empty ( ) {
2455
2457
let mut candidates = valid_out_of_scope_traits;
@@ -2462,7 +2464,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2462
2464
. find ( |did| self . tcx . is_diagnostic_item ( sym:: TryInto , * * did) )
2463
2465
. copied ( ) ;
2464
2466
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
+ }
2466
2470
let msg = format ! (
2467
2471
"the following {traits_are} implemented but not in scope; \
2468
2472
perhaps add a `use` for {one_of_them}:",
@@ -2679,7 +2683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2679
2683
}
2680
2684
}
2681
2685
}
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 ) {
2683
2687
return ;
2684
2688
}
2685
2689
@@ -2959,26 +2963,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2959
2963
match & potential_candidates[ ..] {
2960
2964
[ ] => { }
2961
2965
[ 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
+ }
2975
2996
}
2976
2997
trait_infos => {
2977
2998
let mut msg = message ( param_type. map_or_else (
2978
2999
|| "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2979
3000
|param| format ! ( "restrict type parameter `{param}` with" ) ,
2980
3001
) ) ;
2981
3002
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
+ }
2982
3019
msg. push_str ( & format ! (
2983
3020
"\n candidate #{}: `{}`" ,
2984
3021
i + 1 ,
0 commit comments