mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
Fix many false negatives caused by autoderef
This commit is contained in:
parent
0411edfbbd
commit
1f2f50c34e
3 changed files with 77 additions and 39 deletions
|
@ -6,6 +6,8 @@ use rustc_lint::LateContext;
|
|||
use rustc_middle::ty;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::iter;
|
||||
|
||||
use super::MISNAMED_GETTERS;
|
||||
|
||||
pub fn check_fn(
|
||||
|
@ -75,39 +77,35 @@ pub fn check_fn(
|
|||
}
|
||||
};
|
||||
|
||||
let ty = cx.typeck_results().expr_ty_adjusted(self_data);
|
||||
|
||||
let def = {
|
||||
let mut kind = ty.kind();
|
||||
loop {
|
||||
match kind {
|
||||
ty::Adt(def, _) => break def,
|
||||
ty::Ref(_, ty, _) => kind = ty.kind(),
|
||||
// We don't do tuples because the function name cannot be a number
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut used_field = None;
|
||||
let mut correct_field = None;
|
||||
for f in def.all_fields() {
|
||||
if f.name.as_str() == name {
|
||||
correct_field = Some(f);
|
||||
}
|
||||
if f.name == used_ident.name {
|
||||
used_field = Some(f);
|
||||
let typeck_results = cx.typeck_results();
|
||||
for adjusted_type in iter::once(typeck_results.expr_ty(self_data))
|
||||
.chain(typeck_results.expr_adjustments(self_data).iter().map(|adj| adj.target))
|
||||
{
|
||||
let ty::Adt(def,_) = adjusted_type.kind() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
for f in def.all_fields() {
|
||||
if f.name.as_str() == name {
|
||||
correct_field = Some(f);
|
||||
}
|
||||
if f.name == used_ident.name {
|
||||
used_field = Some(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(used_field) = used_field else {
|
||||
// FIXME: This can be reached if the field access uses autoderef.
|
||||
// `dec.all_fields()` should be replaced by something that uses autoderef on the unajusted type of `self_data`
|
||||
// Can happen if the field access is a tuple. We don't lint those because the getter name could not start with a number.
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(correct_field) = correct_field else {
|
||||
return;
|
||||
// There is no field corresponding to the getter name.
|
||||
// FIXME: This can be a false positive if the correct field is reachable trought deeper autodereferences than used_field is
|
||||
return;
|
||||
};
|
||||
|
||||
if cx.tcx.type_of(used_field.did) == cx.tcx.type_of(correct_field.did) {
|
||||
|
|
|
@ -85,15 +85,37 @@ impl B {
|
|||
}
|
||||
}
|
||||
|
||||
struct C {
|
||||
inner: Box<A>,
|
||||
struct D {
|
||||
d: u8,
|
||||
inner: A,
|
||||
}
|
||||
impl C {
|
||||
unsafe fn a(&self) -> &u8 {
|
||||
&self.inner.b
|
||||
|
||||
impl core::ops::Deref for D {
|
||||
type Target = A;
|
||||
fn deref(&self) -> &A {
|
||||
&self.inner
|
||||
}
|
||||
unsafe fn a_mut(&mut self) -> &mut u8 {
|
||||
&mut self.inner.b
|
||||
}
|
||||
|
||||
impl core::ops::DerefMut for D {
|
||||
fn deref_mut(&mut self) -> &mut A {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl D {
|
||||
fn a(&self) -> &u8 {
|
||||
&self.b
|
||||
}
|
||||
fn a_mut(&mut self) -> &mut u8 {
|
||||
&mut self.b
|
||||
}
|
||||
|
||||
fn d(&self) -> &u8 {
|
||||
&self.b
|
||||
}
|
||||
fn d_mut(&mut self) -> &mut u8 {
|
||||
&mut self.b
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,22 +127,40 @@ LL | | }
|
|||
| |_____^
|
||||
|
||||
error: getter function appears to return the wrong field
|
||||
--> $DIR/misnamed_getters.rs:92:5
|
||||
--> $DIR/misnamed_getters.rs:107:5
|
||||
|
|
||||
LL | / unsafe fn a(&self) -> &u8 {
|
||||
LL | | &self.inner.b
|
||||
| | ------------- help: consider using: `&self.inner.a`
|
||||
LL | / fn a(&self) -> &u8 {
|
||||
LL | | &self.b
|
||||
| | ------- help: consider using: `&self.a`
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: getter function appears to return the wrong field
|
||||
--> $DIR/misnamed_getters.rs:95:5
|
||||
--> $DIR/misnamed_getters.rs:110:5
|
||||
|
|
||||
LL | / unsafe fn a_mut(&mut self) -> &mut u8 {
|
||||
LL | | &mut self.inner.b
|
||||
| | ----------------- help: consider using: `&mut self.inner.a`
|
||||
LL | / fn a_mut(&mut self) -> &mut u8 {
|
||||
LL | | &mut self.b
|
||||
| | ----------- help: consider using: `&mut self.a`
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: getter function appears to return the wrong field
|
||||
--> $DIR/misnamed_getters.rs:114:5
|
||||
|
|
||||
LL | / fn d(&self) -> &u8 {
|
||||
LL | | &self.b
|
||||
| | ------- help: consider using: `&self.d`
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: getter function appears to return the wrong field
|
||||
--> $DIR/misnamed_getters.rs:117:5
|
||||
|
|
||||
LL | / fn d_mut(&mut self) -> &mut u8 {
|
||||
LL | | &mut self.b
|
||||
| | ----------- help: consider using: `&mut self.d`
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
|
|
Loading…
Reference in a new issue