let mut slice = None;
let mut prev_rest_span = None;
+ // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
+ let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
+ let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
+ let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
+ this.pat_with_node_id_of(pat, node)
+ };
+
let mut iter = pats.iter();
// Lower all the patterns until the first occurrence of a sub-slice pattern.
for pat in iter.by_ref() {
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
prev_rest_span = Some(sub.span);
- let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
- let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
- slice = Some(self.pat_with_node_id_of(pat, node));
+ slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
break;
}
// It was not a subslice pattern so lower it normally.
// There was a previous subslice pattern; make sure we don't allow more.
let rest_span = match pat.kind {
PatKind::Rest => Some(pat.span),
- PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
- // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
- after.push(self.pat_wild_with_node_id_of(pat));
+ PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
+ // #69103: Lower into `binding @ _` as above to avoid ICEs.
+ after.push(lower_rest_sub(self, pat, bm, ident, sub));
Some(sub.span)
}
_ => None,
--- /dev/null
+// We used to not lower the extra `b @ ..` into `b @ _` which meant that no type
+// was registered for the binding `b` although it passed through resolve.
+// This resulted in an ICE (#69103).
+
+fn main() {
+ let [a @ .., b @ ..] = &mut [1, 2];
+ //~^ ERROR `..` can only be used once per slice pattern
+ b;
+
+ let [.., c @ ..] = [1, 2];
+ //~^ ERROR `..` can only be used once per slice pattern
+ c;
+
+ // This never ICEd, but let's make sure it won't regress either.
+ let (.., d @ ..) = (1, 2);
+ //~^ ERROR `..` patterns are not allowed here
+ d;
+}
--- /dev/null
+error: `..` can only be used once per slice pattern
+ --> $DIR/issue-69103-extra-binding-subslice.rs:6:22
+ |
+LL | let [a @ .., b @ ..] = &mut [1, 2];
+ | -- ^^ can only be used once per slice pattern
+ | |
+ | previously used here
+
+error: `..` can only be used once per slice pattern
+ --> $DIR/issue-69103-extra-binding-subslice.rs:10:18
+ |
+LL | let [.., c @ ..] = [1, 2];
+ | -- ^^ can only be used once per slice pattern
+ | |
+ | previously used here
+
+error: `..` patterns are not allowed here
+ --> $DIR/issue-69103-extra-binding-subslice.rs:15:18
+ |
+LL | let (.., d @ ..) = (1, 2);
+ | ^^
+ |
+ = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: aborting due to 3 previous errors
+