summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/recursive_format_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/tests/ui/recursive_format_impl.rs')
-rw-r--r--src/tools/clippy/tests/ui/recursive_format_impl.rs322
1 files changed, 322 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/recursive_format_impl.rs b/src/tools/clippy/tests/ui/recursive_format_impl.rs
new file mode 100644
index 000000000..cb6ba36b1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/recursive_format_impl.rs
@@ -0,0 +1,322 @@
+#![warn(clippy::recursive_format_impl)]
+#![allow(
+ clippy::inherent_to_string_shadow_display,
+ clippy::to_string_in_format_args,
+ clippy::deref_addrof,
+ clippy::borrow_deref_ref
+)]
+
+use std::fmt;
+
+struct A;
+impl A {
+ fn fmt(&self) {
+ self.to_string();
+ }
+}
+
+trait B {
+ fn fmt(&self) {}
+}
+
+impl B for A {
+ fn fmt(&self) {
+ self.to_string();
+ }
+}
+
+impl fmt::Display for A {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.to_string())
+ }
+}
+
+fn fmt(a: A) {
+ a.to_string();
+}
+
+struct C;
+
+impl C {
+ // Doesn't trigger if to_string defined separately
+ // i.e. not using ToString trait (from Display)
+ fn to_string(&self) -> String {
+ String::from("I am C")
+ }
+}
+
+impl fmt::Display for C {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.to_string())
+ }
+}
+
+enum D {
+ E(String),
+ F,
+}
+
+impl std::fmt::Display for D {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match &self {
+ Self::E(string) => write!(f, "E {}", string.to_string()),
+ Self::F => write!(f, "F"),
+ }
+ }
+}
+
+// Check for use of self as Display, in Display impl
+// Triggers on direct use of self
+struct G;
+
+impl std::fmt::Display for G {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self)
+ }
+}
+
+// Triggers on reference to self
+struct H;
+
+impl std::fmt::Display for H {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", &self)
+ }
+}
+
+impl std::fmt::Debug for H {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:?}", &self)
+ }
+}
+
+// Triggers on multiple reference to self
+struct H2;
+
+impl std::fmt::Display for H2 {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", &&&self)
+ }
+}
+
+// Doesn't trigger on correct deref
+struct I;
+
+impl std::ops::Deref for I {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for I {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", &**self)
+ }
+}
+
+impl std::fmt::Debug for I {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{:?}", &**self)
+ }
+}
+
+// Doesn't trigger on multiple correct deref
+struct I2;
+
+impl std::ops::Deref for I2 {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for I2 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", **&&&**self)
+ }
+}
+
+// Doesn't trigger on multiple correct deref
+struct I3;
+
+impl std::ops::Deref for I3 {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for I3 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", &&**&&&**self)
+ }
+}
+
+// Does trigger when deref resolves to self
+struct J;
+
+impl std::ops::Deref for J {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for J {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", &*self)
+ }
+}
+
+impl std::fmt::Debug for J {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{:?}", &*self)
+ }
+}
+
+struct J2;
+
+impl std::ops::Deref for J2 {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for J2 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", *self)
+ }
+}
+
+struct J3;
+
+impl std::ops::Deref for J3 {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for J3 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", **&&*self)
+ }
+}
+
+struct J4;
+
+impl std::ops::Deref for J4 {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "test"
+ }
+}
+
+impl std::fmt::Display for J4 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", &&**&&*self)
+ }
+}
+
+// Doesn't trigger on Debug from Display
+struct K;
+
+impl std::fmt::Debug for K {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "test")
+ }
+}
+
+impl std::fmt::Display for K {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
+// Doesn't trigger on Display from Debug
+struct K2;
+
+impl std::fmt::Debug for K2 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{}", self)
+ }
+}
+
+impl std::fmt::Display for K2 {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "test")
+ }
+}
+
+// Doesn't trigger on struct fields
+struct L {
+ field1: u32,
+ field2: i32,
+}
+
+impl std::fmt::Display for L {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{},{}", self.field1, self.field2)
+ }
+}
+
+impl std::fmt::Debug for L {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "{:?},{:?}", self.field1, self.field2)
+ }
+}
+
+// Doesn't trigger on nested enum matching
+enum Tree {
+ Leaf,
+ Node(Vec<Tree>),
+}
+
+impl std::fmt::Display for Tree {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Tree::Leaf => write!(f, "*"),
+ Tree::Node(children) => {
+ write!(f, "(")?;
+ for child in children.iter() {
+ write!(f, "{},", child)?;
+ }
+ write!(f, ")")
+ },
+ }
+ }
+}
+
+impl std::fmt::Debug for Tree {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Tree::Leaf => write!(f, "*"),
+ Tree::Node(children) => {
+ write!(f, "(")?;
+ for child in children.iter() {
+ write!(f, "{:?},", child)?;
+ }
+ write!(f, ")")
+ },
+ }
+ }
+}
+
+fn main() {
+ let a = A;
+ a.to_string();
+ a.fmt();
+ fmt(a);
+
+ let c = C;
+ c.to_string();
+}