about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2021-01-26 16:53:56 -0800
committerEsteban Küber <esteban@kuber.com.ar>2021-01-26 16:53:56 -0800
commita398994cb214c9ba022cb8e6cd97c3fee4bca6ac (patch)
tree688c321cd6a68839c6e39bfd1e2d46c312b59ec5
parent7907345e58b4f4d2c95e5ea9b8e0b3bff8946523 (diff)
downloadrust-a398994cb214c9ba022cb8e6cd97c3fee4bca6ac.tar.gz
rust-a398994cb214c9ba022cb8e6cd97c3fee4bca6ac.zip
Account for existing `_` field pattern when suggesting `..`
Follow up to #80017.
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs22
-rw-r--r--src/test/ui/pattern/pat-tuple-underfield.stderr4
2 files changed, 17 insertions, 9 deletions
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 79234f076ac..12256058b87 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1041,12 +1041,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())],
                 Applicability::MachineApplicable,
             );
-        } else if fields.len() > subpats.len() {
-            let after_fields_span = if pat_span == DUMMY_SP {
-                pat_span
-            } else {
-                pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi()
-            };
+        } else if fields.len() > subpats.len() && pat_span != DUMMY_SP {
+            let after_fields_span = pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi();
             let all_fields_span = match subpats {
                 [] => after_fields_span,
                 [field] => field.span,
@@ -1055,7 +1051,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // Check if all the fields in the pattern are wildcards.
             let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild));
+            let first_tail_wildcard =
+                subpats.iter().enumerate().fold(None, |acc, (pos, pat)| match (acc, &pat.kind) {
+                    (None, PatKind::Wild) => Some(pos),
+                    (Some(_), PatKind::Wild) => acc,
+                    _ => None,
+                });
+            let tail_span = match first_tail_wildcard {
+                None => after_fields_span,
+                Some(0) => subpats[0].span.to(after_fields_span),
+                Some(pos) => subpats[pos - 1].span.shrink_to_hi().to(after_fields_span),
+            };
 
+            // FIXME: heuristic-based suggestion to check current types for where to add `_`.
             let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", ");
             if !subpats.is_empty() {
                 wildcard_sugg = String::from(", ") + &wildcard_sugg;
@@ -1080,7 +1088,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                 } else {
                     err.span_suggestion_verbose(
-                        after_fields_span,
+                        tail_span,
                         "use `..` to ignore the rest of the fields",
                         String::from(", .."),
                         Applicability::MaybeIncorrect,
diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr
index 76323d9a7bf..70c21dbafe9 100644
--- a/src/test/ui/pattern/pat-tuple-underfield.stderr
+++ b/src/test/ui/pattern/pat-tuple-underfield.stderr
@@ -122,8 +122,8 @@ LL |         Point4(   a   ,     _    , _, _) => {}
    |                                  ^^^^^^
 help: use `..` to ignore the rest of the fields
    |
-LL |         Point4(   a   ,     _    , ..) => {}
-   |                                  ^^^^
+LL |         Point4(   a, ..) => {}
+   |                    ^^^^
 
 error: aborting due to 8 previous errors