@@ -18,7 +18,7 @@ use rustc_hir::def_id::DefId;
1818use rustc_hir:: { ExprKind , Node , QPath } ;
1919use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
2020use rustc_middle:: ty:: fold:: TypeFoldable ;
21- use rustc_middle:: ty:: { self , Ty } ;
21+ use rustc_middle:: ty:: { self , ParamEnv , Ty } ;
2222use rustc_session:: Session ;
2323use rustc_span:: symbol:: Ident ;
2424use rustc_span:: { self , MultiSpan , Span } ;
@@ -188,33 +188,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
188188 } ;
189189
190190 // are we passing elements of a tuple without the tuple parentheses?
191- let chosen_arg_tys = if expected_input_tys. is_empty ( ) {
192- // In most cases we can use expected_arg_tys , but some callers won't have the type
191+ let expected_input_tys = if expected_input_tys. is_empty ( ) {
192+ // In most cases we can use expected_input_tys , but some callers won't have the type
193193 // information, in which case we fall back to the types from the input expressions.
194194 formal_input_tys
195195 } else {
196196 & * expected_input_tys
197197 } ;
198198
199- let sugg_tuple_wrap_args = chosen_arg_tys
200- . get ( 0 )
201- . cloned ( )
202- . map ( |arg_ty| self . resolve_vars_if_possible ( arg_ty) )
203- . and_then ( |arg_ty| match arg_ty. kind ( ) {
204- ty:: Tuple ( tup_elems) => Some ( tup_elems) ,
205- _ => None ,
206- } )
207- . and_then ( |tup_elems| {
208- if tup_elems. len ( ) == supplied_arg_count && chosen_arg_tys. len ( ) == 1 {
209- match provided_args {
210- [ ] => None ,
211- [ single] => Some ( FnArgsAsTuple :: Single ( single) ) ,
212- [ first, .., last] => Some ( FnArgsAsTuple :: Multi { first, last } ) ,
213- }
214- } else {
215- None
216- }
217- } ) ;
199+ let sugg_tuple_wrap_args = self . suggested_tuple_wrap ( expected_input_tys, provided_args) ;
218200
219201 error = Some ( (
220202 expected_arg_count,
@@ -518,6 +500,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
518500 }
519501 }
520502
503+ fn suggested_tuple_wrap (
504+ & self ,
505+ expected_input_tys : & [ Ty < ' tcx > ] ,
506+ provided_args : & ' tcx [ hir:: Expr < ' tcx > ] ,
507+ ) -> Option < FnArgsAsTuple < ' _ > > {
508+ let [ expected_arg_type] = & expected_input_tys[ ..] else { return None } ;
509+
510+ let ty:: Tuple ( expected_elems) = self . resolve_vars_if_possible ( * expected_arg_type) . kind ( )
511+ else { return None } ;
512+
513+ let expected_types: Vec < _ > = expected_elems. iter ( ) . map ( |k| k. expect_ty ( ) ) . collect ( ) ;
514+ let supplied_types: Vec < _ > = provided_args. iter ( ) . map ( |arg| self . check_expr ( arg) ) . collect ( ) ;
515+
516+ let all_match = iter:: zip ( expected_types, supplied_types)
517+ . all ( |( expected, supplied) | self . can_eq ( ParamEnv :: empty ( ) , expected, supplied) . is_ok ( ) ) ;
518+
519+ if all_match {
520+ match provided_args {
521+ [ ] => None ,
522+ [ single] => Some ( FnArgsAsTuple :: Single ( single) ) ,
523+ [ first, .., last] => Some ( FnArgsAsTuple :: Multi { first, last } ) ,
524+ }
525+ } else {
526+ None
527+ }
528+ }
529+
521530 // AST fragment checking
522531 pub ( in super :: super ) fn check_lit (
523532 & self ,
0 commit comments