Skip to content

Commit f5bd964

Browse files
committed
fix extra subslice lowering
1 parent 2e6eace commit f5bd964

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

src/librustc_ast_lowering/pat.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
128128
let mut slice = None;
129129
let mut prev_rest_span = None;
130130

131+
// Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
132+
let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
133+
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
134+
let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
135+
this.pat_with_node_id_of(pat, node)
136+
};
137+
131138
let mut iter = pats.iter();
132139
// Lower all the patterns until the first occurrence of a sub-slice pattern.
133140
for pat in iter.by_ref() {
@@ -142,9 +149,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
142149
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
143150
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
144151
prev_rest_span = Some(sub.span);
145-
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
146-
let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
147-
slice = Some(self.pat_with_node_id_of(pat, node));
152+
slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
148153
break;
149154
}
150155
// It was not a subslice pattern so lower it normally.
@@ -157,9 +162,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
157162
// There was a previous subslice pattern; make sure we don't allow more.
158163
let rest_span = match pat.kind {
159164
PatKind::Rest => Some(pat.span),
160-
PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
161-
// The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
162-
after.push(self.pat_wild_with_node_id_of(pat));
165+
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
166+
// #69103: Lower into `binding @ _` as above to avoid ICEs.
167+
after.push(lower_rest_sub(self, pat, bm, ident, sub));
163168
Some(sub.span)
164169
}
165170
_ => None,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// We used to not lower the extra `b @ ..` into `b @ _` which meant that no type
2+
// was registered for the binding `b` although it passed through resolve.
3+
// This resulted in an ICE (#69103).
4+
5+
fn main() {
6+
let [a @ .., b @ ..] = &mut [1, 2];
7+
//~^ ERROR `..` can only be used once per slice pattern
8+
b;
9+
10+
let [.., c @ ..] = [1, 2];
11+
//~^ ERROR `..` can only be used once per slice pattern
12+
c;
13+
14+
// This never ICEd, but let's make sure it won't regress either.
15+
let (.., d @ ..) = (1, 2);
16+
//~^ ERROR `..` patterns are not allowed here
17+
d;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `..` can only be used once per slice pattern
2+
--> $DIR/issue-69103-extra-binding-subslice.rs:6:22
3+
|
4+
LL | let [a @ .., b @ ..] = &mut [1, 2];
5+
| -- ^^ can only be used once per slice pattern
6+
| |
7+
| previously used here
8+
9+
error: `..` can only be used once per slice pattern
10+
--> $DIR/issue-69103-extra-binding-subslice.rs:10:18
11+
|
12+
LL | let [.., c @ ..] = [1, 2];
13+
| -- ^^ can only be used once per slice pattern
14+
| |
15+
| previously used here
16+
17+
error: `..` patterns are not allowed here
18+
--> $DIR/issue-69103-extra-binding-subslice.rs:15:18
19+
|
20+
LL | let (.., d @ ..) = (1, 2);
21+
| ^^
22+
|
23+
= note: only allowed in tuple, tuple struct, and slice patterns
24+
25+
error: aborting due to 3 previous errors
26+

0 commit comments

Comments
 (0)