On resolve error of [rest..]
, suggest [rest @ ..]
When writing a pattern to collect multiple entries of a slice in a single binding, it is easy to misremember or typo the appropriate syntax to do so, instead writing the experimental `X..` pattern syntax. When we encounter a resolve error because `X` isn't available, we suggest `X @ ..` as an alternative. ``` 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:?}"), | ^^^^ 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:?}"), | + ``` Fix #88404.
This commit is contained in:
parent
1be1e84872
commit
5c3e01a340
@ -603,6 +603,8 @@ struct DiagnosticMetadata<'ast> {
|
|||||||
/// Only used for better errors on `let <pat>: <expr, not type>;`.
|
/// Only used for better errors on `let <pat>: <expr, not type>;`.
|
||||||
current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
|
current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
|
||||||
|
|
||||||
|
current_pat: Option<&'ast Pat>,
|
||||||
|
|
||||||
/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
|
/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
|
||||||
in_if_condition: Option<&'ast Expr>,
|
in_if_condition: Option<&'ast Expr>,
|
||||||
|
|
||||||
@ -703,6 +705,12 @@ fn visit_anon_const(&mut self, _constant: &'ast AnonConst) {
|
|||||||
fn visit_expr(&mut self, expr: &'ast Expr) {
|
fn visit_expr(&mut self, expr: &'ast Expr) {
|
||||||
self.resolve_expr(expr, None);
|
self.resolve_expr(expr, None);
|
||||||
}
|
}
|
||||||
|
fn visit_pat(&mut self, p: &'ast Pat) {
|
||||||
|
let prev = self.diagnostic_metadata.current_pat;
|
||||||
|
self.diagnostic_metadata.current_pat = Some(p);
|
||||||
|
visit::walk_pat(self, p);
|
||||||
|
self.diagnostic_metadata.current_pat = prev;
|
||||||
|
}
|
||||||
fn visit_local(&mut self, local: &'ast Local) {
|
fn visit_local(&mut self, local: &'ast Local) {
|
||||||
let local_spans = match local.pat.kind {
|
let local_spans = match local.pat.kind {
|
||||||
// We check for this to avoid tuple struct fields.
|
// We check for this to avoid tuple struct fields.
|
||||||
|
@ -431,6 +431,7 @@ pub(crate) fn smart_resolve_report_errors(
|
|||||||
code,
|
code,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
|
||||||
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
|
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
|
||||||
|
|
||||||
if let Some((span, label)) = base_error.span_label {
|
if let Some((span, label)) = base_error.span_label {
|
||||||
@ -1063,6 +1064,32 @@ fn suggest_self_value(
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn suggest_at_operator_in_slice_pat_with_range(
|
||||||
|
&mut self,
|
||||||
|
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 [segment] = &range_path.segments[..]
|
||||||
|
&& let [s] = path
|
||||||
|
&& segment.ident == s.ident
|
||||||
|
{
|
||||||
|
// 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn suggest_swapping_misplaced_self_ty_and_trait(
|
fn suggest_swapping_misplaced_self_ty_and_trait(
|
||||||
&mut self,
|
&mut self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -3,6 +3,11 @@ error[E0425]: cannot find value `a` in this scope
|
|||||||
|
|
|
|
||||||
LL | [a.., a] => {}
|
LL | [a.., a] => {}
|
||||||
| ^ not found in this scope
|
| ^ not found in this scope
|
||||||
|
|
|
||||||
|
help: if you meant to collect the rest of the slice in `a`, use the at operator
|
||||||
|
|
|
||||||
|
LL | [a @ .., a] => {}
|
||||||
|
| +
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
fn main() {
|
||||||
|
match &[1, 2, 3][..] {
|
||||||
|
[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
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
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:?}"),
|
||||||
|
| ^^^^ 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:?}"),
|
||||||
|
| +
|
||||||
|
|
||||||
|
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:?}"),
|
||||||
|
| ^^^^ 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:?}"),
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= 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
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0425, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0425`.
|
@ -3,6 +3,11 @@ error[E0425]: cannot find value `_y` in this scope
|
|||||||
|
|
|
|
||||||
LL | let [_y..] = [Box::new(1), Box::new(2)];
|
LL | let [_y..] = [Box::new(1), Box::new(2)];
|
||||||
| ^^ not found in this scope
|
| ^^ not found in this scope
|
||||||
|
|
|
||||||
|
help: if you meant to collect the rest of the slice in `_y`, use the at operator
|
||||||
|
|
|
||||||
|
LL | let [_y @ ..] = [Box::new(1), Box::new(2)];
|
||||||
|
| +
|
||||||
|
|
||||||
error[E0658]: `X..` patterns in slices are experimental
|
error[E0658]: `X..` patterns in slices are experimental
|
||||||
--> $DIR/issue-105946.rs:6:10
|
--> $DIR/issue-105946.rs:6:10
|
||||||
|
Loading…
Reference in New Issue
Block a user