@@ -15,6 +15,7 @@ use rustc_span::hygiene::DesugaringKind;
15
15
use rustc_span:: lev_distance:: find_best_match_for_name;
16
16
use rustc_span:: source_map:: { Span , Spanned } ;
17
17
use rustc_span:: symbol:: Ident ;
18
+ use rustc_span:: { BytePos , DUMMY_SP } ;
18
19
use rustc_trait_selection:: traits:: { ObligationCause , Pattern } ;
19
20
20
21
use std:: cmp;
@@ -1001,7 +1002,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1001
1002
// More generally, the expected type wants a tuple variant with one field of an
1002
1003
// N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
1003
1004
// with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
1004
- let missing_parenthesis = match ( & expected. kind ( ) , fields, had_err) {
1005
+ let missing_parentheses = match ( & expected. kind ( ) , fields, had_err) {
1005
1006
// #67037: only do this if we could successfully type-check the expected type against
1006
1007
// the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
1007
1008
// `let P() = U;` where `P != U` with `struct P<T>(T);`.
@@ -1014,13 +1015,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1014
1015
}
1015
1016
_ => false ,
1016
1017
} ;
1017
- if missing_parenthesis {
1018
+ if missing_parentheses {
1018
1019
let ( left, right) = match subpats {
1019
1020
// This is the zero case; we aim to get the "hi" part of the `QPath`'s
1020
1021
// span as the "lo" and then the "hi" part of the pattern's span as the "hi".
1021
1022
// This looks like:
1022
1023
//
1023
- // help: missing parenthesis
1024
+ // help: missing parentheses
1024
1025
// |
1025
1026
// L | let A(()) = A(());
1026
1027
// | ^ ^
@@ -1029,17 +1030,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1029
1030
// last sub-pattern. In the case of `A(x)` the first and last may coincide.
1030
1031
// This looks like:
1031
1032
//
1032
- // help: missing parenthesis
1033
+ // help: missing parentheses
1033
1034
// |
1034
1035
// L | let A((x, y)) = A((1, 2));
1035
1036
// | ^ ^
1036
1037
[ first, ..] => ( first. span . shrink_to_lo ( ) , subpats. last ( ) . unwrap ( ) . span ) ,
1037
1038
} ;
1038
1039
err. multipart_suggestion (
1039
- "missing parenthesis " ,
1040
+ "missing parentheses " ,
1040
1041
vec ! [ ( left, "(" . to_string( ) ) , ( right. shrink_to_hi( ) , ")" . to_string( ) ) ] ,
1041
1042
Applicability :: MachineApplicable ,
1042
1043
) ;
1044
+ } else if fields. len ( ) > subpats. len ( ) {
1045
+ let after_fields_span = if pat_span == DUMMY_SP {
1046
+ pat_span
1047
+ } else {
1048
+ pat_span. with_hi ( pat_span. hi ( ) - BytePos ( 1 ) ) . shrink_to_hi ( )
1049
+ } ;
1050
+ let all_fields_span = match subpats {
1051
+ [ ] => after_fields_span,
1052
+ [ field] => field. span ,
1053
+ [ first, .., last] => first. span . to ( last. span ) ,
1054
+ } ;
1055
+
1056
+ // Check if all the fields in the pattern are wildcards.
1057
+ let all_wildcards = subpats. iter ( ) . all ( |pat| matches ! ( pat. kind, PatKind :: Wild ) ) ;
1058
+
1059
+ let mut wildcard_sugg = vec ! [ "_" ; fields. len( ) - subpats. len( ) ] . join ( ", " ) ;
1060
+ if !subpats. is_empty ( ) {
1061
+ wildcard_sugg = String :: from ( ", " ) + & wildcard_sugg;
1062
+ }
1063
+
1064
+ err. span_suggestion_verbose (
1065
+ after_fields_span,
1066
+ "use `_` to explicitly ignore each field" ,
1067
+ wildcard_sugg,
1068
+ Applicability :: MaybeIncorrect ,
1069
+ ) ;
1070
+
1071
+ // Only suggest `..` if more than one field is missing
1072
+ // or the pattern consists of all wildcards.
1073
+ if fields. len ( ) - subpats. len ( ) > 1 || all_wildcards {
1074
+ if subpats. is_empty ( ) || all_wildcards {
1075
+ err. span_suggestion_verbose (
1076
+ all_fields_span,
1077
+ "use `..` to ignore all fields" ,
1078
+ String :: from ( ".." ) ,
1079
+ Applicability :: MaybeIncorrect ,
1080
+ ) ;
1081
+ } else {
1082
+ err. span_suggestion_verbose (
1083
+ after_fields_span,
1084
+ "use `..` to ignore the rest of the fields" ,
1085
+ String :: from ( ", .." ) ,
1086
+ Applicability :: MaybeIncorrect ,
1087
+ ) ;
1088
+ }
1089
+ }
1043
1090
}
1044
1091
1045
1092
err. emit ( ) ;
0 commit comments