@@ -321,6 +321,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
321
321
322
322
let mut final_arg_types: Vec < ( usize , Ty < ' _ > , Ty < ' _ > ) > = vec ! [ ] ;
323
323
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
+
324
373
// Check the arguments.
325
374
// We do this in a pretty awful way: first we type-check any arguments
326
375
// that are not closures, then we type-check the closures. This is so
@@ -369,47 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
369
418
continue ;
370
419
}
371
420
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) ;
413
422
}
414
423
}
415
424
0 commit comments