Skip to content

Commit fae1071

Browse files
authored
Rollup merge of #120597 - fmease:sugg-on-js-style-spread-op-in-pat, r=estebank
Suggest `[tail @ ..]` on `[..tail]` and `[...tail]` where `tail` is unresolved Fixes #120591. ~~Will conflict with #120570~~ (rebased). r? estebank or compiler
2 parents a55fdcc + 285d8c2 commit fae1071

File tree

5 files changed

+112
-20
lines changed

5 files changed

+112
-20
lines changed

compiler/rustc_resolve/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here =
292292
resolve_unexpected_res_change_ty_to_const_param_sugg =
293293
you might have meant to write a const parameter here
294294
295+
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
296+
if you meant to collect the rest of the slice in `{$ident}`, use the at operator
297+
295298
resolve_unreachable_label =
296299
use of unreachable label `{$name}`
297300
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/errors.rs

+14
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,17 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
800800
#[applicability]
801801
pub applicability: Applicability,
802802
}
803+
804+
#[derive(Subdiagnostic)]
805+
#[suggestion(
806+
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg,
807+
code = "{snippet}",
808+
applicability = "maybe-incorrect",
809+
style = "verbose"
810+
)]
811+
pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg {
812+
#[primary_span]
813+
pub span: Span,
814+
pub ident: Ident,
815+
pub snippet: String,
816+
}

compiler/rustc_resolve/src/late/diagnostics.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -1077,24 +1077,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
10771077
err: &mut Diagnostic,
10781078
path: &[Segment],
10791079
) {
1080-
if let Some(pat) = self.diagnostic_metadata.current_pat
1081-
&& let ast::PatKind::Range(Some(start), None, range) = &pat.kind
1082-
&& let ExprKind::Path(None, range_path) = &start.kind
1080+
let Some(pat) = self.diagnostic_metadata.current_pat else { return };
1081+
let (bound, side, range) = match &pat.kind {
1082+
ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range),
1083+
ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range),
1084+
_ => return,
1085+
};
1086+
if let ExprKind::Path(None, range_path) = &bound.kind
10831087
&& let [segment] = &range_path.segments[..]
10841088
&& let [s] = path
10851089
&& segment.ident == s.ident
1090+
&& segment.ident.span.eq_ctxt(range.span)
10861091
{
1087-
// We've encountered `[first, rest..]` where the user might have meant
1088-
// `[first, rest @ ..]` (#88404).
1089-
err.span_suggestion_verbose(
1090-
segment.ident.span.between(range.span),
1091-
format!(
1092-
"if you meant to collect the rest of the slice in `{}`, use the at operator",
1093-
segment.ident,
1094-
),
1095-
" @ ",
1096-
Applicability::MaybeIncorrect,
1097-
);
1092+
// We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591)
1093+
// where the user might have meant `[first, rest @ ..]`.
1094+
let (span, snippet) = match side {
1095+
Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
1096+
Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
1097+
};
1098+
err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
1099+
span,
1100+
ident: segment.ident,
1101+
snippet,
1102+
});
1103+
}
1104+
1105+
enum Side {
1106+
Start,
1107+
End,
10981108
}
10991109
}
11001110

Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
fn main() {
22
match &[1, 2, 3][..] {
3-
[1, rest..] => println!("{rest:?}"),
3+
[1, rest..] => println!("{rest}"),
44
//~^ ERROR cannot find value `rest` in this scope
55
//~| ERROR cannot find value `rest` in this scope
66
//~| ERROR `X..` patterns in slices are experimental
77
_ => {}
88
}
9+
match &[4, 5, 6][..] {
10+
[] => {}
11+
[_, ..tail] => println!("{tail}"),
12+
//~^ ERROR cannot find value `tail` in this scope
13+
//~| ERROR cannot find value `tail` in this scope
14+
//~| ERROR exclusive range pattern syntax is experimental
15+
}
16+
match &[7, 8, 9][..] {
17+
[] => {}
18+
[_, ...tail] => println!("{tail}"),
19+
//~^ ERROR cannot find value `tail` in this scope
20+
//~| ERROR cannot find value `tail` in this scope
21+
//~| ERROR range-to patterns with `...` are not allowed
22+
}
923
}
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,82 @@
1+
error: range-to patterns with `...` are not allowed
2+
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13
3+
|
4+
LL | [_, ...tail] => println!("{tail}"),
5+
| ^^^ help: use `..=` instead
6+
17
error[E0425]: cannot find value `rest` in this scope
28
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
39
|
4-
LL | [1, rest..] => println!("{rest:?}"),
10+
LL | [1, rest..] => println!("{rest}"),
511
| ^^^^ not found in this scope
612
|
713
help: if you meant to collect the rest of the slice in `rest`, use the at operator
814
|
9-
LL | [1, rest @ ..] => println!("{rest:?}"),
15+
LL | [1, rest @ ..] => println!("{rest}"),
1016
| +
1117

1218
error[E0425]: cannot find value `rest` in this scope
1319
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35
1420
|
15-
LL | [1, rest..] => println!("{rest:?}"),
21+
LL | [1, rest..] => println!("{rest}"),
22+
| ^^^^ not found in this scope
23+
24+
error[E0425]: cannot find value `tail` in this scope
25+
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:15
26+
|
27+
LL | [_, ..tail] => println!("{tail}"),
28+
| ^^^^ not found in this scope
29+
|
30+
help: if you meant to collect the rest of the slice in `tail`, use the at operator
31+
|
32+
LL | [_, tail @ ..] => println!("{tail}"),
33+
| ~~~~~~~~~
34+
35+
error[E0425]: cannot find value `tail` in this scope
36+
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35
37+
|
38+
LL | [_, ..tail] => println!("{tail}"),
1639
| ^^^^ not found in this scope
1740

41+
error[E0425]: cannot find value `tail` in this scope
42+
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16
43+
|
44+
LL | [_, ...tail] => println!("{tail}"),
45+
| ^^^^ not found in this scope
46+
|
47+
help: if you meant to collect the rest of the slice in `tail`, use the at operator
48+
|
49+
LL | [_, tail @ ..] => println!("{tail}"),
50+
| ~~~~~~~~~
51+
52+
error[E0425]: cannot find value `tail` in this scope
53+
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36
54+
|
55+
LL | [_, ...tail] => println!("{tail}"),
56+
| ^^^^ not found in this scope
57+
1858
error[E0658]: `X..` patterns in slices are experimental
1959
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
2060
|
21-
LL | [1, rest..] => println!("{rest:?}"),
61+
LL | [1, rest..] => println!("{rest}"),
2262
| ^^^^^^
2363
|
2464
= note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
2565
= help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
2666
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2767

28-
error: aborting due to 3 previous errors
68+
error[E0658]: exclusive range pattern syntax is experimental
69+
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:13
70+
|
71+
LL | [_, ..tail] => println!("{tail}"),
72+
| ^^^^^^
73+
|
74+
= note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
75+
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
76+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
77+
= help: use an inclusive range pattern, like N..=M
78+
79+
error: aborting due to 9 previous errors
2980

3081
Some errors have detailed explanations: E0425, E0658.
3182
For more information about an error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)