@@ -321,6 +321,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
321321
322322 let mut final_arg_types: Vec < ( usize , Ty < ' _ > , Ty < ' _ > ) > = vec ! [ ] ;
323323
324+ // We introduce a helper function to demand that a given argument satisfy a given input
325+ // This is more complicated than just checking type equality, as arguments could be coerced
326+ // This version writes those types back so further type checking uses the narrowed types
327+ let demand_compatible = |idx, final_arg_types : & mut Vec < ( usize , Ty < ' tcx > , Ty < ' tcx > ) > | {
328+ let formal_input_ty: Ty < ' tcx > = formal_input_tys[ idx] ;
329+ let expected_input_ty: Ty < ' tcx > = expected_input_tys[ idx] ;
330+ let provided_arg = & provided_args[ idx] ;
331+
332+ debug ! ( "checking argument {}: {:?} = {:?}" , idx, provided_arg, formal_input_ty) ;
333+
334+ // The special-cased logic below has three functions:
335+ // 1. Provide as good of an expected type as possible.
336+ let expectation = Expectation :: rvalue_hint ( self , expected_input_ty) ;
337+
338+ let checked_ty = self . check_expr_with_expectation ( provided_arg, expectation) ;
339+
340+ // 2. Coerce to the most detailed type that could be coerced
341+ // to, which is `expected_ty` if `rvalue_hint` returns an
342+ // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
343+ let coerced_ty = expectation. only_has_type ( self ) . unwrap_or ( formal_input_ty) ;
344+
345+ // Keep track of these for below
346+ final_arg_types. push ( ( idx, checked_ty, coerced_ty) ) ;
347+
348+ // Cause selection errors caused by resolving a single argument to point at the
349+ // argument and not the call. This is otherwise redundant with the `demand_coerce`
350+ // call immediately after, but it lets us customize the span pointed to in the
351+ // fulfillment error to be more accurate.
352+ let _ =
353+ self . resolve_vars_with_obligations_and_mutate_fulfillment ( coerced_ty, |errors| {
354+ self . point_at_type_arg_instead_of_call_if_possible ( errors, call_expr) ;
355+ self . point_at_arg_instead_of_call_if_possible (
356+ errors,
357+ & final_arg_types,
358+ call_expr,
359+ call_span,
360+ provided_args,
361+ ) ;
362+ } ) ;
363+
364+ // We're processing function arguments so we definitely want to use
365+ // two-phase borrows.
366+ self . demand_coerce ( & provided_arg, checked_ty, coerced_ty, None , AllowTwoPhase :: Yes ) ;
367+
368+ // 3. Relate the expected type and the formal one,
369+ // if the expected type was used for the coercion.
370+ self . demand_suptype ( provided_arg. span , formal_input_ty, coerced_ty) ;
371+ } ;
372+
324373 // Check the arguments.
325374 // We do this in a pretty awful way: first we type-check any arguments
326375 // that are not closures, then we type-check the closures. This is so
@@ -369,47 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
369418 continue ;
370419 }
371420
372- let formal_ty = formal_input_tys[ i] ;
373- debug ! ( "checking argument {}: {:?} = {:?}" , i, arg, formal_ty) ;
374-
375- // The special-cased logic below has three functions:
376- // 1. Provide as good of an expected type as possible.
377- let expected = Expectation :: rvalue_hint ( self , expected_input_tys[ i] ) ;
378-
379- let checked_ty = self . check_expr_with_expectation ( & arg, expected) ;
380-
381- // 2. Coerce to the most detailed type that could be coerced
382- // to, which is `expected_ty` if `rvalue_hint` returns an
383- // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
384- let coerce_ty = expected. only_has_type ( self ) . unwrap_or ( formal_ty) ;
385-
386- final_arg_types. push ( ( i, checked_ty, coerce_ty) ) ;
387-
388- // Cause selection errors caused by resolving a single argument to point at the
389- // argument and not the call. This is otherwise redundant with the `demand_coerce`
390- // call immediately after, but it lets us customize the span pointed to in the
391- // fulfillment error to be more accurate.
392- let _ = self . resolve_vars_with_obligations_and_mutate_fulfillment (
393- coerce_ty,
394- |errors| {
395- self . point_at_type_arg_instead_of_call_if_possible ( errors, call_expr) ;
396- self . point_at_arg_instead_of_call_if_possible (
397- errors,
398- & final_arg_types,
399- call_expr,
400- call_span,
401- provided_args,
402- ) ;
403- } ,
404- ) ;
405-
406- // We're processing function arguments so we definitely want to use
407- // two-phase borrows.
408- self . demand_coerce ( & arg, checked_ty, coerce_ty, None , AllowTwoPhase :: Yes ) ;
409-
410- // 3. Relate the expected type and the formal one,
411- // if the expected type was used for the coercion.
412- self . demand_suptype ( arg. span , formal_ty, coerce_ty) ;
421+ demand_compatible ( i, & mut final_arg_types) ;
413422 }
414423 }
415424
0 commit comments