@@ -33,27 +33,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33
33
} ;
34
34
35
35
let generics = self . tcx . generics_of ( def_id) ;
36
- let predicate_args = match unsubstituted_pred. kind ( ) . skip_binder ( ) {
37
- ty:: ClauseKind :: Trait ( pred) => pred. trait_ref . args . to_vec ( ) ,
38
- ty:: ClauseKind :: Projection ( pred) => pred. projection_ty . args . to_vec ( ) ,
39
- ty:: ClauseKind :: ConstArgHasType ( arg, ty) => {
40
- vec ! [ ty. into( ) , arg. into( ) ]
41
- }
42
- ty:: ClauseKind :: ConstEvaluatable ( e) => vec ! [ e. into( ) ] ,
43
- _ => return false ,
44
- } ;
36
+ let ( predicate_args, predicate_self_type_to_point_at) =
37
+ match unsubstituted_pred. kind ( ) . skip_binder ( ) {
38
+ ty:: ClauseKind :: Trait ( pred) => {
39
+ ( pred. trait_ref . args . to_vec ( ) , Some ( pred. self_ty ( ) . into ( ) ) )
40
+ }
41
+ ty:: ClauseKind :: Projection ( pred) => ( pred. projection_ty . args . to_vec ( ) , None ) ,
42
+ ty:: ClauseKind :: ConstArgHasType ( arg, ty) => ( vec ! [ ty. into( ) , arg. into( ) ] , None ) ,
43
+ ty:: ClauseKind :: ConstEvaluatable ( e) => ( vec ! [ e. into( ) ] , None ) ,
44
+ _ => return false ,
45
+ } ;
45
46
46
- let direct_param = if let ty:: ClauseKind :: Trait ( pred) = unsubstituted_pred. kind ( ) . skip_binder ( )
47
- && let ty = pred. trait_ref . self_ty ( )
48
- && let ty:: Param ( _param) = ty. kind ( )
49
- && let Some ( arg) = predicate_args. get ( 0 )
50
- && let ty:: GenericArgKind :: Type ( arg_ty) = arg. unpack ( )
51
- && arg_ty == ty
52
- {
53
- Some ( * arg)
54
- } else {
55
- None
56
- } ;
57
47
let find_param_matching = |matches : & dyn Fn ( ty:: ParamTerm ) -> bool | {
58
48
predicate_args. iter ( ) . find_map ( |arg| {
59
49
arg. walk ( ) . find_map ( |arg| {
@@ -112,18 +102,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
112
102
let qpath =
113
103
if let hir:: ExprKind :: Path ( qpath) = expr. kind { Some ( qpath) } else { None } ;
114
104
115
- ( Some ( * expr) , qpath)
105
+ ( Some ( & expr. kind ) , qpath)
116
106
}
117
107
hir:: Node :: Ty ( hir:: Ty { kind : hir:: TyKind :: Path ( qpath) , .. } ) => ( None , Some ( * qpath) ) ,
118
108
_ => return false ,
119
109
} ;
120
110
121
111
if let Some ( qpath) = qpath {
122
- if let Some ( param) = direct_param {
123
- if self . point_at_path_if_possible ( error, def_id, param, & qpath) {
124
- return true ;
125
- }
112
+ // Prefer pointing at the turbofished arg that corresponds to the
113
+ // self type of the failing predicate over anything else.
114
+ if let Some ( param) = predicate_self_type_to_point_at
115
+ && self . point_at_path_if_possible ( error, def_id, param, & qpath)
116
+ {
117
+ return true ;
126
118
}
119
+
127
120
if let hir:: Node :: Expr ( hir:: Expr {
128
121
kind : hir:: ExprKind :: Call ( callee, args) ,
129
122
hir_id : call_hir_id,
@@ -166,11 +159,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
166
159
}
167
160
}
168
161
169
- match expr. map ( |e| e . kind ) {
162
+ match expr {
170
163
Some ( hir:: ExprKind :: MethodCall ( segment, receiver, args, ..) ) => {
171
- if let Some ( param) = direct_param
164
+ if let Some ( param) = predicate_self_type_to_point_at
172
165
&& self . point_at_generic_if_possible ( error, def_id, param, segment)
173
166
{
167
+ // HACK: This is not correct, since `predicate_self_type_to_point_at` might
168
+ // not actually correspond to the receiver of the method call. But we
169
+ // re-adjust the cause code here in order to prefer pointing at one of
170
+ // the method's turbofish segments but still use `FunctionArgumentObligation`
171
+ // elsewhere. Hopefully this doesn't break something.
174
172
error. obligation . cause . map_code ( |parent_code| {
175
173
ObligationCauseCode :: FunctionArgumentObligation {
176
174
arg_hir_id : receiver. hir_id ,
@@ -180,6 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
180
178
} ) ;
181
179
return true ;
182
180
}
181
+
183
182
for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
184
183
. into_iter ( )
185
184
. flatten ( )
@@ -237,7 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
237
236
}
238
237
239
238
for param in [
240
- direct_param ,
239
+ predicate_self_type_to_point_at ,
241
240
param_to_point_at,
242
241
fallback_param_to_point_at,
243
242
self_param_to_point_at,
0 commit comments