@@ -374,6 +374,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
374
374
} )
375
375
}
376
376
}
377
+
377
378
impl < ' tcx > TypeErrCtxtExt < ' tcx > for TypeErrCtxt < ' _ , ' tcx > {
378
379
fn report_fulfillment_errors (
379
380
& self ,
@@ -852,6 +853,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
852
853
let mut suggested =
853
854
self . suggest_dereferences ( & obligation, & mut err, trait_predicate) ;
854
855
suggested |= self . suggest_fn_call ( & obligation, & mut err, trait_predicate) ;
856
+ let impl_candidates = self . find_similar_impl_candidates ( trait_predicate) ;
857
+ suggested = if let & [ cand] = & impl_candidates[ ..] {
858
+ let cand = cand. trait_ref ;
859
+ if let ( ty:: FnPtr ( _) , ty:: FnDef ( ..) ) =
860
+ ( cand. self_ty ( ) . kind ( ) , trait_ref. self_ty ( ) . skip_binder ( ) . kind ( ) )
861
+ {
862
+ err. span_suggestion (
863
+ span. shrink_to_hi ( ) ,
864
+ format ! (
865
+ "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`" ,
866
+ cand. print_only_trait_path( ) ,
867
+ cand. self_ty( ) ,
868
+ ) ,
869
+ format ! ( " as {}" , cand. self_ty( ) ) ,
870
+ Applicability :: MaybeIncorrect ,
871
+ ) ;
872
+ true
873
+ } else {
874
+ false
875
+ }
876
+ } else {
877
+ false
878
+ } || suggested;
855
879
suggested |=
856
880
self . suggest_remove_reference ( & obligation, & mut err, trait_predicate) ;
857
881
suggested |= self . suggest_semicolon_removal (
@@ -1968,27 +1992,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1968
1992
candidates. sort ( ) ;
1969
1993
candidates. dedup ( ) ;
1970
1994
let len = candidates. len ( ) ;
1971
- if candidates. len ( ) == 0 {
1995
+ if candidates. is_empty ( ) {
1972
1996
return false ;
1973
1997
}
1974
- if candidates . len ( ) == 1 {
1975
- let ty_desc = match candidates [ 0 ] . self_ty ( ) . kind ( ) {
1976
- ty :: FnPtr ( _ ) => Some ( "fn pointer" ) ,
1977
- _ => None ,
1978
- } ;
1979
- let the_desc = match ty_desc {
1980
- Some ( desc ) => format ! ( " implemented for {} `" , desc ) ,
1981
- None => " implemented for `" . to_string ( ) ,
1982
- } ;
1998
+ if let & [ cand ] = & candidates [ .. ] {
1999
+ let ( desc , mention_castable ) =
2000
+ match ( cand . self_ty ( ) . kind ( ) , trait_ref . self_ty ( ) . skip_binder ( ) . kind ( ) ) {
2001
+ ( ty :: FnPtr ( _ ) , ty :: FnDef ( .. ) ) => {
2002
+ ( " implemented for fn pointer `" , ", cast using `as`" )
2003
+ }
2004
+ ( ty :: FnPtr ( _ ) , _ ) => ( " implemented for fn pointer `" , "" ) ,
2005
+ _ => ( " implemented for `" , "" ) ,
2006
+ } ;
1983
2007
err. highlighted_help ( vec ! [
1984
- (
1985
- format!( "the trait `{}` " , candidates[ 0 ] . print_only_trait_path( ) ) ,
1986
- Style :: NoStyle ,
1987
- ) ,
2008
+ ( format!( "the trait `{}` " , cand. print_only_trait_path( ) ) , Style :: NoStyle ) ,
1988
2009
( "is" . to_string( ) , Style :: Highlight ) ,
1989
- ( the_desc , Style :: NoStyle ) ,
1990
- ( candidates [ 0 ] . self_ty( ) . to_string( ) , Style :: Highlight ) ,
2010
+ ( desc . to_string ( ) , Style :: NoStyle ) ,
2011
+ ( cand . self_ty( ) . to_string( ) , Style :: Highlight ) ,
1991
2012
( "`" . to_string( ) , Style :: NoStyle ) ,
2013
+ ( mention_castable. to_string( ) , Style :: NoStyle ) ,
1992
2014
] ) ;
1993
2015
return true ;
1994
2016
}
0 commit comments