@@ -128,21 +128,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
128
128
}
129
129
130
130
match self.tcx.hir_node(hir_id) {
131
- hir::Node::Expr(&hir::Expr {
132
- kind:
133
- hir::ExprKind::Call(
134
- hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. },
135
- args,
136
- ),
137
- span,
138
- ..
139
- }) => {
140
- if self.closure_span_overlaps_error(error, span) {
141
- return false;
131
+ hir::Node::Expr(expr) => self.point_at_expr_if_possible(
132
+ error,
133
+ def_id,
134
+ expr,
135
+ predicate_self_type_to_point_at,
136
+ param_to_point_at,
137
+ fallback_param_to_point_at,
138
+ self_param_to_point_at,
139
+ ),
140
+
141
+ hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => {
142
+ for param in [
143
+ predicate_self_type_to_point_at,
144
+ param_to_point_at,
145
+ fallback_param_to_point_at,
146
+ self_param_to_point_at,
147
+ ]
148
+ .into_iter()
149
+ .flatten()
150
+ {
151
+ if self.point_at_path_if_possible(error, def_id, param, &qpath) {
152
+ return true;
153
+ }
142
154
}
143
155
156
+ false
157
+ }
158
+
159
+ _ => false,
160
+ }
161
+ }
162
+
163
+ fn point_at_expr_if_possible(
164
+ &self,
165
+ error: &mut traits::FulfillmentError<'tcx>,
166
+ callee_def_id: DefId,
167
+ expr: &'tcx hir::Expr<'tcx>,
168
+ predicate_self_type_to_point_at: Option<ty::GenericArg<'tcx>>,
169
+ param_to_point_at: Option<ty::GenericArg<'tcx>>,
170
+ fallback_param_to_point_at: Option<ty::GenericArg<'tcx>>,
171
+ self_param_to_point_at: Option<ty::GenericArg<'tcx>>,
172
+ ) -> bool {
173
+ if self.closure_span_overlaps_error(error, expr.span) {
174
+ return false;
175
+ }
176
+
177
+ match expr.kind {
178
+ hir::ExprKind::Call(
179
+ hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. },
180
+ args,
181
+ ) => {
144
182
if let Some(param) = predicate_self_type_to_point_at
145
- && self.point_at_path_if_possible(error, def_id , param, &qpath)
183
+ && self.point_at_path_if_possible(error, callee_def_id , param, &qpath)
146
184
{
147
185
return true;
148
186
}
@@ -153,9 +191,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
153
191
{
154
192
if self.blame_specific_arg_if_possible(
155
193
error,
156
- def_id ,
194
+ callee_def_id ,
157
195
param,
158
- hir_id,
196
+ expr. hir_id,
159
197
*callee_span,
160
198
None,
161
199
args,
@@ -168,88 +206,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
168
206
.into_iter()
169
207
.flatten()
170
208
{
171
- if self.point_at_path_if_possible(error, def_id , param, &qpath) {
209
+ if self.point_at_path_if_possible(error, callee_def_id , param, &qpath) {
172
210
return true;
173
211
}
174
212
}
175
213
}
176
- hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(qpath), span, .. }) => {
177
- if self.closure_span_overlaps_error(error, span) {
178
- return false;
214
+ hir::ExprKind::Path(qpath) => {
215
+ // If the parent is an call, then process this as a call.
216
+ //
217
+ // This is because the `WhereClauseInExpr` obligations come from
218
+ // the well-formedness of the *path* expression, but we care to
219
+ // point at the call expression (namely, its args).
220
+ if let hir::Node::Expr(
221
+ call_expr @ hir::Expr { kind: hir::ExprKind::Call(callee, ..), .. },
222
+ ) = self.tcx.parent_hir_node(expr.hir_id)
223
+ && callee.hir_id == expr.hir_id
224
+ {
225
+ return self.point_at_expr_if_possible(
226
+ error,
227
+ callee_def_id,
228
+ call_expr,
229
+ predicate_self_type_to_point_at,
230
+ param_to_point_at,
231
+ fallback_param_to_point_at,
232
+ self_param_to_point_at,
233
+ );
179
234
}
180
235
236
+ // Otherwise, just try to point at path components.
237
+
181
238
if let Some(param) = predicate_self_type_to_point_at
182
- && self.point_at_path_if_possible(error, def_id , param, &qpath)
239
+ && self.point_at_path_if_possible(error, callee_def_id , param, &qpath)
183
240
{
184
241
return true;
185
242
}
186
243
187
- if let hir::Node::Expr(hir::Expr {
188
- kind: hir::ExprKind::Call(callee, args),
189
- hir_id: call_hir_id,
190
- span: call_span,
191
- ..
192
- }) = self.tcx.parent_hir_node(hir_id)
193
- && callee.hir_id == hir_id
194
- {
195
- if self.closure_span_overlaps_error(error, *call_span) {
196
- return false;
197
- }
198
-
199
- for param in
200
- [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
201
- .into_iter()
202
- .flatten()
203
- {
204
- if self.blame_specific_arg_if_possible(
205
- error,
206
- def_id,
207
- param,
208
- *call_hir_id,
209
- callee.span,
210
- None,
211
- args,
212
- ) {
213
- return true;
214
- }
215
- }
216
- }
217
-
218
244
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
219
245
.into_iter()
220
246
.flatten()
221
247
{
222
- if self.point_at_path_if_possible(error, def_id , param, &qpath) {
248
+ if self.point_at_path_if_possible(error, callee_def_id , param, &qpath) {
223
249
return true;
224
250
}
225
251
}
226
252
}
227
- hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => {
228
- for param in [
229
- predicate_self_type_to_point_at,
230
- param_to_point_at,
231
- fallback_param_to_point_at,
232
- self_param_to_point_at,
233
- ]
234
- .into_iter()
235
- .flatten()
236
- {
237
- if self.point_at_path_if_possible(error, def_id, param, &qpath) {
238
- return true;
239
- }
240
- }
241
- }
242
- hir::Node::Expr(&hir::Expr {
243
- kind: hir::ExprKind::MethodCall(segment, receiver, args, ..),
244
- span,
245
- ..
246
- }) => {
247
- if self.closure_span_overlaps_error(error, span) {
248
- return false;
249
- }
250
-
253
+ hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
251
254
if let Some(param) = predicate_self_type_to_point_at
252
- && self.point_at_generic_if_possible(error, def_id , param, segment)
255
+ && self.point_at_generic_if_possible(error, callee_def_id , param, segment)
253
256
{
254
257
// HACK: This is not correct, since `predicate_self_type_to_point_at` might
255
258
// not actually correspond to the receiver of the method call. But we
@@ -259,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259
262
error.obligation.cause.map_code(|parent_code| {
260
263
ObligationCauseCode::FunctionArg {
261
264
arg_hir_id: receiver.hir_id,
262
- call_hir_id: hir_id,
265
+ call_hir_id: expr. hir_id,
263
266
parent_code,
264
267
}
265
268
});
@@ -272,9 +275,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
272
275
{
273
276
if self.blame_specific_arg_if_possible(
274
277
error,
275
- def_id ,
278
+ callee_def_id ,
276
279
param,
277
- hir_id,
280
+ expr. hir_id,
278
281
segment.ident.span,
279
282
Some(receiver),
280
283
args,
@@ -283,7 +286,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
283
286
}
284
287
}
285
288
if let Some(param_to_point_at) = param_to_point_at
286
- && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
289
+ && self.point_at_generic_if_possible(
290
+ error,
291
+ callee_def_id,
292
+ param_to_point_at,
293
+ segment,
294
+ )
287
295
{
288
296
return true;
289
297
}
@@ -297,25 +305,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
297
305
return true;
298
306
}
299
307
}
300
- hir::Node::Expr(&hir::Expr {
301
- kind: hir::ExprKind::Struct(qpath, fields, ..),
302
- span,
303
- ..
304
- }) => {
305
- if self.closure_span_overlaps_error(error, span) {
306
- return false;
307
- }
308
-
308
+ hir::ExprKind::Struct(qpath, fields, ..) => {
309
309
if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
310
- self.typeck_results.borrow().qpath_res(qpath, hir_id)
310
+ self.typeck_results.borrow().qpath_res(qpath, expr. hir_id)
311
311
{
312
312
for param in
313
313
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
314
314
.into_iter()
315
315
.flatten()
316
316
{
317
- let refined_expr =
318
- self.point_at_field_if_possible(def_id, param, variant_def_id, fields);
317
+ let refined_expr = self.point_at_field_if_possible(
318
+ callee_def_id,
319
+ param,
320
+ variant_def_id,
321
+ fields,
322
+ );
319
323
320
324
match refined_expr {
321
325
None => {}
@@ -339,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
339
343
.into_iter()
340
344
.flatten()
341
345
{
342
- if self.point_at_path_if_possible(error, def_id , param, qpath) {
346
+ if self.point_at_path_if_possible(error, callee_def_id , param, qpath) {
343
347
return true;
344
348
}
345
349
}
0 commit comments