@@ -912,12 +912,12 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
912
912
} ;
913
913
914
914
// All type checking constraints were added, try to fallback unsolved variables.
915
- fcx. select_obligations_where_possible ( false ) ;
915
+ fcx. select_obligations_where_possible ( false , |_| { } ) ;
916
916
let mut fallback_has_occurred = false ;
917
917
for ty in & fcx. unsolved_variables ( ) {
918
918
fallback_has_occurred |= fcx. fallback_if_possible ( ty) ;
919
919
}
920
- fcx. select_obligations_where_possible ( fallback_has_occurred) ;
920
+ fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
921
921
922
922
// Even though coercion casts provide type hints, we check casts after fallback for
923
923
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
@@ -2391,7 +2391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2391
2391
// possible. This can help substantially when there are
2392
2392
// indirect dependencies that don't seem worth tracking
2393
2393
// precisely.
2394
- self . select_obligations_where_possible ( false ) ;
2394
+ self . select_obligations_where_possible ( false , |_| { } ) ;
2395
2395
ty = self . resolve_vars_if_possible ( & ty) ;
2396
2396
2397
2397
debug ! ( "resolve_type_vars_with_obligations: ty={:?}" , ty) ;
@@ -2842,7 +2842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2842
2842
fn resolve_generator_interiors ( & self , def_id : DefId ) {
2843
2843
let mut generators = self . deferred_generator_interiors . borrow_mut ( ) ;
2844
2844
for ( body_id, interior, kind) in generators. drain ( ..) {
2845
- self . select_obligations_where_possible ( false ) ;
2845
+ self . select_obligations_where_possible ( false , |_| { } ) ;
2846
2846
generator_interior:: resolve_interior ( self , def_id, body_id, interior, kind) ;
2847
2847
}
2848
2848
}
@@ -2879,8 +2879,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2879
2879
}
2880
2880
2881
2881
/// Select as many obligations as we can at present.
2882
- fn select_obligations_where_possible ( & self , fallback_has_occurred : bool ) {
2883
- if let Err ( errors) = self . fulfillment_cx . borrow_mut ( ) . select_where_possible ( self ) {
2882
+ fn select_obligations_where_possible (
2883
+ & self ,
2884
+ fallback_has_occurred : bool ,
2885
+ mutate_fullfillment_errors : impl Fn ( & mut Vec < traits:: FulfillmentError < ' tcx > > ) ,
2886
+ ) {
2887
+ if let Err ( mut errors) = self . fulfillment_cx . borrow_mut ( ) . select_where_possible ( self ) {
2888
+ mutate_fullfillment_errors ( & mut errors) ;
2884
2889
self . report_fulfillment_errors ( & errors, self . inh . body_id , fallback_has_occurred) ;
2885
2890
}
2886
2891
}
@@ -3288,6 +3293,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3288
3293
formal_tys. clone ( )
3289
3294
} ;
3290
3295
3296
+ let mut final_arg_types: Vec < ( usize , Ty < ' _ > ) > = vec ! [ ] ;
3297
+
3291
3298
// Check the arguments.
3292
3299
// We do this in a pretty awful way: first we type-check any arguments
3293
3300
// that are not closures, then we type-check the closures. This is so
@@ -3300,7 +3307,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3300
3307
// an "opportunistic" vtable resolution of any trait bounds on
3301
3308
// the call. This helps coercions.
3302
3309
if check_closures {
3303
- self . select_obligations_where_possible ( false ) ;
3310
+ self . select_obligations_where_possible ( false , |errors| {
3311
+ self . point_at_arg_instead_of_call_if_possible (
3312
+ errors,
3313
+ & final_arg_types[ ..] ,
3314
+ sp,
3315
+ & args,
3316
+ ) ;
3317
+ } )
3304
3318
}
3305
3319
3306
3320
// For C-variadic functions, we don't have a declared type for all of
@@ -3346,6 +3360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3346
3360
// We're processing function arguments so we definitely want to use
3347
3361
// two-phase borrows.
3348
3362
self . demand_coerce ( & arg, checked_ty, coerce_ty, AllowTwoPhase :: Yes ) ;
3363
+ final_arg_types. push ( ( i, coerce_ty) ) ;
3349
3364
3350
3365
// 3. Relate the expected type and the formal one,
3351
3366
// if the expected type was used for the coercion.
@@ -3392,6 +3407,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3392
3407
vec ! [ self . tcx. types. err; len]
3393
3408
}
3394
3409
3410
+ /// Given a vec of evaluated `FullfillmentError`s and an `fn` call argument expressions, we
3411
+ /// walk the resolved types for each argument to see if any of the `FullfillmentError`s
3412
+ /// reference a type argument. If they do, and there's only *one* argument that does, we point
3413
+ /// at the corresponding argument's expression span instead of the `fn` call path span.
3414
+ fn point_at_arg_instead_of_call_if_possible (
3415
+ & self ,
3416
+ errors : & mut Vec < traits:: FulfillmentError < ' _ > > ,
3417
+ final_arg_types : & [ ( usize , Ty < ' tcx > ) ] ,
3418
+ call_sp : Span ,
3419
+ args : & ' tcx [ hir:: Expr ] ,
3420
+ ) {
3421
+ if !call_sp. desugaring_kind ( ) . is_some ( ) {
3422
+ // We *do not* do this for desugared call spans to keep good diagnostics when involving
3423
+ // the `?` operator.
3424
+ for error in errors {
3425
+ if let ty:: Predicate :: Trait ( predicate) = error. obligation . predicate {
3426
+ // Collect the argument position for all arguments that could have caused this
3427
+ // `FullfillmentError`.
3428
+ let mut referenced_in = final_arg_types. iter ( )
3429
+ . flat_map ( |( i, ty) | {
3430
+ let ty = self . resolve_vars_if_possible ( ty) ;
3431
+ // We walk the argument type because the argument's type could have
3432
+ // been `Option<T>`, but the `FullfillmentError` references `T`.
3433
+ ty. walk ( )
3434
+ . filter ( |& ty| ty == predicate. skip_binder ( ) . self_ty ( ) )
3435
+ . map ( move |_| * i)
3436
+ } ) ;
3437
+ if let ( Some ( ref_in) , None ) = ( referenced_in. next ( ) , referenced_in. next ( ) ) {
3438
+ // We make sure that only *one* argument matches the obligation failure
3439
+ // and thet the obligation's span to its expression's.
3440
+ error. obligation . cause . span = args[ ref_in] . span ;
3441
+ error. points_at_arg_span = true ;
3442
+ }
3443
+ }
3444
+ }
3445
+ }
3446
+ }
3447
+
3395
3448
// AST fragment checking
3396
3449
fn check_lit ( & self ,
3397
3450
lit : & hir:: Lit ,
@@ -3549,8 +3602,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3549
3602
3550
3603
// Check bounds on type arguments used in the path.
3551
3604
let bounds = self . instantiate_bounds ( path_span, did, substs) ;
3552
- let cause = traits:: ObligationCause :: new ( path_span, self . body_id ,
3553
- traits:: ItemObligation ( did) ) ;
3605
+ let cause = traits:: ObligationCause :: new (
3606
+ path_span,
3607
+ self . body_id ,
3608
+ traits:: ItemObligation ( did) ,
3609
+ ) ;
3554
3610
self . add_obligations_for_parameters ( cause, & bounds) ;
3555
3611
3556
3612
Some ( ( variant, ty) )
@@ -4674,7 +4730,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4674
4730
let bounds = self . instantiate_bounds ( span, def_id, & substs) ;
4675
4731
self . add_obligations_for_parameters (
4676
4732
traits:: ObligationCause :: new ( span, self . body_id , traits:: ItemObligation ( def_id) ) ,
4677
- & bounds) ;
4733
+ & bounds,
4734
+ ) ;
4678
4735
4679
4736
// Substitute the values for the type parameters into the type of
4680
4737
// the referenced item.
0 commit comments