Check that the suggested method exists in unwrap_or_default
This commit is contained in:
parent
d9e6aac8bb
commit
8f2d47ea72
@ -65,11 +65,26 @@ pub(super) fn check<'tcx>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sugg = match (name, call_expr.is_some()) {
|
let sugg = match (name, call_expr.is_some()) {
|
||||||
("unwrap_or", true) | ("unwrap_or_else", false) => "unwrap_or_default",
|
("unwrap_or", true) | ("unwrap_or_else", false) => sym!(unwrap_or_default),
|
||||||
("or_insert", true) | ("or_insert_with", false) => "or_default",
|
("or_insert", true) | ("or_insert_with", false) => sym!(or_default),
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let receiver_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs();
|
||||||
|
let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| {
|
||||||
|
cx.tcx
|
||||||
|
.inherent_impls(adt_def.did())
|
||||||
|
.iter()
|
||||||
|
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
|
||||||
|
.any(|assoc| {
|
||||||
|
assoc.fn_has_self_parameter
|
||||||
|
&& cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if !has_suggested_method {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// needs to target Default::default in particular or be *::new and have a Default impl
|
// needs to target Default::default in particular or be *::new and have a Default impl
|
||||||
// available
|
// available
|
||||||
if (is_new(fun) && output_type_implements_default(fun))
|
if (is_new(fun) && output_type_implements_default(fun))
|
||||||
|
@ -130,4 +130,34 @@ fn method_call_with_deref() {
|
|||||||
let _ = inner_map.entry(0).or_default();
|
let _ = inner_map.entry(0).or_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn missing_suggested_method() {
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct S<T>(T);
|
||||||
|
|
||||||
|
impl<T> S<T> {
|
||||||
|
fn or_insert_with(&mut self, default: impl FnOnce() -> T) -> &mut T {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn or_insert(&mut self, default: T) -> &mut T {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrap_or_else(self, default: impl FnOnce() -> T) -> T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrap_or(self, default: T) -> T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't lint when or_default/unwrap_or_default do not exist on the type
|
||||||
|
let mut s = S(1);
|
||||||
|
s.or_insert_with(Default::default);
|
||||||
|
s.or_insert(Default::default());
|
||||||
|
s.unwrap_or_else(Default::default);
|
||||||
|
s.unwrap_or(Default::default());
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -130,4 +130,34 @@ fn method_call_with_deref() {
|
|||||||
let _ = inner_map.entry(0).or_insert_with(Default::default);
|
let _ = inner_map.entry(0).or_insert_with(Default::default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn missing_suggested_method() {
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct S<T>(T);
|
||||||
|
|
||||||
|
impl<T> S<T> {
|
||||||
|
fn or_insert_with(&mut self, default: impl FnOnce() -> T) -> &mut T {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn or_insert(&mut self, default: T) -> &mut T {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrap_or_else(self, default: impl FnOnce() -> T) -> T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrap_or(self, default: T) -> T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't lint when or_default/unwrap_or_default do not exist on the type
|
||||||
|
let mut s = S(1);
|
||||||
|
s.or_insert_with(Default::default);
|
||||||
|
s.or_insert(Default::default());
|
||||||
|
s.unwrap_or_else(Default::default);
|
||||||
|
s.unwrap_or(Default::default());
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user