@@ -18,7 +18,7 @@ use rustc_hir::def_id::DefId;
18
18
use rustc_hir:: { ExprKind , Node , QPath } ;
19
19
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
20
20
use rustc_middle:: ty:: fold:: TypeFoldable ;
21
- use rustc_middle:: ty:: { self , Ty } ;
21
+ use rustc_middle:: ty:: { self , ParamEnv , Ty } ;
22
22
use rustc_session:: Session ;
23
23
use rustc_span:: symbol:: Ident ;
24
24
use rustc_span:: { self , MultiSpan , Span } ;
@@ -188,33 +188,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
188
188
} ;
189
189
190
190
// 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
193
193
// information, in which case we fall back to the types from the input expressions.
194
194
formal_input_tys
195
195
} else {
196
196
& * expected_input_tys
197
197
} ;
198
198
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) ;
218
200
219
201
error = Some ( (
220
202
expected_arg_count,
@@ -518,6 +500,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
518
500
}
519
501
}
520
502
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
+
521
530
// AST fragment checking
522
531
pub ( in super :: super ) fn check_lit (
523
532
& self ,
0 commit comments