@@ -483,6 +483,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
483483 self . set_tainted_by_errors ( ) ;
484484 let tcx = self . tcx ;
485485
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+
486499 // A "softer" version of the `demand_compatible`, which checks types without persisting them,
487500 // and treats error types differently
488501 // 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> {
499512 return Compatibility :: Incompatible ( None ) ;
500513 }
501514
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] ;
510516
517+ let expectation = Expectation :: rvalue_hint ( self , expected_input_ty) ;
511518 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) ;
513520 if !can_coerce {
514521 return Compatibility :: Incompatible ( None ) ;
515522 }
516523
517524 // Using probe here, since we don't want this subtyping to affect inference.
518525 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 ( )
522527 } ) ;
523528
524529 // Same as above: if either the coerce type or the checked type is an error type,
525530 // consider them *not* compatible.
526- let references_error = ( coerced_ty, checked_ty ) . references_error ( ) ;
531+ let references_error = ( coerced_ty, arg_ty ) . references_error ( ) ;
527532 match ( references_error, subtyping_error) {
528533 ( false , None ) => Compatibility :: Compatible ,
529534 ( _, subtyping_error) => Compatibility :: Incompatible ( subtyping_error) ,
@@ -542,19 +547,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
542547 ArgMatrix :: new ( provided_args. len ( ) , formal_and_expected_inputs. len ( ) , check_compatible)
543548 . find_errors ( ) ;
544549
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-
558550 // First, check if we just need to wrap some arguments in a tuple.
559551 if let Some ( ( mismatch_idx, terr) ) =
560552 compatibility_diagonal. iter ( ) . enumerate ( ) . find_map ( |( i, c) | {
0 commit comments