check that the adjusted receiver type matches target
This commit is contained in:
parent
60258b061d
commit
dd084940de
|
@ -144,6 +144,11 @@ fn check_addr_of_expr(
|
||||||
if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
|
if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
|
||||||
if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
|
if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
|
||||||
if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty);
|
if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty);
|
||||||
|
// Make sure that it's actually calling the right `.to_string()`, (#10033)
|
||||||
|
// *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow)
|
||||||
|
// but that's ok for Cow::into_owned specifically)
|
||||||
|
if cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty
|
||||||
|
|| is_cow_into_owned(cx, method_name, method_def_id);
|
||||||
then {
|
then {
|
||||||
if n_receiver_refs > 0 {
|
if n_receiver_refs > 0 {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -474,3 +474,36 @@ mod issue_10021 {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_10033 {
|
||||||
|
#![allow(dead_code)]
|
||||||
|
use std::{fmt::Display, ops::Deref};
|
||||||
|
|
||||||
|
fn _main() {
|
||||||
|
let f = Foo;
|
||||||
|
|
||||||
|
// Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
|
||||||
|
// deref to `str`)
|
||||||
|
foo(&f.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(s: &str) {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Deref for Foo {
|
||||||
|
type Target = str;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
"str"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Foo {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -474,3 +474,36 @@ mod issue_10021 {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_10033 {
|
||||||
|
#![allow(dead_code)]
|
||||||
|
use std::{fmt::Display, ops::Deref};
|
||||||
|
|
||||||
|
fn _main() {
|
||||||
|
let f = Foo;
|
||||||
|
|
||||||
|
// Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
|
||||||
|
// deref to `str`)
|
||||||
|
foo(&f.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(s: &str) {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Deref for Foo {
|
||||||
|
type Target = str;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
"str"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Foo {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue