@@ -222,6 +222,15 @@ pub trait TypeErrCtxtExt<'tcx> {
222
222
param_env : ty:: ParamEnv < ' tcx > ,
223
223
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
224
224
225
+ fn note_conflicting_fn_args (
226
+ & self ,
227
+ err : & mut Diagnostic ,
228
+ cause : & ObligationCauseCode < ' tcx > ,
229
+ expected : Ty < ' tcx > ,
230
+ found : Ty < ' tcx > ,
231
+ param_env : ty:: ParamEnv < ' tcx > ,
232
+ ) ;
233
+
225
234
fn note_conflicting_closure_bounds (
226
235
& self ,
227
236
cause : & ObligationCauseCode < ' tcx > ,
@@ -2006,6 +2015,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2006
2015
let signature_kind = format ! ( "{argument_kind} signature" ) ;
2007
2016
err. note_expected_found ( & signature_kind, expected_str, & signature_kind, found_str) ;
2008
2017
2018
+ self . note_conflicting_fn_args ( & mut err, cause, expected, found, param_env) ;
2009
2019
self . note_conflicting_closure_bounds ( cause, & mut err) ;
2010
2020
2011
2021
if let Some ( found_node) = found_node {
@@ -2015,17 +2025,168 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2015
2025
err
2016
2026
}
2017
2027
2028
+ fn note_conflicting_fn_args (
2029
+ & self ,
2030
+ err : & mut Diagnostic ,
2031
+ cause : & ObligationCauseCode < ' tcx > ,
2032
+ expected : Ty < ' tcx > ,
2033
+ found : Ty < ' tcx > ,
2034
+ param_env : ty:: ParamEnv < ' tcx > ,
2035
+ ) {
2036
+ let ObligationCauseCode :: FunctionArgumentObligation { arg_hir_id, .. } = cause else {
2037
+ return ;
2038
+ } ;
2039
+ let ty:: FnPtr ( expected) = expected. kind ( ) else {
2040
+ return ;
2041
+ } ;
2042
+ let ty:: FnPtr ( found) = found. kind ( ) else {
2043
+ return ;
2044
+ } ;
2045
+ let Some ( Node :: Expr ( arg) ) = self . tcx . hir ( ) . find ( * arg_hir_id) else {
2046
+ return ;
2047
+ } ;
2048
+ let hir:: ExprKind :: Path ( path) = arg. kind else {
2049
+ return ;
2050
+ } ;
2051
+ let expected_inputs = self . tcx . erase_late_bound_regions ( * expected) . inputs ( ) ;
2052
+ let found_inputs = self . tcx . erase_late_bound_regions ( * found) . inputs ( ) ;
2053
+ let both_tys = expected_inputs. iter ( ) . cloned ( ) . zip ( found_inputs. iter ( ) . cloned ( ) ) ;
2054
+
2055
+ let arg_expr = |infcx : & InferCtxt < ' tcx > , name, expected : Ty < ' tcx > , found : Ty < ' tcx > | {
2056
+ let ( expected_ty, expected_refs) = get_deref_type_and_refs ( expected) ;
2057
+ let ( found_ty, found_refs) = get_deref_type_and_refs ( found) ;
2058
+
2059
+ if infcx. can_eq ( param_env, found_ty, expected_ty) {
2060
+ if found_refs. len ( ) == expected_refs. len ( )
2061
+ && found_refs. iter ( ) . zip ( expected_refs. iter ( ) ) . all ( |( e, f) | e == f)
2062
+ {
2063
+ name
2064
+ } else if found_refs. len ( ) > expected_refs. len ( ) {
2065
+ if found_refs[ ..found_refs. len ( ) - expected_refs. len ( ) ]
2066
+ . iter ( )
2067
+ . zip ( expected_refs. iter ( ) )
2068
+ . any ( |( e, f) | e != f)
2069
+ {
2070
+ // The refs have different mutability.
2071
+ format ! (
2072
+ "{}*{name}" ,
2073
+ found_refs[ ..found_refs. len( ) - expected_refs. len( ) ]
2074
+ . iter( )
2075
+ . map( |mutbl| format!( "&{}" , mutbl. prefix_str( ) ) )
2076
+ . collect:: <Vec <_>>( )
2077
+ . join( "" ) ,
2078
+ )
2079
+ } else {
2080
+ format ! (
2081
+ "{}{name}" ,
2082
+ found_refs[ ..found_refs. len( ) - expected_refs. len( ) ]
2083
+ . iter( )
2084
+ . map( |mutbl| format!( "&{}" , mutbl. prefix_str( ) ) )
2085
+ . collect:: <Vec <_>>( )
2086
+ . join( "" ) ,
2087
+ )
2088
+ }
2089
+ } else if expected_refs. len ( ) > found_refs. len ( ) {
2090
+ format ! (
2091
+ "{}{name}" ,
2092
+ ( 0 ..( expected_refs. len( ) - found_refs. len( ) ) )
2093
+ . map( |_| "*" )
2094
+ . collect:: <Vec <_>>( )
2095
+ . join( "" ) ,
2096
+ )
2097
+ } else {
2098
+ format ! (
2099
+ "{}{name}" ,
2100
+ found_refs
2101
+ . iter( )
2102
+ . map( |mutbl| format!( "&{}" , mutbl. prefix_str( ) ) )
2103
+ . chain( found_refs. iter( ) . map( |_| "*" . to_string( ) ) )
2104
+ . collect:: <Vec <_>>( )
2105
+ . join( "" ) ,
2106
+ )
2107
+ }
2108
+ } else {
2109
+ format ! ( "/* {found} */" )
2110
+ }
2111
+ } ;
2112
+ let ( closure_names, call_names) : ( Vec < _ > , Vec < _ > ) = if both_tys
2113
+ . clone ( )
2114
+ . all ( |( expected, found) | {
2115
+ let ( expected_ty, _) = get_deref_type_and_refs ( expected) ;
2116
+ let ( found_ty, _) = get_deref_type_and_refs ( found) ;
2117
+ self . can_eq ( param_env, found_ty, expected_ty)
2118
+ } )
2119
+ && !expected_inputs. is_empty ( )
2120
+ && expected_inputs. len ( ) == found_inputs. len ( )
2121
+ && let hir:: QPath :: Resolved ( _, path) = path
2122
+ && let hir:: def:: Res :: Def ( _, fn_def_id) = path. res
2123
+ && let Some ( node) = self . tcx . hir ( ) . get_if_local ( fn_def_id)
2124
+ && let Some ( body_id) = node. body_id ( )
2125
+ {
2126
+ let closure = self
2127
+ . tcx
2128
+ . hir ( )
2129
+ . body_param_names ( body_id)
2130
+ . map ( |name| format ! ( "{name}" ) )
2131
+ . collect ( ) ;
2132
+ let args = self
2133
+ . tcx
2134
+ . hir ( )
2135
+ . body_param_names ( body_id)
2136
+ . zip ( both_tys)
2137
+ . map ( |( name, ( expected, found) ) | {
2138
+ arg_expr ( self . infcx , format ! ( "{name}" ) , expected, found)
2139
+ } )
2140
+ . collect ( ) ;
2141
+ ( closure, args)
2142
+ } else {
2143
+ let closure_args = expected_inputs
2144
+ . iter ( )
2145
+ . enumerate ( )
2146
+ . map ( |( i, _) | format ! ( "arg{i}" ) )
2147
+ . collect :: < Vec < _ > > ( ) ;
2148
+ let call_args = both_tys
2149
+ . enumerate ( )
2150
+ . map ( |( i, ( expected, found) ) | {
2151
+ arg_expr ( self . infcx , format ! ( "arg{i}" ) , expected, found)
2152
+ } )
2153
+ . collect :: < Vec < _ > > ( ) ;
2154
+ ( closure_args, call_args)
2155
+ } ;
2156
+ let closure_names: Vec < _ > = closure_names
2157
+ . into_iter ( )
2158
+ . zip ( expected_inputs. iter ( ) )
2159
+ . map ( |( name, ty) | {
2160
+ format ! (
2161
+ "{name}{}" ,
2162
+ if ty. has_infer_types( ) { String :: new( ) } else { format!( ": {ty}" ) }
2163
+ )
2164
+ } )
2165
+ . collect ( ) ;
2166
+ err. multipart_suggestion (
2167
+ format ! ( "consider wrapping the function in a closure" ) ,
2168
+ vec ! [
2169
+ ( arg. span. shrink_to_lo( ) , format!( "|{}| " , closure_names. join( ", " ) ) ) ,
2170
+ ( arg. span. shrink_to_hi( ) , format!( "({})" , call_names. join( ", " ) ) ) ,
2171
+ ] ,
2172
+ Applicability :: MaybeIncorrect ,
2173
+ ) ;
2174
+ }
2175
+
2018
2176
// Add a note if there are two `Fn`-family bounds that have conflicting argument
2019
2177
// requirements, which will always cause a closure to have a type error.
2020
2178
fn note_conflicting_closure_bounds (
2021
2179
& self ,
2022
2180
cause : & ObligationCauseCode < ' tcx > ,
2023
2181
err : & mut DiagnosticBuilder < ' tcx , ErrorGuaranteed > ,
2024
2182
) {
2183
+ // if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = cause {
2184
+ // cause = parent_code;
2185
+ // }
2025
2186
// First, look for an `ExprBindingObligation`, which means we can get
2026
2187
// the unsubstituted predicate list of the called function. And check
2027
2188
// that the predicate that we failed to satisfy is a `Fn`-like trait.
2028
- if let ObligationCauseCode :: ExprBindingObligation ( def_id, _, _ , idx) = cause
2189
+ if let ObligationCauseCode :: ExprBindingObligation ( def_id, _, hir_id , idx) = cause
2029
2190
&& let predicates = self . tcx . predicates_of ( def_id) . instantiate_identity ( self . tcx )
2030
2191
&& let Some ( pred) = predicates. predicates . get ( * idx)
2031
2192
&& let ty:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( )
@@ -2035,6 +2196,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2035
2196
self . tcx . anonymize_bound_vars ( pred. kind ( ) . rebind ( trait_pred. self_ty ( ) ) ) ;
2036
2197
let expected_args =
2037
2198
self . tcx . anonymize_bound_vars ( pred. kind ( ) . rebind ( trait_pred. trait_ref . args ) ) ;
2199
+ let node = self . tcx . hir ( ) . find ( * hir_id) ;
2200
+ info ! ( ?node) ;
2201
+ info ! ( ?pred) ;
2202
+ info ! ( ?trait_pred) ;
2203
+ info ! ( ?expected_self) ;
2204
+ info ! ( ?expected_args) ;
2038
2205
2039
2206
// Find another predicate whose self-type is equal to the expected self type,
2040
2207
// but whose args don't match.
@@ -4342,17 +4509,6 @@ fn hint_missing_borrow<'tcx>(
4342
4509
4343
4510
let args = fn_decl. inputs . iter ( ) ;
4344
4511
4345
- fn get_deref_type_and_refs ( mut ty : Ty < ' _ > ) -> ( Ty < ' _ > , Vec < hir:: Mutability > ) {
4346
- let mut refs = vec ! [ ] ;
4347
-
4348
- while let ty:: Ref ( _, new_ty, mutbl) = ty. kind ( ) {
4349
- ty = * new_ty;
4350
- refs. push ( * mutbl) ;
4351
- }
4352
-
4353
- ( ty, refs)
4354
- }
4355
-
4356
4512
let mut to_borrow = Vec :: new ( ) ;
4357
4513
let mut remove_borrow = Vec :: new ( ) ;
4358
4514
@@ -4645,3 +4801,14 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
4645
4801
4646
4802
Some ( sugg)
4647
4803
}
4804
+
4805
+ fn get_deref_type_and_refs ( mut ty : Ty < ' _ > ) -> ( Ty < ' _ > , Vec < hir:: Mutability > ) {
4806
+ let mut refs = vec ! [ ] ;
4807
+
4808
+ while let ty:: Ref ( _, new_ty, mutbl) = ty. kind ( ) {
4809
+ ty = * new_ty;
4810
+ refs. push ( * mutbl) ;
4811
+ }
4812
+
4813
+ ( ty, refs)
4814
+ }
0 commit comments