Apply review suggestions
This commit is contained in:
parent
3e78653ec3
commit
6fac0fac99
6 changed files with 221 additions and 62 deletions
|
|
@ -1385,38 +1385,81 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
|
||||
fn suggest_range_struct_destructuring(
|
||||
&self,
|
||||
&mut 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;
|
||||
let Some(pat) = self.diag_metadata.current_pat else { return };
|
||||
let ast::PatKind::Range(start, end, end_kind) = &pat.kind else { return };
|
||||
|
||||
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;
|
||||
let [segment] = path else { return };
|
||||
let failing_span = segment.ident.span;
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
pat.span,
|
||||
"if you meant to destructure a `Range`, use a struct pattern",
|
||||
format!("std::ops::Range {{ start: {}, end: {} }}", start_name, end_name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
let in_start = start.as_ref().is_some_and(|e| e.span.contains(failing_span));
|
||||
let in_end = end.as_ref().is_some_and(|e| e.span.contains(failing_span));
|
||||
|
||||
if !in_start && !in_end {
|
||||
return;
|
||||
}
|
||||
|
||||
let start_snippet =
|
||||
start.as_ref().and_then(|e| self.r.tcx.sess.source_map().span_to_snippet(e.span).ok());
|
||||
let end_snippet =
|
||||
end.as_ref().and_then(|e| self.r.tcx.sess.source_map().span_to_snippet(e.span).ok());
|
||||
|
||||
let field = |name: &str, val: String| {
|
||||
if val == name { val } else { format!("{name}: {val}") }
|
||||
};
|
||||
|
||||
let mut resolve_short_name = |short: Symbol, full: &str| -> String {
|
||||
let ident = Ident::with_dummy_span(short);
|
||||
let path = Segment::from_path(&Path::from_ident(ident));
|
||||
|
||||
match self.resolve_path(&path, Some(TypeNS), None, PathSource::Type) {
|
||||
PathResult::NonModule(..) => short.to_string(),
|
||||
_ => full.to_string(),
|
||||
}
|
||||
};
|
||||
// FIXME(new_range): Also account for new range types
|
||||
let (struct_path, fields) = match (start_snippet, end_snippet, &end_kind.node) {
|
||||
(Some(start), Some(end), ast::RangeEnd::Excluded) => (
|
||||
resolve_short_name(sym::Range, "std::ops::Range"),
|
||||
vec![field("start", start), field("end", end)],
|
||||
),
|
||||
(Some(start), Some(end), ast::RangeEnd::Included(_)) => (
|
||||
resolve_short_name(sym::RangeInclusive, "std::ops::RangeInclusive"),
|
||||
vec![field("start", start), field("end", end)],
|
||||
),
|
||||
(Some(start), None, _) => (
|
||||
resolve_short_name(sym::RangeFrom, "std::ops::RangeFrom"),
|
||||
vec![field("start", start)],
|
||||
),
|
||||
(None, Some(end), ast::RangeEnd::Excluded) => {
|
||||
(resolve_short_name(sym::RangeTo, "std::ops::RangeTo"), vec![field("end", end)])
|
||||
}
|
||||
(None, Some(end), ast::RangeEnd::Included(_)) => (
|
||||
resolve_short_name(sym::RangeToInclusive, "std::ops::RangeToInclusive"),
|
||||
vec![field("end", end)],
|
||||
),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
pat.span,
|
||||
format!("if you meant to destructure a range use a struct pattern"),
|
||||
format!("{} {{ {} }}", struct_path, fields.join(", ")),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
err.note(
|
||||
"range patterns match against the start and end of a range; \
|
||||
to bind the components, use a struct pattern",
|
||||
);
|
||||
}
|
||||
|
||||
fn suggest_swapping_misplaced_self_ty_and_trait(
|
||||
|
|
|
|||
|
|
@ -4,10 +4,16 @@ error[E0425]: cannot find value `a` in this scope
|
|||
LL | [a.., a] => {}
|
||||
| ^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `a`, use the at operator
|
||||
|
|
||||
LL | [a @ .., a] => {}
|
||||
| +
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - [a.., a] => {}
|
||||
LL + [std::ops::RangeFrom { start: a }, a] => {}
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,16 @@ error[E0425]: cannot find value `rest` in this scope
|
|||
LL | [1, rest..] => println!("{rest}"),
|
||||
| ^^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `rest`, use the at operator
|
||||
|
|
||||
LL | [1, rest @ ..] => println!("{rest}"),
|
||||
| +
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - [1, rest..] => println!("{rest}"),
|
||||
LL + [1, std::ops::RangeFrom { start: rest }] => println!("{rest}"),
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `rest` in this scope
|
||||
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35
|
||||
|
|
@ -33,11 +39,17 @@ error[E0425]: cannot find value `tail` in this scope
|
|||
LL | [_, ..tail] => println!("{tail}"),
|
||||
| ^^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `tail`, use the at operator
|
||||
|
|
||||
LL - [_, ..tail] => println!("{tail}"),
|
||||
LL + [_, tail @ ..] => println!("{tail}"),
|
||||
|
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - [_, ..tail] => println!("{tail}"),
|
||||
LL + [_, std::ops::RangeTo { end: tail }] => println!("{tail}"),
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `tail` in this scope
|
||||
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35
|
||||
|
|
@ -51,11 +63,17 @@ error[E0425]: cannot find value `tail` in this scope
|
|||
LL | [_, ...tail] => println!("{tail}"),
|
||||
| ^^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `tail`, use the at operator
|
||||
|
|
||||
LL - [_, ...tail] => println!("{tail}"),
|
||||
LL + [_, tail @ ..] => println!("{tail}"),
|
||||
|
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - [_, ...tail] => println!("{tail}"),
|
||||
LL + [_, std::ops::RangeToInclusive { end: tail }] => println!("{tail}"),
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `tail` in this scope
|
||||
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:17:36
|
||||
|
|
|
|||
|
|
@ -1,15 +1,40 @@
|
|||
use std::ops::Range;
|
||||
use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
|
||||
|
||||
fn test_basic_range(r: Range<u32>) {
|
||||
fn test_range(r: Range<u32>) {
|
||||
let start..end = r;
|
||||
//~^ ERROR cannot find value `start` in this scope
|
||||
//~| ERROR cannot find value `end` in this scope
|
||||
//~^ ERROR cannot find value `start`
|
||||
//~| ERROR cannot find value `end`
|
||||
}
|
||||
|
||||
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 test_inclusive(r: RangeInclusive<u32>) {
|
||||
let start..=end = r;
|
||||
//~^ ERROR cannot find value `start`
|
||||
//~| ERROR cannot find value `end`
|
||||
}
|
||||
|
||||
fn test_from(r: RangeFrom<u32>) {
|
||||
let start.. = r;
|
||||
//~^ ERROR cannot find value `start`
|
||||
}
|
||||
|
||||
fn test_to(r: RangeTo<u32>) {
|
||||
let ..end = r;
|
||||
//~^ ERROR cannot find value `end`
|
||||
}
|
||||
|
||||
fn test_to_inclusive(r: RangeToInclusive<u32>) {
|
||||
let ..=end = r;
|
||||
//~^ ERROR cannot find value `end`
|
||||
}
|
||||
|
||||
// Case 6: Complex Path (Keep this! It works!)
|
||||
mod my {
|
||||
// We don't define MISSING here to trigger the error
|
||||
}
|
||||
fn test_path(r: Range<u32>) {
|
||||
let my::MISSING..end = r;
|
||||
//~^ ERROR cannot find value `MISSING`
|
||||
//~| ERROR cannot find value `end`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ error[E0425]: cannot find value `start` in this scope
|
|||
LL | let start..end = r;
|
||||
| ^^^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use a struct pattern
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let start..end = r;
|
||||
LL + let std::ops::Range { start: start, end: end } = r;
|
||||
LL + let Range { start, end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `end` in this scope
|
||||
|
|
@ -16,51 +17,111 @@ error[E0425]: cannot find value `end` in this scope
|
|||
LL | let start..end = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use a struct pattern
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let start..end = r;
|
||||
LL + let std::ops::Range { start: start, end: end } = r;
|
||||
LL + let Range { start, end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `min` in this scope
|
||||
error[E0425]: cannot find value `start` 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
|
||||
LL | let start..=end = r;
|
||||
| ^^^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use a struct pattern
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to destructure a range use a 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;
|
||||
LL - let start..=end = r;
|
||||
LL + let RangeInclusive { start, end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `max` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:10:14
|
||||
error[E0425]: cannot find value `end` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:10:17
|
||||
|
|
||||
LL | let min..max = r;
|
||||
| ^^^ not found in this scope
|
||||
LL | let start..=end = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
help: if you meant to destructure a `Range`, use a struct pattern
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to destructure a range use a 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;
|
||||
LL - let start..=end = r;
|
||||
LL + let RangeInclusive { start, end } = r;
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0425]: cannot find value `start` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:16:9
|
||||
|
|
||||
LL | let start.. = r;
|
||||
| ^^^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `start`, use the at operator
|
||||
|
|
||||
LL | let start @ .. = r;
|
||||
| +
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let start.. = r;
|
||||
LL + let RangeFrom { start } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `end` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:21:11
|
||||
|
|
||||
LL | let ..end = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `end`, use the at operator
|
||||
|
|
||||
LL - let ..end = r;
|
||||
LL + let end @ .. = r;
|
||||
|
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let ..end = r;
|
||||
LL + let RangeTo { end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `end` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:26:12
|
||||
|
|
||||
LL | let ..=end = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to collect the rest of the slice in `end`, use the at operator
|
||||
|
|
||||
LL - let ..=end = r;
|
||||
LL + let end @ .. = r;
|
||||
|
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let ..=end = r;
|
||||
LL + let RangeToInclusive { end } = r;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find value `MISSING` in module `my`
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:35:13
|
||||
|
|
||||
LL | let my::MISSING..end = r;
|
||||
| ^^^^^^^ not found in `my`
|
||||
|
||||
error[E0425]: cannot find value `end` in this scope
|
||||
--> $DIR/suggest-range-struct-destructuring.rs:35:22
|
||||
|
|
||||
LL | let my::MISSING..end = r;
|
||||
| ^^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let my::MISSING..end = r;
|
||||
LL + let Range { start: my::MISSING, end } = r;
|
||||
|
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
|
|
|
|||
|
|
@ -4,10 +4,16 @@ error[E0425]: cannot find value `_y` in this scope
|
|||
LL | let [_y..] = [Box::new(1), Box::new(2)];
|
||||
| ^^ not found in this scope
|
||||
|
|
||||
= note: range patterns match against the start and end of a range; to bind the components, use a struct pattern
|
||||
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)];
|
||||
| +
|
||||
help: if you meant to destructure a range use a struct pattern
|
||||
|
|
||||
LL - let [_y..] = [Box::new(1), Box::new(2)];
|
||||
LL + let [std::ops::RangeFrom { start: _y }] = [Box::new(1), Box::new(2)];
|
||||
|
|
||||
|
||||
error[E0658]: `X..` patterns in slices are experimental
|
||||
--> $DIR/issue-105946.rs:7:10
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue