Suggest struct pattern when destructuring Range with .. syntax
This commit is contained in:
parent
f2c70877a7
commit
cb301751b3
3 changed files with 117 additions and 0 deletions
|
|
@ -440,6 +440,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
|
||||
self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg);
|
||||
self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
|
||||
self.suggest_range_struct_destructuring(&mut err, path, source);
|
||||
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
|
||||
|
||||
if let Some((span, label)) = base_error.span_label {
|
||||
|
|
@ -1383,6 +1384,41 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn suggest_range_struct_destructuring(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
path: &[Segment],
|
||||
source: PathSource<'_, '_, '_>,
|
||||
) {
|
||||
// We accept Expr here because range bounds (start..end) are parsed as expressions
|
||||
if !matches!(source, PathSource::Pat | PathSource::TupleStruct(..) | PathSource::Expr(..)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(pat) = self.diag_metadata.current_pat
|
||||
&& let ast::PatKind::Range(Some(start_expr), Some(end_expr), _) = &pat.kind
|
||||
&& let (ast::ExprKind::Path(None, start_path), ast::ExprKind::Path(None, end_path)) =
|
||||
(&start_expr.kind, &end_expr.kind)
|
||||
&& path.len() == 1
|
||||
{
|
||||
let ident = path[0].ident;
|
||||
|
||||
if (start_path.segments.len() == 1 && start_path.segments[0].ident == ident)
|
||||
|| (end_path.segments.len() == 1 && end_path.segments[0].ident == ident)
|
||||
{
|
||||
let start_name = start_path.segments[0].ident;
|
||||
let end_name = end_path.segments[0].ident;
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
pat.span,
|
||||
"if you meant to destructure a `Range`, use the struct pattern",
|
||||
format!("std::ops::Range {{ start: {}, end: {} }}", start_name, end_name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_swapping_misplaced_self_ty_and_trait(
|
||||
&mut self,
|
||||
err: &mut Diag<'_>,
|
||||
|
|
|
|||
15
tests/ui/resolve/suggest-range-struct-destructuring.rs
Normal file
15
tests/ui/resolve/suggest-range-struct-destructuring.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use std::ops::Range;
|
||||
|
||||
fn test_basic_range(r: Range<u32>) {
|
||||
let start..end = r;
|
||||
//~^ ERROR cannot find value `start` in this scope
|
||||
//~| ERROR cannot find value `end` in this scope
|
||||
}
|
||||
|
||||
fn test_different_names(r: Range<u32>) {
|
||||
let min..max = r;
|
||||
//~^ ERROR cannot find value `min` in this scope
|
||||
//~| ERROR cannot find value `max` in this scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
66
tests/ui/resolve/suggest-range-struct-destructuring.stderr
Normal file
66
tests/ui/resolve/suggest-range-struct-destructuring.stderr
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
error[E0425]: cannot find value `start` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:4:9
|
||||
|
|
||||
LL | let start..end = r;
|
||||
| ^^^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use the struct pattern
|
||||
|
|
||||
LL - let start..end = r;
|
||||
LL + let std::ops::Range { start: start, end: end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `end` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:4:16
|
||||
|
|
||||
LL | let start..end = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use the struct pattern
|
||||
|
|
||||
LL - let start..end = r;
|
||||
LL + let std::ops::Range { start: start, end: end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `min` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:10:9
|
||||
|
|
||||
LL | let min..max = r;
|
||||
| ^^^
|
||||
...
|
||||
LL | fn main() {}
|
||||
| --------- similarly named function `main` defined here
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use the struct pattern
|
||||
|
|
||||
LL - let min..max = r;
|
||||
LL + let std::ops::Range { start: min, end: max } = r;
|
||||
|
|
||||
help: a function with a similar name exists
|
||||
|
|
||||
LL | let main..max = r;
|
||||
| +
|
||||
help: consider importing this function
|
||||
|
|
||||
LL + use std::cmp::min;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `max` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:10:14
|
||||
|
|
||||
LL | let min..max = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use the struct pattern
|
||||
|
|
||||
LL - let min..max = r;
|
||||
LL + let std::ops::Range { start: min, end: max } = r;
|
||||
|
|
||||
help: consider importing this function
|
||||
|
|
||||
LL + use std::cmp::max;
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue