@@ -912,12 +912,12 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
912912 } ;
913913
914914 // 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 , |_| { } ) ;
916916 let mut fallback_has_occurred = false ;
917917 for ty in & fcx. unsolved_variables ( ) {
918918 fallback_has_occurred |= fcx. fallback_if_possible ( ty) ;
919919 }
920- fcx. select_obligations_where_possible ( fallback_has_occurred) ;
920+ fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
921921
922922 // Even though coercion casts provide type hints, we check casts after fallback for
923923 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
@@ -2391,7 +2391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23912391 // possible. This can help substantially when there are
23922392 // indirect dependencies that don't seem worth tracking
23932393 // precisely.
2394- self . select_obligations_where_possible ( false ) ;
2394+ self . select_obligations_where_possible ( false , |_| { } ) ;
23952395 ty = self . resolve_vars_if_possible ( & ty) ;
23962396
23972397 debug ! ( "resolve_type_vars_with_obligations: ty={:?}" , ty) ;
@@ -2842,7 +2842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
28422842 fn resolve_generator_interiors ( & self , def_id : DefId ) {
28432843 let mut generators = self . deferred_generator_interiors . borrow_mut ( ) ;
28442844 for ( body_id, interior, kind) in generators. drain ( ..) {
2845- self . select_obligations_where_possible ( false ) ;
2845+ self . select_obligations_where_possible ( false , |_| { } ) ;
28462846 generator_interior:: resolve_interior ( self , def_id, body_id, interior, kind) ;
28472847 }
28482848 }
@@ -2879,8 +2879,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
28792879 }
28802880
28812881 /// 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) ;
28842889 self . report_fulfillment_errors ( & errors, self . inh . body_id , fallback_has_occurred) ;
28852890 }
28862891 }
@@ -3288,6 +3293,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32883293 formal_tys. clone ( )
32893294 } ;
32903295
3296+ let mut final_arg_types: Vec < ( usize , Ty < ' _ > ) > = vec ! [ ] ;
3297+
32913298 // Check the arguments.
32923299 // We do this in a pretty awful way: first we type-check any arguments
32933300 // that are not closures, then we type-check the closures. This is so
@@ -3300,7 +3307,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33003307 // an "opportunistic" vtable resolution of any trait bounds on
33013308 // the call. This helps coercions.
33023309 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+ } )
33043318 }
33053319
33063320 // For C-variadic functions, we don't have a declared type for all of
@@ -3346,6 +3360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33463360 // We're processing function arguments so we definitely want to use
33473361 // two-phase borrows.
33483362 self . demand_coerce ( & arg, checked_ty, coerce_ty, AllowTwoPhase :: Yes ) ;
3363+ final_arg_types. push ( ( i, coerce_ty) ) ;
33493364
33503365 // 3. Relate the expected type and the formal one,
33513366 // if the expected type was used for the coercion.
@@ -3392,6 +3407,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33923407 vec ! [ self . tcx. types. err; len]
33933408 }
33943409
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+
33953448 // AST fragment checking
33963449 fn check_lit ( & self ,
33973450 lit : & hir:: Lit ,
@@ -3549,8 +3602,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
35493602
35503603 // Check bounds on type arguments used in the path.
35513604 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+ ) ;
35543610 self . add_obligations_for_parameters ( cause, & bounds) ;
35553611
35563612 Some ( ( variant, ty) )
@@ -4674,7 +4730,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46744730 let bounds = self . instantiate_bounds ( span, def_id, & substs) ;
46754731 self . add_obligations_for_parameters (
46764732 traits:: ObligationCause :: new ( span, self . body_id , traits:: ItemObligation ( def_id) ) ,
4677- & bounds) ;
4733+ & bounds,
4734+ ) ;
46784735
46794736 // Substitute the values for the type parameters into the type of
46804737 // the referenced item.
0 commit comments