Skip to content

Commit

Permalink
Rollup merge of rust-lang#120597 - fmease:sugg-on-js-style-spread-op-…
Browse files Browse the repository at this point in the history
…in-pat, r=estebank

Suggest `[tail @ ..]` on `[..tail]` and `[...tail]` where `tail` is unresolved

Fixes rust-lang#120591.
~~Will conflict with rust-lang#120570~~ (rebased).

r? estebank or compiler
  • Loading branch information
matthiaskrgr committed Feb 6, 2024
2 parents a55fdcc + 285d8c2 commit fae1071
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 20 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here =
resolve_unexpected_res_change_ty_to_const_param_sugg =
you might have meant to write a const parameter here
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
if you meant to collect the rest of the slice in `{$ident}`, use the at operator
resolve_unreachable_label =
use of unreachable label `{$name}`
.label = unreachable label `{$name}`
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,3 +800,17 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
#[applicability]
pub applicability: Applicability,
}

#[derive(Subdiagnostic)]
#[suggestion(
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg,
code = "{snippet}",
applicability = "maybe-incorrect",
style = "verbose"
)]
pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg {
#[primary_span]
pub span: Span,
pub ident: Ident,
pub snippet: String,
}
38 changes: 24 additions & 14 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,24 +1077,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
err: &mut Diagnostic,
path: &[Segment],
) {
if let Some(pat) = self.diagnostic_metadata.current_pat
&& let ast::PatKind::Range(Some(start), None, range) = &pat.kind
&& let ExprKind::Path(None, range_path) = &start.kind
let Some(pat) = self.diagnostic_metadata.current_pat else { return };
let (bound, side, range) = match &pat.kind {
ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range),
ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range),
_ => return,
};
if let ExprKind::Path(None, range_path) = &bound.kind
&& let [segment] = &range_path.segments[..]
&& let [s] = path
&& segment.ident == s.ident
&& segment.ident.span.eq_ctxt(range.span)
{
// We've encountered `[first, rest..]` where the user might have meant
// `[first, rest @ ..]` (#88404).
err.span_suggestion_verbose(
segment.ident.span.between(range.span),
format!(
"if you meant to collect the rest of the slice in `{}`, use the at operator",
segment.ident,
),
" @ ",
Applicability::MaybeIncorrect,
);
// We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591)
// where the user might have meant `[first, rest @ ..]`.
let (span, snippet) = match side {
Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
};
err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
span,
ident: segment.ident,
snippet,
});
}

enum Side {
Start,
End,
}
}

Expand Down
16 changes: 15 additions & 1 deletion tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
fn main() {
match &[1, 2, 3][..] {
[1, rest..] => println!("{rest:?}"),
[1, rest..] => println!("{rest}"),
//~^ ERROR cannot find value `rest` in this scope
//~| ERROR cannot find value `rest` in this scope
//~| ERROR `X..` patterns in slices are experimental
_ => {}
}
match &[4, 5, 6][..] {
[] => {}
[_, ..tail] => println!("{tail}"),
//~^ ERROR cannot find value `tail` in this scope
//~| ERROR cannot find value `tail` in this scope
//~| ERROR exclusive range pattern syntax is experimental
}
match &[7, 8, 9][..] {
[] => {}
[_, ...tail] => println!("{tail}"),
//~^ ERROR cannot find value `tail` in this scope
//~| ERROR cannot find value `tail` in this scope
//~| ERROR range-to patterns with `...` are not allowed
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,82 @@
error: range-to patterns with `...` are not allowed
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13
|
LL | [_, ...tail] => println!("{tail}"),
| ^^^ help: use `..=` instead

error[E0425]: cannot find value `rest` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
|
LL | [1, rest..] => println!("{rest:?}"),
LL | [1, rest..] => println!("{rest}"),
| ^^^^ not found in this scope
|
help: if you meant to collect the rest of the slice in `rest`, use the at operator
|
LL | [1, rest @ ..] => println!("{rest:?}"),
LL | [1, rest @ ..] => println!("{rest}"),
| +

error[E0425]: cannot find value `rest` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35
|
LL | [1, rest..] => println!("{rest:?}"),
LL | [1, rest..] => println!("{rest}"),
| ^^^^ not found in this scope

error[E0425]: cannot find value `tail` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:15
|
LL | [_, ..tail] => println!("{tail}"),
| ^^^^ not found in this scope
|
help: if you meant to collect the rest of the slice in `tail`, use the at operator
|
LL | [_, tail @ ..] => println!("{tail}"),
| ~~~~~~~~~

error[E0425]: cannot find value `tail` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35
|
LL | [_, ..tail] => println!("{tail}"),
| ^^^^ not found in this scope

error[E0425]: cannot find value `tail` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16
|
LL | [_, ...tail] => println!("{tail}"),
| ^^^^ not found in this scope
|
help: if you meant to collect the rest of the slice in `tail`, use the at operator
|
LL | [_, tail @ ..] => println!("{tail}"),
| ~~~~~~~~~

error[E0425]: cannot find value `tail` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36
|
LL | [_, ...tail] => println!("{tail}"),
| ^^^^ not found in this scope

error[E0658]: `X..` patterns in slices are experimental
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
|
LL | [1, rest..] => println!("{rest:?}"),
LL | [1, rest..] => println!("{rest}"),
| ^^^^^^
|
= note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
= help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

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

error: aborting due to 9 previous errors

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

0 comments on commit fae1071

Please sign in to comment.