22//! found or is otherwise invalid.
33
44use crate :: errors;
5+ use crate :: errors:: CandidateTraitNote ;
6+ use crate :: errors:: NoAssociatedItem ;
57use crate :: Expectation ;
68use crate :: FnCtxt ;
79use rustc_ast:: ast:: Mutability ;
@@ -38,6 +40,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
3840use rustc_trait_selection:: traits:: {
3941 FulfillmentError , Obligation , ObligationCause , ObligationCauseCode ,
4042} ;
43+ use std:: borrow:: Cow ;
4144
4245use super :: probe:: { AutorefOrPtrAdjustment , IsSuggestion , Mode , ProbeScope } ;
4346use super :: { CandidateSource , MethodError , NoMatchData } ;
@@ -112,6 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
112115 error : MethodError < ' tcx > ,
113116 args : Option < ( & ' tcx hir:: Expr < ' tcx > , & ' tcx [ hir:: Expr < ' tcx > ] ) > ,
114117 expected : Expectation < ' tcx > ,
118+ trait_missing_method : bool ,
115119 ) -> Option < DiagnosticBuilder < ' _ , ErrorGuaranteed > > {
116120 // Avoid suggestions when we don't know what's going on.
117121 if rcvr_ty. references_error ( ) {
@@ -136,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
136140 sugg_span,
137141 & mut no_match_data,
138142 expected,
143+ trait_missing_method,
139144 ) ;
140145 }
141146
@@ -278,6 +283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
278283 sugg_span : Span ,
279284 no_match_data : & mut NoMatchData < ' tcx > ,
280285 expected : Expectation < ' tcx > ,
286+ trait_missing_method : bool ,
281287 ) -> Option < DiagnosticBuilder < ' _ , ErrorGuaranteed > > {
282288 let mode = no_match_data. mode ;
283289 let tcx = self . tcx ;
@@ -323,7 +329,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323329 span = item_name. span ;
324330
325331 // Don't show generic arguments when the method can't be found in any implementation (#81576).
326- let mut ty_str_reported = ty_str. clone ( ) ;
332+ let mut ty_str_reported = if trait_missing_method {
333+ ty_str. strip_prefix ( "dyn " ) . expect ( "Failed to remove the prefix dyn" ) . to_owned ( )
334+ } else {
335+ ty_str. clone ( )
336+ } ;
337+
327338 if let ty:: Adt ( _, generics) = rcvr_ty. kind ( ) {
328339 if generics. len ( ) > 0 {
329340 let mut autoderef = self . autoderef ( span, rcvr_ty) ;
@@ -355,25 +366,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
355366 {
356367 self . suggest_missing_writer ( rcvr_ty, args)
357368 } else {
358- struct_span_err ! (
359- tcx. sess,
369+ tcx. sess . create_err ( NoAssociatedItem {
360370 span,
361- E0599 ,
362- "no {} named `{}` found for {} `{}` in the current scope" ,
363371 item_kind,
364372 item_name,
365- rcvr_ty. prefix_string( self . tcx) ,
366- ty_str_reported,
367- )
373+ ty_prefix : if trait_missing_method {
374+ // FIXME(mu001999) E0599 maybe not suitable here because it is for types
375+ Cow :: from ( "trait" )
376+ } else {
377+ rcvr_ty. prefix_string ( self . tcx )
378+ } ,
379+ ty_str : ty_str_reported,
380+ trait_missing_method,
381+ } )
368382 } ;
369383 if tcx. sess . source_map ( ) . is_multiline ( sugg_span) {
370384 err. span_label ( sugg_span. with_hi ( span. lo ( ) ) , "" ) ;
371385 }
372- let ty_str = if short_ty_str. len ( ) < ty_str. len ( ) && ty_str. len ( ) > 10 {
386+ let mut ty_str = if short_ty_str. len ( ) < ty_str. len ( ) && ty_str. len ( ) > 10 {
373387 short_ty_str
374388 } else {
375389 ty_str
376390 } ;
391+ if trait_missing_method {
392+ ty_str =
393+ ty_str. strip_prefix ( "dyn " ) . expect ( "Failed to remove the prefix dyn" ) . to_owned ( ) ;
394+ }
395+
377396 if let Some ( file) = ty_file {
378397 err. note ( format ! ( "the full type name has been written to '{}'" , file. display( ) , ) ) ;
379398 }
@@ -1067,6 +1086,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10671086 & static_candidates,
10681087 unsatisfied_bounds,
10691088 expected. only_has_type ( self ) ,
1089+ trait_missing_method,
10701090 ) ;
10711091 }
10721092
@@ -2375,6 +2395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23752395 static_candidates : & [ CandidateSource ] ,
23762396 unsatisfied_bounds : bool ,
23772397 return_type : Option < Ty < ' tcx > > ,
2398+ trait_missing_method : bool ,
23782399 ) {
23792400 let mut alt_rcvr_sugg = false ;
23802401 if let ( SelfSource :: MethodCall ( rcvr) , false ) = ( source, unsatisfied_bounds) {
@@ -2598,11 +2619,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25982619 } ,
25992620 _ => None ,
26002621 } ;
2601- err. help ( if param_type. is_some ( ) {
2602- "items from traits can only be used if the type parameter is bounded by the trait"
2603- } else {
2604- "items from traits can only be used if the trait is implemented and in scope"
2605- } ) ;
2622+ if !trait_missing_method {
2623+ err. help ( if param_type. is_some ( ) {
2624+ "items from traits can only be used if the type parameter is bounded by the trait"
2625+ } else {
2626+ "items from traits can only be used if the trait is implemented and in scope"
2627+ } ) ;
2628+ }
2629+
26062630 let candidates_len = candidates. len ( ) ;
26072631 let message = |action| {
26082632 format ! (
@@ -2751,27 +2775,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27512775 ( candidates, Vec :: new ( ) )
27522776 } ;
27532777
2754- let action = if let Some ( param) = param_type {
2755- format ! ( "restrict type parameter `{}` with" , param)
2756- } else {
2757- // FIXME: it might only need to be imported into scope, not implemented.
2758- "implement" . to_string ( )
2759- } ;
27602778 match & potential_candidates[ ..] {
27612779 [ ] => { }
27622780 [ trait_info] if trait_info. def_id . is_local ( ) => {
2763- err. span_note (
2764- self . tcx . def_span ( trait_info. def_id ) ,
2765- format ! (
2766- "`{}` defines an item `{}`, perhaps you need to {} it" ,
2767- self . tcx. def_path_str( trait_info. def_id) ,
2768- item_name,
2769- action
2770- ) ,
2771- ) ;
2781+ err. subdiagnostic ( CandidateTraitNote {
2782+ span : self . tcx . def_span ( trait_info. def_id ) ,
2783+ trait_name : self . tcx . def_path_str ( trait_info. def_id ) ,
2784+ item_name,
2785+ action_or_ty : if trait_missing_method {
2786+ "NONE" . to_string ( )
2787+ } else {
2788+ param_type. map_or_else (
2789+ || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2790+ ToString :: to_string,
2791+ )
2792+ } ,
2793+ } ) ;
27722794 }
27732795 trait_infos => {
2774- let mut msg = message ( action) ;
2796+ let mut msg = message ( param_type. map_or_else (
2797+ || "implement" . to_string ( ) , // FIXME: it might only need to be imported into scope, not implemented.
2798+ |param| format ! ( "restrict type parameter `{}` with" , param) ,
2799+ ) ) ;
27752800 for ( i, trait_info) in trait_infos. iter ( ) . enumerate ( ) {
27762801 msg. push_str ( & format ! (
27772802 "\n candidate #{}: `{}`" ,
0 commit comments