@@ -483,6 +483,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
483
483
self . set_tainted_by_errors ( ) ;
484
484
let tcx = self . tcx ;
485
485
486
+ // Precompute the provided types and spans, since that's all we typically need for below
487
+ let provided_arg_tys: IndexVec < ProvidedIdx , ( Ty < ' tcx > , Span ) > = provided_args
488
+ . iter ( )
489
+ . map ( |expr| {
490
+ let ty = self
491
+ . typeck_results
492
+ . borrow ( )
493
+ . expr_ty_adjusted_opt ( * expr)
494
+ . unwrap_or_else ( || tcx. ty_error ( ) ) ;
495
+ ( self . resolve_vars_if_possible ( ty) , expr. span )
496
+ } )
497
+ . collect ( ) ;
498
+
486
499
// A "softer" version of the `demand_compatible`, which checks types without persisting them,
487
500
// and treats error types differently
488
501
// This will allow us to "probe" for other argument orders that would likely have been correct
@@ -499,31 +512,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
499
512
return Compatibility :: Incompatible ( None ) ;
500
513
}
501
514
502
- let provided_arg: & hir:: Expr < ' tcx > = & provided_args[ provided_idx] ;
503
- let expectation = Expectation :: rvalue_hint ( self , expected_input_ty) ;
504
- // FIXME: check that this is safe; I don't believe this commits any of the obligations, but I can't be sure.
505
- //
506
- // I had another method of "soft" type checking before,
507
- // but it was failing to find the type of some expressions (like "")
508
- // so I prodded this method and made it pub(super) so I could call it, and it seems to work well.
509
- let checked_ty = self . check_expr_kind ( provided_arg, expectation) ;
515
+ let ( arg_ty, arg_span) = provided_arg_tys[ provided_idx] ;
510
516
517
+ let expectation = Expectation :: rvalue_hint ( self , expected_input_ty) ;
511
518
let coerced_ty = expectation. only_has_type ( self ) . unwrap_or ( formal_input_ty) ;
512
- let can_coerce = self . can_coerce ( checked_ty , coerced_ty) ;
519
+ let can_coerce = self . can_coerce ( arg_ty , coerced_ty) ;
513
520
if !can_coerce {
514
521
return Compatibility :: Incompatible ( None ) ;
515
522
}
516
523
517
524
// Using probe here, since we don't want this subtyping to affect inference.
518
525
let subtyping_error = self . probe ( |_| {
519
- self . at ( & self . misc ( provided_arg. span ) , self . param_env )
520
- . sup ( formal_input_ty, coerced_ty)
521
- . err ( )
526
+ self . at ( & self . misc ( arg_span) , self . param_env ) . sup ( formal_input_ty, coerced_ty) . err ( )
522
527
} ) ;
523
528
524
529
// Same as above: if either the coerce type or the checked type is an error type,
525
530
// consider them *not* compatible.
526
- let references_error = ( coerced_ty, checked_ty ) . references_error ( ) ;
531
+ let references_error = ( coerced_ty, arg_ty ) . references_error ( ) ;
527
532
match ( references_error, subtyping_error) {
528
533
( false , None ) => Compatibility :: Compatible ,
529
534
( _, subtyping_error) => Compatibility :: Incompatible ( subtyping_error) ,
@@ -542,19 +547,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
542
547
ArgMatrix :: new ( provided_args. len ( ) , formal_and_expected_inputs. len ( ) , check_compatible)
543
548
. find_errors ( ) ;
544
549
545
- // Precompute the provided types and spans, since that's all we typically need for below
546
- let provided_arg_tys: IndexVec < ProvidedIdx , ( Ty < ' tcx > , Span ) > = provided_args
547
- . iter ( )
548
- . map ( |expr| {
549
- let ty = self
550
- . typeck_results
551
- . borrow ( )
552
- . expr_ty_adjusted_opt ( * expr)
553
- . unwrap_or_else ( || tcx. ty_error ( ) ) ;
554
- ( self . resolve_vars_if_possible ( ty) , expr. span )
555
- } )
556
- . collect ( ) ;
557
-
558
550
// First, check if we just need to wrap some arguments in a tuple.
559
551
if let Some ( ( mismatch_idx, terr) ) =
560
552
compatibility_diagonal. iter ( ) . enumerate ( ) . find_map ( |( i, c) | {
0 commit comments