Auto merge of #11792 - y21:issue11764, r=llogiq
[`map_identity`]: respect match ergonomics Fixes #11764 Note: the original tests before this were slightly wrong themselves already and had to be changed. They were calling `map` on an iterator of `&(i32, i32)`s, so this PR would stop linting there, but they were meant to test something else unrelated to binding modes, so I just changed them to remove the references so that it iterates over owned values and they all bind by value. This way they continue to test what they checked for before: the identity function for tuple patterns. changelog: [`map_identity`]: respect match ergonomics
This commit is contained in:
commit
d487579efd
@ -2023,6 +2023,18 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
/// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
|
||||
fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
|
||||
fn check_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
|
||||
if cx
|
||||
.typeck_results()
|
||||
.pat_binding_modes()
|
||||
.get(pat.hir_id)
|
||||
.is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_)))
|
||||
{
|
||||
// If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics,
|
||||
// the inner patterns become references. Don't consider this the identity function
|
||||
// as that changes types.
|
||||
return false;
|
||||
}
|
||||
|
||||
match (pat.kind, expr.kind) {
|
||||
(PatKind::Binding(_, id, _, _), _) => {
|
||||
path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty()
|
||||
|
@ -24,28 +24,40 @@ fn main() {
|
||||
|
||||
fn issue7189() {
|
||||
// should lint
|
||||
let x = [(1, 2), (3, 4)];
|
||||
let _ = x.iter();
|
||||
let _ = x.iter();
|
||||
let _ = x.iter();
|
||||
let x = [(1, 2), (3, 4)].iter().copied();
|
||||
let _ = x.clone();
|
||||
let _ = x.clone();
|
||||
let _ = x.clone();
|
||||
|
||||
let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))];
|
||||
let _ = y.iter();
|
||||
let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied();
|
||||
let _ = y.clone();
|
||||
|
||||
// should not lint
|
||||
let _ = x.iter().map(|(x, y)| (x, y, y));
|
||||
let _ = x.iter().map(|(x, _y)| (x,));
|
||||
let _ = x.iter().map(|(x, _)| (x,));
|
||||
let _ = x.iter().map(|(x, ..)| (x,));
|
||||
let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z)));
|
||||
let _ = x.clone().map(|(x, y)| (x, y, y));
|
||||
let _ = x.clone().map(|(x, _y)| (x,));
|
||||
let _ = x.clone().map(|(x, _)| (x,));
|
||||
let _ = x.clone().map(|(x, ..)| (x,));
|
||||
let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z)));
|
||||
let _ = y
|
||||
.iter()
|
||||
.map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z)));
|
||||
.clone()
|
||||
.map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z)));
|
||||
let _ = y
|
||||
.iter()
|
||||
.map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
|
||||
.clone()
|
||||
.map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
|
||||
}
|
||||
|
||||
fn not_identity(x: &u16) -> u16 {
|
||||
*x
|
||||
}
|
||||
|
||||
fn issue11764() {
|
||||
let x = [(1, 2), (3, 4)];
|
||||
// don't lint: this is an `Iterator<Item = &(i32, i32)>`
|
||||
// match ergonomics makes the binding patterns into references
|
||||
// so that its type changes to `Iterator<Item = (&i32, &i32)>`
|
||||
let _ = x.iter().map(|(x, y)| (x, y));
|
||||
let _ = x.iter().map(|x| (x.0,)).map(|(x,)| x);
|
||||
|
||||
// no match ergonomics for `(i32, i32)`
|
||||
let _ = x.iter().copied();
|
||||
}
|
||||
|
@ -26,30 +26,42 @@ fn main() {
|
||||
|
||||
fn issue7189() {
|
||||
// should lint
|
||||
let x = [(1, 2), (3, 4)];
|
||||
let _ = x.iter().map(|(x, y)| (x, y));
|
||||
let _ = x.iter().map(|(x, y)| {
|
||||
let x = [(1, 2), (3, 4)].iter().copied();
|
||||
let _ = x.clone().map(|(x, y)| (x, y));
|
||||
let _ = x.clone().map(|(x, y)| {
|
||||
return (x, y);
|
||||
});
|
||||
let _ = x.iter().map(|(x, y)| return (x, y));
|
||||
let _ = x.clone().map(|(x, y)| return (x, y));
|
||||
|
||||
let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))];
|
||||
let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
|
||||
let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied();
|
||||
let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
|
||||
|
||||
// should not lint
|
||||
let _ = x.iter().map(|(x, y)| (x, y, y));
|
||||
let _ = x.iter().map(|(x, _y)| (x,));
|
||||
let _ = x.iter().map(|(x, _)| (x,));
|
||||
let _ = x.iter().map(|(x, ..)| (x,));
|
||||
let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z)));
|
||||
let _ = x.clone().map(|(x, y)| (x, y, y));
|
||||
let _ = x.clone().map(|(x, _y)| (x,));
|
||||
let _ = x.clone().map(|(x, _)| (x,));
|
||||
let _ = x.clone().map(|(x, ..)| (x,));
|
||||
let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z)));
|
||||
let _ = y
|
||||
.iter()
|
||||
.map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z)));
|
||||
.clone()
|
||||
.map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z)));
|
||||
let _ = y
|
||||
.iter()
|
||||
.map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
|
||||
.clone()
|
||||
.map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
|
||||
}
|
||||
|
||||
fn not_identity(x: &u16) -> u16 {
|
||||
*x
|
||||
}
|
||||
|
||||
fn issue11764() {
|
||||
let x = [(1, 2), (3, 4)];
|
||||
// don't lint: this is an `Iterator<Item = &(i32, i32)>`
|
||||
// match ergonomics makes the binding patterns into references
|
||||
// so that its type changes to `Iterator<Item = (&i32, &i32)>`
|
||||
let _ = x.iter().map(|(x, y)| (x, y));
|
||||
let _ = x.iter().map(|x| (x.0,)).map(|(x,)| x);
|
||||
|
||||
// no match ergonomics for `(i32, i32)`
|
||||
let _ = x.iter().copied().map(|(x, y)| (x, y));
|
||||
}
|
||||
|
@ -41,31 +41,37 @@ LL | let _: Result<u32, u32> = Ok(1).map_err(|a| a);
|
||||
| ^^^^^^^^^^^^^^^ help: remove the call to `map_err`
|
||||
|
||||
error: unnecessary map of the identity function
|
||||
--> $DIR/map_identity.rs:30:21
|
||||
--> $DIR/map_identity.rs:30:22
|
||||
|
|
||||
LL | let _ = x.iter().map(|(x, y)| (x, y));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
LL | let _ = x.clone().map(|(x, y)| (x, y));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
|
||||
error: unnecessary map of the identity function
|
||||
--> $DIR/map_identity.rs:31:21
|
||||
--> $DIR/map_identity.rs:31:22
|
||||
|
|
||||
LL | let _ = x.iter().map(|(x, y)| {
|
||||
| _____________________^
|
||||
LL | let _ = x.clone().map(|(x, y)| {
|
||||
| ______________________^
|
||||
LL | | return (x, y);
|
||||
LL | | });
|
||||
| |______^ help: remove the call to `map`
|
||||
|
||||
error: unnecessary map of the identity function
|
||||
--> $DIR/map_identity.rs:34:21
|
||||
--> $DIR/map_identity.rs:34:22
|
||||
|
|
||||
LL | let _ = x.iter().map(|(x, y)| return (x, y));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
LL | let _ = x.clone().map(|(x, y)| return (x, y));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
|
||||
error: unnecessary map of the identity function
|
||||
--> $DIR/map_identity.rs:37:21
|
||||
--> $DIR/map_identity.rs:37:22
|
||||
|
|
||||
LL | let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
LL | let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: unnecessary map of the identity function
|
||||
--> $DIR/map_identity.rs:66:30
|
||||
|
|
||||
LL | let _ = x.iter().copied().map(|(x, y)| (x, y));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user