mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Handle other projection kinds
This commit is contained in:
parent
97783a8cb9
commit
91dd9c46de
@ -220,7 +220,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||||||
let ident_str = map.name(id).to_string();
|
let ident_str = map.name(id).to_string();
|
||||||
let span = map.span(cmt.hir_id);
|
let span = map.span(cmt.hir_id);
|
||||||
let start_span = Span::new(self.next_pos, span.lo(), span.ctxt());
|
let start_span = Span::new(self.next_pos, span.lo(), span.ctxt());
|
||||||
let start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
||||||
|
|
||||||
if cmt.place.projections.is_empty() {
|
if cmt.place.projections.is_empty() {
|
||||||
// handle item without any projection, that needs an explicit borrowing
|
// handle item without any projection, that needs an explicit borrowing
|
||||||
@ -255,19 +255,75 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||||||
// handle item projections by removing one explicit deref
|
// handle item projections by removing one explicit deref
|
||||||
// i.e.: suggest `*x` instead of `**x`
|
// i.e.: suggest `*x` instead of `**x`
|
||||||
let mut replacement_str = ident_str;
|
let mut replacement_str = ident_str;
|
||||||
let last_deref = cmt
|
|
||||||
.place
|
|
||||||
.projections
|
|
||||||
.iter()
|
|
||||||
.rposition(|proj| proj.kind == ProjectionKind::Deref);
|
|
||||||
|
|
||||||
if let Some(pos) = last_deref {
|
// handle index projection first
|
||||||
let mut projections = cmt.place.projections.clone();
|
let index_handled = cmt.place.projections.iter().any(|proj| match proj.kind {
|
||||||
projections.truncate(pos);
|
// Index projection like `|x| foo[x]`
|
||||||
|
// the index is dropped so we can't get it to build the suggestion,
|
||||||
|
// so the span is set-up again to get more code, using `span.hi()` (i.e.: `foo[x]`)
|
||||||
|
// instead of `span.lo()` (i.e.: `foo`)
|
||||||
|
ProjectionKind::Index => {
|
||||||
|
let start_span = Span::new(self.next_pos, span.hi(), span.ctxt());
|
||||||
|
start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
||||||
|
replacement_str.clear();
|
||||||
|
true
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
|
||||||
for item in projections {
|
// looking for projections other that need to be handled differently
|
||||||
if item.kind == ProjectionKind::Deref {
|
let other_projections_handled = cmt.place.projections.iter().enumerate().any(|(i, proj)| {
|
||||||
replacement_str = format!("*{}", replacement_str);
|
match proj.kind {
|
||||||
|
// Field projection like `|v| v.foo`
|
||||||
|
ProjectionKind::Field(idx, variant) => match cmt.place.ty_before_projection(i).kind() {
|
||||||
|
ty::Adt(def, ..) => {
|
||||||
|
replacement_str = format!(
|
||||||
|
"{}.{}",
|
||||||
|
replacement_str,
|
||||||
|
def.variants[variant].fields[idx as usize].ident.name.as_str()
|
||||||
|
);
|
||||||
|
true
|
||||||
|
},
|
||||||
|
ty::Tuple(_) => {
|
||||||
|
replacement_str = format!("{}.{}", replacement_str, idx);
|
||||||
|
true
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
ProjectionKind::Index => false, /* handled previously */
|
||||||
|
// note: unable to capture `Subslice` kind in tests
|
||||||
|
ProjectionKind::Subslice => false,
|
||||||
|
ProjectionKind::Deref => {
|
||||||
|
// explicit deref for arrays should be avoided in the suggestion
|
||||||
|
// i.e.: `|sub| *sub[1..4].len() == 3` is not expected
|
||||||
|
match cmt.place.ty_before_projection(i).kind() {
|
||||||
|
// dereferencing an array (i.e.: `|sub| sub[1..4].len() == 3`)
|
||||||
|
ty::Ref(_, inner, _) => match inner.kind() {
|
||||||
|
ty::Ref(_, innermost, _) if innermost.is_array() => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// handle `ProjectionKind::Deref` if no special case detected
|
||||||
|
if !index_handled && !other_projections_handled {
|
||||||
|
let last_deref = cmt
|
||||||
|
.place
|
||||||
|
.projections
|
||||||
|
.iter()
|
||||||
|
.rposition(|proj| proj.kind == ProjectionKind::Deref);
|
||||||
|
|
||||||
|
if let Some(pos) = last_deref {
|
||||||
|
let mut projections = cmt.place.projections.clone();
|
||||||
|
projections.truncate(pos);
|
||||||
|
|
||||||
|
for item in projections {
|
||||||
|
if item.kind == ProjectionKind::Deref {
|
||||||
|
replacement_str = format!("*{}", replacement_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,4 +73,28 @@ mod issue7392 {
|
|||||||
.map(|c| c.clone())
|
.map(|c| c.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_projection() {
|
||||||
|
struct Foo {
|
||||||
|
foo: i32,
|
||||||
|
bar: u32,
|
||||||
|
}
|
||||||
|
let vfoo = vec![Foo { foo: 1, bar: 2 }];
|
||||||
|
let _ = !vfoo.iter().any(|v| v.foo == 1 && v.bar == 2);
|
||||||
|
|
||||||
|
let vfoo = vec![(42, Foo { foo: 1, bar: 2 })];
|
||||||
|
let _ = !vfoo
|
||||||
|
.iter().any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3]];
|
||||||
|
let _ = !vfoo.iter().any(|a| a[0] == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
|
fn slice_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]];
|
||||||
|
let _ = !vfoo.iter().any(|sub| sub[1..4].len() == 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,4 +75,30 @@ mod issue7392 {
|
|||||||
.map(|c| c.clone())
|
.map(|c| c.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_projection() {
|
||||||
|
struct Foo {
|
||||||
|
foo: i32,
|
||||||
|
bar: u32,
|
||||||
|
}
|
||||||
|
let vfoo = vec![Foo { foo: 1, bar: 2 }];
|
||||||
|
let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_none();
|
||||||
|
|
||||||
|
let vfoo = vec![(42, Foo { foo: 1, bar: 2 })];
|
||||||
|
let _ = vfoo
|
||||||
|
.iter()
|
||||||
|
.find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)
|
||||||
|
.is_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3]];
|
||||||
|
let _ = vfoo.iter().find(|a| a[0] == 42).is_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
|
fn slice_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]];
|
||||||
|
let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_none();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,5 +135,39 @@ error: called `is_none()` after searching an `Iterator` with `find`
|
|||||||
LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none())
|
LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!filter_hand.iter().any(|cc| c == cc)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!filter_hand.iter().any(|cc| c == cc)`
|
||||||
|
|
||||||
error: aborting due to 22 previous errors
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_none.rs:85:17
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_none();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|v| v.foo == 1 && v.bar == 2)`
|
||||||
|
|
||||||
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_none.rs:88:17
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo
|
||||||
|
| _________________^
|
||||||
|
LL | | .iter()
|
||||||
|
LL | | .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)
|
||||||
|
LL | | .is_none();
|
||||||
|
| |______________________^
|
||||||
|
|
|
||||||
|
help: use `!_.any()` instead
|
||||||
|
|
|
||||||
|
LL ~ let _ = !vfoo
|
||||||
|
LL ~ .iter().any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2);
|
||||||
|
|
|
||||||
|
|
||||||
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_none.rs:96:17
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo.iter().find(|a| a[0] == 42).is_none();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|a| a[0] == 42)`
|
||||||
|
|
||||||
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_none.rs:102:17
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_none();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|sub| sub[1..4].len() == 3)`
|
||||||
|
|
||||||
|
error: aborting due to 26 previous errors
|
||||||
|
|
||||||
|
@ -73,4 +73,29 @@ mod issue7392 {
|
|||||||
.map(|c| c.clone())
|
.map(|c| c.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_projection() {
|
||||||
|
struct Foo {
|
||||||
|
foo: i32,
|
||||||
|
bar: u32,
|
||||||
|
}
|
||||||
|
let vfoo = vec![Foo { foo: 1, bar: 2 }];
|
||||||
|
let _ = vfoo.iter().any(|v| v.foo == 1 && v.bar == 2);
|
||||||
|
|
||||||
|
let vfoo = vec![(42, Foo { foo: 1, bar: 2 })];
|
||||||
|
let _ = vfoo
|
||||||
|
.iter()
|
||||||
|
.any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3]];
|
||||||
|
let _ = vfoo.iter().any(|a| a[0] == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
|
fn slice_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]];
|
||||||
|
let _ = vfoo.iter().any(|sub| sub[1..4].len() == 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,4 +74,30 @@ mod issue7392 {
|
|||||||
.map(|c| c.clone())
|
.map(|c| c.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_projection() {
|
||||||
|
struct Foo {
|
||||||
|
foo: i32,
|
||||||
|
bar: u32,
|
||||||
|
}
|
||||||
|
let vfoo = vec![Foo { foo: 1, bar: 2 }];
|
||||||
|
let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_some();
|
||||||
|
|
||||||
|
let vfoo = vec![(42, Foo { foo: 1, bar: 2 })];
|
||||||
|
let _ = vfoo
|
||||||
|
.iter()
|
||||||
|
.find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)
|
||||||
|
.is_some();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3]];
|
||||||
|
let _ = vfoo.iter().find(|a| a[0] == 42).is_some();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
|
fn slice_projection() {
|
||||||
|
let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]];
|
||||||
|
let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_some();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,5 +134,31 @@ error: called `is_some()` after searching an `Iterator` with `find`
|
|||||||
LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_some())
|
LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_some())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|cc| c == cc)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|cc| c == cc)`
|
||||||
|
|
||||||
error: aborting due to 22 previous errors
|
error: called `is_some()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_some.rs:84:29
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_some();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|v| v.foo == 1 && v.bar == 2)`
|
||||||
|
|
||||||
|
error: called `is_some()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_some.rs:89:14
|
||||||
|
|
|
||||||
|
LL | .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)
|
||||||
|
| ______________^
|
||||||
|
LL | | .is_some();
|
||||||
|
| |______________________^ help: use `any()` instead: `any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)`
|
||||||
|
|
||||||
|
error: called `is_some()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_some.rs:95:29
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo.iter().find(|a| a[0] == 42).is_some();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|a| a[0] == 42)`
|
||||||
|
|
||||||
|
error: called `is_some()` after searching an `Iterator` with `find`
|
||||||
|
--> $DIR/search_is_some_fixable_some.rs:101:29
|
||||||
|
|
|
||||||
|
LL | let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_some();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|sub| sub[1..4].len() == 3)`
|
||||||
|
|
||||||
|
error: aborting due to 26 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user