@@ -43,6 +43,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
43
43
_ => return false ,
44
44
} ;
45
45
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
+ } ;
46
57
let find_param_matching = |matches : & dyn Fn ( ty:: ParamTerm ) -> bool | {
47
58
predicate_args. iter ( ) . find_map ( |arg| {
48
59
arg. walk ( ) . find_map ( |arg| {
@@ -63,32 +74,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
63
74
} )
64
75
} ;
65
76
66
- // Account for enum variant constructors, where the type param corresponds to the enum
67
- // itself.
68
- let enum_def_id =
69
- if let DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , _) = self . tcx . def_kind ( def_id) {
70
- // `def_id` corresponds to a constructor, and its parent is the variant, and we want
71
- // the enum.
72
- Some ( self . tcx . parent ( self . tcx . parent ( def_id) ) )
73
- } else {
74
- None
75
- } ;
76
- let variant_param_to_point_at = find_param_matching ( & |param_term| {
77
- // FIXME: It would be nice to make this not use string manipulation,
78
- // but it's pretty hard to do this, since `ty::ParamTy` is missing
79
- // sufficient info to determine if it is synthetic, and we don't
80
- // always have a convenient way of getting `ty::Generics` at the call
81
- // sites we invoke `IsSuggestable::is_suggestable`.
82
- let include = match param_term {
83
- ty:: ParamTerm :: Ty ( param_ty) => !param_ty. name . as_str ( ) . starts_with ( "impl " ) ,
84
- _ => true ,
85
- } ;
86
- // Account for enum variant constructors, where the type param corresponds to the enum
87
- // itself.
88
- let def_id = if let Some ( def_id) = enum_def_id { def_id } else { def_id } ;
89
- self . tcx . parent ( generics. param_at ( param_term. index ( ) , self . tcx ) . def_id ) == def_id
90
- && include
91
- } ) ;
92
77
// Prefer generics that are local to the fn item, since these are likely
93
78
// to be the cause of the unsatisfied predicate.
94
79
let mut param_to_point_at = find_param_matching ( & |param_term| {
@@ -134,20 +119,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
134
119
} ;
135
120
136
121
if let Some ( qpath) = qpath {
137
- let def_id = if let Some ( def_id) = enum_def_id { def_id } else { def_id } ;
138
- if let hir:: QPath :: Resolved ( None , path) = qpath {
139
- for segment in path. segments {
140
- if let Some ( param) = variant_param_to_point_at
141
- && self . point_at_generic_if_possible ( error, def_id, param, segment)
142
- {
143
- return true ;
144
- }
145
- }
146
- }
147
- if let hir:: QPath :: TypeRelative ( _ty, segment) = qpath {
148
- if let Some ( param) = variant_param_to_point_at
149
- && self . point_at_generic_if_possible ( error, def_id, param, segment)
150
- {
122
+ if let Some ( param) = direct_param {
123
+ if self . point_at_path_if_possible ( error, def_id, param, & qpath) {
151
124
return true ;
152
125
}
153
126
}
@@ -195,6 +168,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
195
168
196
169
match expr. map ( |e| e. kind ) {
197
170
Some ( hir:: ExprKind :: MethodCall ( segment, receiver, args, ..) ) => {
171
+ if let Some ( param) = direct_param
172
+ && self . point_at_generic_if_possible ( error, def_id, param, segment)
173
+ {
174
+ error. obligation . cause . map_code ( |parent_code| {
175
+ ObligationCauseCode :: FunctionArgumentObligation {
176
+ arg_hir_id : receiver. hir_id ,
177
+ call_hir_id : hir_id,
178
+ parent_code,
179
+ }
180
+ } ) ;
181
+ return true ;
182
+ }
198
183
for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
199
184
. into_iter ( )
200
185
. flatten ( )
@@ -251,9 +236,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
251
236
}
252
237
}
253
238
254
- for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
255
- . into_iter ( )
256
- . flatten ( )
239
+ for param in [
240
+ direct_param,
241
+ param_to_point_at,
242
+ fallback_param_to_point_at,
243
+ self_param_to_point_at,
244
+ ]
245
+ . into_iter ( )
246
+ . flatten ( )
257
247
{
258
248
if self . point_at_path_if_possible ( error, def_id, param, qpath) {
259
249
return true ;
@@ -485,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
485
475
}
486
476
487
477
/**
488
- * Recursively searches for the most-specific blamable expression.
478
+ * Recursively searches for the most-specific blameable expression.
489
479
* For example, if you have a chain of constraints like:
490
480
* - want `Vec<i32>: Copy`
491
481
* - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
0 commit comments