@@ -2,6 +2,7 @@ use super::FnCtxt;
22use crate :: astconv:: AstConv ;
33use crate :: errors:: { AddReturnTypeSuggestion , ExpectedReturnTypeLabel } ;
44
5+ use hir:: def_id:: DefId ;
56use rustc_ast:: util:: parser:: ExprPrecedence ;
67use rustc_errors:: { Applicability , Diagnostic , MultiSpan } ;
78use rustc_hir as hir;
@@ -75,38 +76,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7576 found : Ty < ' tcx > ,
7677 can_satisfy : impl FnOnce ( Ty < ' tcx > ) -> bool ,
7778 ) -> bool {
79+ enum DefIdOrName {
80+ DefId ( DefId ) ,
81+ Name ( & ' static str ) ,
82+ }
7883 // Autoderef is useful here because sometimes we box callables, etc.
79- let Some ( ( def_id , output, inputs) ) = self . autoderef ( expr. span , found) . silence_errors ( ) . find_map ( |( found, _) | {
84+ let Some ( ( def_id_or_name , output, inputs) ) = self . autoderef ( expr. span , found) . silence_errors ( ) . find_map ( |( found, _) | {
8085 match * found. kind ( ) {
81- ty:: FnPtr ( fn_sig) => Some ( ( None , fn_sig. output ( ) , fn_sig. inputs ( ) . skip_binder ( ) . len ( ) ) ) ,
86+ ty:: FnPtr ( fn_sig) =>
87+ Some ( ( DefIdOrName :: Name ( "function pointer" ) , fn_sig. output ( ) , fn_sig. inputs ( ) . skip_binder ( ) . len ( ) ) ) ,
8288 ty:: FnDef ( def_id, _) => {
8389 let fn_sig = found. fn_sig ( self . tcx ) ;
84- Some ( ( Some ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) . skip_binder ( ) . len ( ) ) )
90+ Some ( ( DefIdOrName :: DefId ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) . skip_binder ( ) . len ( ) ) )
8591 }
8692 ty:: Closure ( def_id, substs) => {
8793 let fn_sig = substs. as_closure ( ) . sig ( ) ;
88- Some ( ( Some ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) . skip_binder ( ) . len ( ) - 1 ) )
94+ Some ( ( DefIdOrName :: DefId ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) . skip_binder ( ) . len ( ) - 1 ) )
8995 }
9096 ty:: Opaque ( def_id, substs) => {
91- let sig = self . tcx . bound_item_bounds ( def_id) . subst ( self . tcx , substs) . iter ( ) . find_map ( |pred| {
97+ self . tcx . bound_item_bounds ( def_id) . subst ( self . tcx , substs) . iter ( ) . find_map ( |pred| {
9298 if let ty:: PredicateKind :: Projection ( proj) = pred. kind ( ) . skip_binder ( )
9399 && Some ( proj. projection_ty . item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
94100 // args tuple will always be substs[1]
95101 && let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
96102 {
97103 Some ( (
104+ DefIdOrName :: DefId ( def_id) ,
98105 pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
99106 args. len ( ) ,
100107 ) )
101108 } else {
102109 None
103110 }
104- } ) ;
105- if let Some ( ( output, inputs) ) = sig {
106- Some ( ( Some ( def_id) , output, inputs) )
107- } else {
108- None
109- }
111+ } )
112+ }
113+ ty:: Dynamic ( data, _) => {
114+ data. iter ( ) . find_map ( |pred| {
115+ if let ty:: ExistentialPredicate :: Projection ( proj) = pred. skip_binder ( )
116+ && Some ( proj. item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
117+ // for existential projection, substs are shifted over by 1
118+ && let ty:: Tuple ( args) = proj. substs . type_at ( 0 ) . kind ( )
119+ {
120+ Some ( (
121+ DefIdOrName :: Name ( "trait object" ) ,
122+ pred. rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
123+ args. len ( ) ,
124+ ) )
125+ } else {
126+ None
127+ }
128+ } )
129+ }
130+ ty:: Param ( param) => {
131+ let def_id = self . tcx . generics_of ( self . body_id . owner ) . type_param ( & param, self . tcx ) . def_id ;
132+ self . tcx . predicates_of ( self . body_id . owner ) . predicates . iter ( ) . find_map ( |( pred, _) | {
133+ if let ty:: PredicateKind :: Projection ( proj) = pred. kind ( ) . skip_binder ( )
134+ && Some ( proj. projection_ty . item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
135+ && proj. projection_ty . self_ty ( ) == found
136+ // args tuple will always be substs[1]
137+ && let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
138+ {
139+ Some ( (
140+ DefIdOrName :: DefId ( def_id) ,
141+ pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
142+ args. len ( ) ,
143+ ) )
144+ } else {
145+ None
146+ }
147+ } )
110148 }
111149 _ => None ,
112150 }
@@ -128,12 +166,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
128166 _ => ( "..." . to_string ( ) , Applicability :: HasPlaceholders ) ,
129167 } ;
130168
131- let msg = match def_id. map ( |def_id| self . tcx . def_kind ( def_id) ) {
132- Some ( DefKind :: Fn ) => "call this function" ,
133- Some ( DefKind :: Closure | DefKind :: OpaqueTy ) => "call this closure" ,
134- Some ( DefKind :: Ctor ( CtorOf :: Struct , _) ) => "instantiate this tuple struct" ,
135- Some ( DefKind :: Ctor ( CtorOf :: Variant , _) ) => "instantiate this tuple variant" ,
136- _ => "call this function" ,
169+ let msg = match def_id_or_name {
170+ DefIdOrName :: DefId ( def_id) => match self . tcx . def_kind ( def_id) {
171+ DefKind :: Ctor ( CtorOf :: Struct , _) => "instantiate this tuple struct" . to_string ( ) ,
172+ DefKind :: Ctor ( CtorOf :: Variant , _) => {
173+ "instantiate this tuple variant" . to_string ( )
174+ }
175+ kind => format ! ( "call this {}" , kind. descr( def_id) ) ,
176+ } ,
177+ DefIdOrName :: Name ( name) => format ! ( "call this {name}" ) ,
137178 } ;
138179
139180 let sugg = match expr. kind {
0 commit comments