@@ -33,27 +33,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3333 } ;
3434
3535 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+ } ;
4546
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- } ;
5747 let find_param_matching = |matches : & dyn Fn ( ty:: ParamTerm ) -> bool | {
5848 predicate_args. iter ( ) . find_map ( |arg| {
5949 arg. walk ( ) . find_map ( |arg| {
@@ -112,18 +102,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
112102 let qpath =
113103 if let hir:: ExprKind :: Path ( qpath) = expr. kind { Some ( qpath) } else { None } ;
114104
115- ( Some ( * expr) , qpath)
105+ ( Some ( & expr. kind ) , qpath)
116106 }
117107 hir:: Node :: Ty ( hir:: Ty { kind : hir:: TyKind :: Path ( qpath) , .. } ) => ( None , Some ( * qpath) ) ,
118108 _ => return false ,
119109 } ;
120110
121111 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 ;
126118 }
119+
127120 if let hir:: Node :: Expr ( hir:: Expr {
128121 kind : hir:: ExprKind :: Call ( callee, args) ,
129122 hir_id : call_hir_id,
@@ -166,11 +159,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
166159 }
167160 }
168161
169- match expr. map ( |e| e . kind ) {
162+ match expr {
170163 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
172165 && self . point_at_generic_if_possible ( error, def_id, param, segment)
173166 {
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.
174172 error. obligation . cause . map_code ( |parent_code| {
175173 ObligationCauseCode :: FunctionArgumentObligation {
176174 arg_hir_id : receiver. hir_id ,
@@ -180,6 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
180178 } ) ;
181179 return true ;
182180 }
181+
183182 for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
184183 . into_iter ( )
185184 . flatten ( )
@@ -237,7 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
237236 }
238237
239238 for param in [
240- direct_param ,
239+ predicate_self_type_to_point_at ,
241240 param_to_point_at,
242241 fallback_param_to_point_at,
243242 self_param_to_point_at,
0 commit comments