@@ -2,6 +2,7 @@ use super::FnCtxt;
2
2
use crate :: astconv:: AstConv ;
3
3
use crate :: errors:: { AddReturnTypeSuggestion , ExpectedReturnTypeLabel } ;
4
4
5
+ use hir:: def_id:: DefId ;
5
6
use rustc_ast:: util:: parser:: ExprPrecedence ;
6
7
use rustc_errors:: { Applicability , Diagnostic , MultiSpan } ;
7
8
use rustc_hir as hir;
@@ -75,38 +76,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
75
76
found : Ty < ' tcx > ,
76
77
can_satisfy : impl FnOnce ( Ty < ' tcx > ) -> bool ,
77
78
) -> bool {
79
+ enum DefIdOrName {
80
+ DefId ( DefId ) ,
81
+ Name ( & ' static str ) ,
82
+ }
78
83
// 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, _) | {
80
85
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 ( ) ) ) ,
82
88
ty:: FnDef ( def_id, _) => {
83
89
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 ( ) ) )
85
91
}
86
92
ty:: Closure ( def_id, substs) => {
87
93
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 ) )
89
95
}
90
96
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| {
92
98
if let ty:: PredicateKind :: Projection ( proj) = pred. kind ( ) . skip_binder ( )
93
99
&& Some ( proj. projection_ty . item_def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
94
100
// args tuple will always be substs[1]
95
101
&& let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
96
102
{
97
103
Some ( (
104
+ DefIdOrName :: DefId ( def_id) ,
98
105
pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
99
106
args. len ( ) ,
100
107
) )
101
108
} else {
102
109
None
103
110
}
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
+ } )
110
148
}
111
149
_ => None ,
112
150
}
@@ -128,12 +166,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
128
166
_ => ( "..." . to_string ( ) , Applicability :: HasPlaceholders ) ,
129
167
} ;
130
168
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}" ) ,
137
178
} ;
138
179
139
180
let sugg = match expr. kind {
0 commit comments