about summary refs log tree commit diff
diff options
context:
space:
mode:
authorllogiq <bogusandre@gmail.com>2025-06-05 19:36:33 +0000
committerGitHub <noreply@github.com>2025-06-05 19:36:33 +0000
commit6ef2a2d17718734f29b3d80d432e39a12a1e41fe (patch)
tree8161e6760e6ac15f17734910b31728778204af6c
parentf8a3929c3cc09a63677519f9b5a5da9b25cdd336 (diff)
parent8d8b3f16d75dd0841bba7d21b2356f86c099d006 (diff)
downloadrust-6ef2a2d17718734f29b3d80d432e39a12a1e41fe.tar.gz
rust-6ef2a2d17718734f29b3d80d432e39a12a1e41fe.zip
add new lint: `ip_constant` (#14878)
Closes: rust-lang/rust-clippy#14819

changelog: new lint: [`ip_constant`]
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/lib.rs1
-rw-r--r--clippy_lints/src/methods/ip_constant.rs52
-rw-r--r--clippy_lints/src/methods/mod.rs39
-rw-r--r--tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs1
-rw-r--r--tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr6
-rw-r--r--tests/ui/ip_constant.fixed107
-rw-r--r--tests/ui/ip_constant.rs127
-rw-r--r--tests/ui/ip_constant.stderr338
-rw-r--r--tests/ui/ip_constant_from_external.rs12
-rw-r--r--tests/ui/ip_constant_from_external.stderr16
-rw-r--r--tests/ui/localhost.txt1
13 files changed, 699 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1bc0b1ed13..5ba1e3f1e05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5890,6 +5890,7 @@ Released 2018-09-13
 [`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub
 [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
 [`io_other_error`]: https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error
+[`ip_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#ip_constant
 [`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
 [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
 [`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index cbe733e007a..c6a4f3b1572 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -382,6 +382,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::methods::INSPECT_FOR_EACH_INFO,
     crate::methods::INTO_ITER_ON_REF_INFO,
     crate::methods::IO_OTHER_ERROR_INFO,
+    crate::methods::IP_CONSTANT_INFO,
     crate::methods::IS_DIGIT_ASCII_RADIX_INFO,
     crate::methods::ITERATOR_STEP_BY_ZERO_INFO,
     crate::methods::ITER_CLONED_COLLECT_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 6ec14486c20..d915fdc7993 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -55,6 +55,7 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
+extern crate smallvec;
 extern crate thin_vec;
 
 #[macro_use]
diff --git a/clippy_lints/src/methods/ip_constant.rs b/clippy_lints/src/methods/ip_constant.rs
new file mode 100644
index 00000000000..83803fba6a1
--- /dev/null
+++ b/clippy_lints/src/methods/ip_constant.rs
@@ -0,0 +1,52 @@
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, QPath, Ty, TyKind};
+use rustc_lint::LateContext;
+use rustc_span::sym;
+use smallvec::SmallVec;
+
+use super::IP_CONSTANT;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>]) {
+    if let ExprKind::Path(QPath::TypeRelative(
+        Ty {
+            kind: TyKind::Path(QPath::Resolved(_, func_path)),
+            ..
+        },
+        p,
+    )) = func.kind
+        && p.ident.name == sym::new
+        && let Some(func_def_id) = func_path.res.opt_def_id()
+        && matches!(
+            cx.tcx.get_diagnostic_name(func_def_id),
+            Some(sym::Ipv4Addr | sym::Ipv6Addr)
+        )
+        && let Some(args) = args
+            .iter()
+            .map(|arg| {
+                if let Some(Constant::Int(constant @ (0 | 1 | 127 | 255))) = ConstEvalCtxt::new(cx).eval(arg) {
+                    u8::try_from(constant).ok()
+                } else {
+                    None
+                }
+            })
+            .collect::<Option<SmallVec<[u8; 8]>>>()
+    {
+        let constant_name = match args.as_slice() {
+            [0, 0, 0, 0] | [0, 0, 0, 0, 0, 0, 0, 0] => "UNSPECIFIED",
+            [127, 0, 0, 1] | [0, 0, 0, 0, 0, 0, 0, 1] => "LOCALHOST",
+            [255, 255, 255, 255] => "BROADCAST",
+            _ => return,
+        };
+
+        span_lint_and_then(cx, IP_CONSTANT, expr.span, "hand-coded well-known IP address", |diag| {
+            diag.span_suggestion_verbose(
+                expr.span.with_lo(p.ident.span.lo()),
+                "use",
+                constant_name,
+                Applicability::MachineApplicable,
+            );
+        });
+    }
+}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index bc159206985..347960e0003 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -37,6 +37,7 @@ mod inefficient_to_string;
 mod inspect_for_each;
 mod into_iter_on_ref;
 mod io_other_error;
+mod ip_constant;
 mod is_digit_ascii_radix;
 mod is_empty;
 mod iter_cloned_collect;
@@ -4528,6 +4529,42 @@ declare_clippy_lint! {
     "detect swap with a temporary value"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for IP addresses that could be replaced with predefined constants such as
+    /// `Ipv4Addr::new(127, 0, 0, 1)` instead of using the appropriate constants.
+    ///
+    /// ### Why is this bad?
+    /// Using specific IP addresses like `127.0.0.1` or `::1` is less clear and less maintainable than using the
+    /// predefined constants `Ipv4Addr::LOCALHOST` or `Ipv6Addr::LOCALHOST`. These constants improve code
+    /// readability, make the intent explicit, and are less error-prone.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// // IPv4 loopback
+    /// let addr_v4 = Ipv4Addr::new(127, 0, 0, 1);
+    ///
+    /// // IPv6 loopback
+    /// let addr_v6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// // IPv4 loopback
+    /// let addr_v4 = Ipv4Addr::LOCALHOST;
+    ///
+    /// // IPv6 loopback
+    /// let addr_v6 = Ipv6Addr::LOCALHOST;
+    /// ```
+    #[clippy::version = "1.89.0"]
+    pub IP_CONSTANT,
+    pedantic,
+    "hardcoded localhost IP address"
+}
+
 #[expect(clippy::struct_excessive_bools)]
 pub struct Methods {
     avoid_breaking_exported_api: bool,
@@ -4706,6 +4743,7 @@ impl_lint_pass!(Methods => [
     MANUAL_CONTAINS,
     IO_OTHER_ERROR,
     SWAP_WITH_TEMPORARY,
+    IP_CONSTANT,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -4738,6 +4776,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 useless_nonzero_new_unchecked::check(cx, expr, func, args, self.msrv);
                 io_other_error::check(cx, expr, func, args, self.msrv);
                 swap_with_temporary::check(cx, expr, func, args);
+                ip_constant::check(cx, expr, func, args);
             },
             ExprKind::MethodCall(method_call, receiver, args, _) => {
                 let method_span = method_call.ident.span;
diff --git a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs
index 6a9a49324db..4a179cd929f 100644
--- a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs
+++ b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::await_holding_invalid_type)]
+#![allow(clippy::ip_constant)]
 use std::net::Ipv4Addr;
 
 async fn bad() -> u32 {
diff --git a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
index deb7f49db9e..c3c88698032 100644
--- a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
+++ b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
@@ -1,5 +1,5 @@
 error: holding a disallowed type across an await point `std::string::String`
-  --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:5:9
+  --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:6:9
    |
 LL |     let _x = String::from("hello");
    |         ^^
@@ -9,13 +9,13 @@ LL |     let _x = String::from("hello");
    = help: to override `-D warnings` add `#[allow(clippy::await_holding_invalid_type)]`
 
 error: holding a disallowed type across an await point `std::net::Ipv4Addr`
-  --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:11:9
+  --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:12:9
    |
 LL |     let x = Ipv4Addr::new(127, 0, 0, 1);
    |         ^
 
 error: holding a disallowed type across an await point `std::string::String`
-  --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:35:13
+  --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:36:13
    |
 LL |         let _x = String::from("hi!");
    |             ^^
diff --git a/tests/ui/ip_constant.fixed b/tests/ui/ip_constant.fixed
new file mode 100644
index 00000000000..2e3389c1193
--- /dev/null
+++ b/tests/ui/ip_constant.fixed
@@ -0,0 +1,107 @@
+#![warn(clippy::ip_constant)]
+#![allow(dead_code)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::eq_op)]
+
+fn literal_test1() {
+    use std::net::Ipv4Addr;
+    let _ = Ipv4Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = Ipv4Addr::BROADCAST;
+    //~^ ip_constant
+    let _ = Ipv4Addr::UNSPECIFIED;
+    //~^ ip_constant
+
+    use std::net::Ipv6Addr;
+    let _ = Ipv6Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = Ipv6Addr::UNSPECIFIED;
+    //~^ ip_constant
+}
+
+fn literal_test2() {
+    use std::net;
+    let _ = net::Ipv4Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = net::Ipv4Addr::BROADCAST;
+    //~^ ip_constant
+    let _ = net::Ipv4Addr::UNSPECIFIED;
+    //~^ ip_constant
+
+    let _ = net::Ipv6Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = net::Ipv6Addr::UNSPECIFIED;
+    //~^ ip_constant
+}
+
+fn literal_test3() {
+    let _ = std::net::Ipv4Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = std::net::Ipv4Addr::BROADCAST;
+    //~^ ip_constant
+    let _ = std::net::Ipv4Addr::UNSPECIFIED;
+    //~^ ip_constant
+
+    let _ = std::net::Ipv6Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = std::net::Ipv6Addr::UNSPECIFIED;
+    //~^ ip_constant
+}
+
+const CONST_U8_0: u8 = 0;
+const CONST_U8_1: u8 = 1;
+const CONST_U8_127: u8 = 127;
+const CONST_U8_255: u8 = 255;
+
+const CONST_U16_0: u16 = 0;
+const CONST_U16_1: u16 = 1;
+
+fn const_test1() {
+    use std::net::Ipv4Addr;
+    let _ = Ipv4Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = Ipv4Addr::BROADCAST;
+    //~^ ip_constant
+    let _ = Ipv4Addr::UNSPECIFIED;
+    //~^ ip_constant
+
+    use std::net::Ipv6Addr;
+    let _ = Ipv6Addr::LOCALHOST;
+
+    let _ = Ipv6Addr::UNSPECIFIED;
+}
+
+fn const_test2() {
+    use std::net::Ipv4Addr;
+    let _ = Ipv4Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = Ipv4Addr::BROADCAST;
+    //~^ ip_constant
+    let _ = Ipv4Addr::UNSPECIFIED;
+    //~^ ip_constant
+
+    use std::net::Ipv6Addr;
+    let _ = Ipv6Addr::LOCALHOST;
+    //~^ ip_constant
+    let _ = Ipv6Addr::LOCALHOST;
+    //~^ ip_constant
+}
+
+macro_rules! ipv4_new {
+    ($a:expr, $b:expr, $c:expr, $d:expr) => {
+        std::net::Ipv4Addr::new($a, $b, $c, $d)
+    };
+}
+
+fn macro_test() {
+    let _ = ipv4_new!(127, 0, 0, 1);
+    // no lint
+    let _ = ipv4_new!(255, 255, 255, 255);
+    // no lint
+    let _ = ipv4_new!(0, 0, 0, 0);
+    // no lint
+}
+
+fn main() {
+    // UI Test
+}
diff --git a/tests/ui/ip_constant.rs b/tests/ui/ip_constant.rs
new file mode 100644
index 00000000000..15e0b0551ba
--- /dev/null
+++ b/tests/ui/ip_constant.rs
@@ -0,0 +1,127 @@
+#![warn(clippy::ip_constant)]
+#![allow(dead_code)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::eq_op)]
+
+fn literal_test1() {
+    use std::net::Ipv4Addr;
+    let _ = Ipv4Addr::new(127, 0, 0, 1);
+    //~^ ip_constant
+    let _ = Ipv4Addr::new(255, 255, 255, 255);
+    //~^ ip_constant
+    let _ = Ipv4Addr::new(0, 0, 0, 0);
+    //~^ ip_constant
+
+    use std::net::Ipv6Addr;
+    let _ = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+    //~^ ip_constant
+    let _ = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+    //~^ ip_constant
+}
+
+fn literal_test2() {
+    use std::net;
+    let _ = net::Ipv4Addr::new(127, 0, 0, 1);
+    //~^ ip_constant
+    let _ = net::Ipv4Addr::new(255, 255, 255, 255);
+    //~^ ip_constant
+    let _ = net::Ipv4Addr::new(0, 0, 0, 0);
+    //~^ ip_constant
+
+    let _ = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+    //~^ ip_constant
+    let _ = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+    //~^ ip_constant
+}
+
+fn literal_test3() {
+    let _ = std::net::Ipv4Addr::new(127, 0, 0, 1);
+    //~^ ip_constant
+    let _ = std::net::Ipv4Addr::new(255, 255, 255, 255);
+    //~^ ip_constant
+    let _ = std::net::Ipv4Addr::new(0, 0, 0, 0);
+    //~^ ip_constant
+
+    let _ = std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+    //~^ ip_constant
+    let _ = std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+    //~^ ip_constant
+}
+
+const CONST_U8_0: u8 = 0;
+const CONST_U8_1: u8 = 1;
+const CONST_U8_127: u8 = 127;
+const CONST_U8_255: u8 = 255;
+
+const CONST_U16_0: u16 = 0;
+const CONST_U16_1: u16 = 1;
+
+fn const_test1() {
+    use std::net::Ipv4Addr;
+    let _ = Ipv4Addr::new(CONST_U8_127, CONST_U8_0, CONST_U8_0, CONST_U8_1);
+    //~^ ip_constant
+    let _ = Ipv4Addr::new(CONST_U8_255, CONST_U8_255, CONST_U8_255, CONST_U8_255);
+    //~^ ip_constant
+    let _ = Ipv4Addr::new(CONST_U8_0, CONST_U8_0, CONST_U8_0, CONST_U8_0);
+    //~^ ip_constant
+
+    use std::net::Ipv6Addr;
+    let _ = Ipv6Addr::new(
+        //~^ ip_constant
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_1,
+    );
+
+    let _ = Ipv6Addr::new(
+        //~^ ip_constant
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+        CONST_U16_0,
+    );
+}
+
+fn const_test2() {
+    use std::net::Ipv4Addr;
+    let _ = Ipv4Addr::new(126 + 1, 0, 0, 1);
+    //~^ ip_constant
+    let _ = Ipv4Addr::new(254 + CONST_U8_1, 255, { 255 - CONST_U8_0 }, CONST_U8_255);
+    //~^ ip_constant
+    let _ = Ipv4Addr::new(0, CONST_U8_255 - 255, 0, { 1 + 0 - 1 });
+    //~^ ip_constant
+
+    use std::net::Ipv6Addr;
+    let _ = Ipv6Addr::new(0 + CONST_U16_0, 0, 0, 0, 0, 0, 0, 1);
+    //~^ ip_constant
+    let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1);
+    //~^ ip_constant
+}
+
+macro_rules! ipv4_new {
+    ($a:expr, $b:expr, $c:expr, $d:expr) => {
+        std::net::Ipv4Addr::new($a, $b, $c, $d)
+    };
+}
+
+fn macro_test() {
+    let _ = ipv4_new!(127, 0, 0, 1);
+    // no lint
+    let _ = ipv4_new!(255, 255, 255, 255);
+    // no lint
+    let _ = ipv4_new!(0, 0, 0, 0);
+    // no lint
+}
+
+fn main() {
+    // UI Test
+}
diff --git a/tests/ui/ip_constant.stderr b/tests/ui/ip_constant.stderr
new file mode 100644
index 00000000000..3e984c6cb3b
--- /dev/null
+++ b/tests/ui/ip_constant.stderr
@@ -0,0 +1,338 @@
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:8:13
+   |
+LL |     let _ = Ipv4Addr::new(127, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::ip-constant` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::ip_constant)]`
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(127, 0, 0, 1);
+LL +     let _ = Ipv4Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:10:13
+   |
+LL |     let _ = Ipv4Addr::new(255, 255, 255, 255);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(255, 255, 255, 255);
+LL +     let _ = Ipv4Addr::BROADCAST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:12:13
+   |
+LL |     let _ = Ipv4Addr::new(0, 0, 0, 0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(0, 0, 0, 0);
+LL +     let _ = Ipv4Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:16:13
+   |
+LL |     let _ = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+LL +     let _ = Ipv6Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:18:13
+   |
+LL |     let _ = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+LL +     let _ = Ipv6Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:24:13
+   |
+LL |     let _ = net::Ipv4Addr::new(127, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = net::Ipv4Addr::new(127, 0, 0, 1);
+LL +     let _ = net::Ipv4Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:26:13
+   |
+LL |     let _ = net::Ipv4Addr::new(255, 255, 255, 255);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = net::Ipv4Addr::new(255, 255, 255, 255);
+LL +     let _ = net::Ipv4Addr::BROADCAST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:28:13
+   |
+LL |     let _ = net::Ipv4Addr::new(0, 0, 0, 0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = net::Ipv4Addr::new(0, 0, 0, 0);
+LL +     let _ = net::Ipv4Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:31:13
+   |
+LL |     let _ = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+LL +     let _ = net::Ipv6Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:33:13
+   |
+LL |     let _ = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+LL +     let _ = net::Ipv6Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:38:13
+   |
+LL |     let _ = std::net::Ipv4Addr::new(127, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = std::net::Ipv4Addr::new(127, 0, 0, 1);
+LL +     let _ = std::net::Ipv4Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:40:13
+   |
+LL |     let _ = std::net::Ipv4Addr::new(255, 255, 255, 255);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = std::net::Ipv4Addr::new(255, 255, 255, 255);
+LL +     let _ = std::net::Ipv4Addr::BROADCAST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:42:13
+   |
+LL |     let _ = std::net::Ipv4Addr::new(0, 0, 0, 0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = std::net::Ipv4Addr::new(0, 0, 0, 0);
+LL +     let _ = std::net::Ipv4Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:45:13
+   |
+LL |     let _ = std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+LL +     let _ = std::net::Ipv6Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:47:13
+   |
+LL |     let _ = std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+LL +     let _ = std::net::Ipv6Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:61:13
+   |
+LL |     let _ = Ipv4Addr::new(CONST_U8_127, CONST_U8_0, CONST_U8_0, CONST_U8_1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(CONST_U8_127, CONST_U8_0, CONST_U8_0, CONST_U8_1);
+LL +     let _ = Ipv4Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:63:13
+   |
+LL |     let _ = Ipv4Addr::new(CONST_U8_255, CONST_U8_255, CONST_U8_255, CONST_U8_255);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(CONST_U8_255, CONST_U8_255, CONST_U8_255, CONST_U8_255);
+LL +     let _ = Ipv4Addr::BROADCAST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:65:13
+   |
+LL |     let _ = Ipv4Addr::new(CONST_U8_0, CONST_U8_0, CONST_U8_0, CONST_U8_0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(CONST_U8_0, CONST_U8_0, CONST_U8_0, CONST_U8_0);
+LL +     let _ = Ipv4Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:69:13
+   |
+LL |       let _ = Ipv6Addr::new(
+   |  _____________^
+LL | |
+LL | |         CONST_U16_0,
+LL | |         CONST_U16_0,
+...  |
+LL | |         CONST_U16_1,
+LL | |     );
+   | |_____^
+   |
+help: use
+   |
+LL -     let _ = Ipv6Addr::new(
+LL -
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_1,
+LL -     );
+LL +     let _ = Ipv6Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:81:13
+   |
+LL |       let _ = Ipv6Addr::new(
+   |  _____________^
+LL | |
+LL | |         CONST_U16_0,
+LL | |         CONST_U16_0,
+...  |
+LL | |         CONST_U16_0,
+LL | |     );
+   | |_____^
+   |
+help: use
+   |
+LL -     let _ = Ipv6Addr::new(
+LL -
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -         CONST_U16_0,
+LL -     );
+LL +     let _ = Ipv6Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:96:13
+   |
+LL |     let _ = Ipv4Addr::new(126 + 1, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(126 + 1, 0, 0, 1);
+LL +     let _ = Ipv4Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:98:13
+   |
+LL |     let _ = Ipv4Addr::new(254 + CONST_U8_1, 255, { 255 - CONST_U8_0 }, CONST_U8_255);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(254 + CONST_U8_1, 255, { 255 - CONST_U8_0 }, CONST_U8_255);
+LL +     let _ = Ipv4Addr::BROADCAST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:100:13
+   |
+LL |     let _ = Ipv4Addr::new(0, CONST_U8_255 - 255, 0, { 1 + 0 - 1 });
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv4Addr::new(0, CONST_U8_255 - 255, 0, { 1 + 0 - 1 });
+LL +     let _ = Ipv4Addr::UNSPECIFIED;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:104:13
+   |
+LL |     let _ = Ipv6Addr::new(0 + CONST_U16_0, 0, 0, 0, 0, 0, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv6Addr::new(0 + CONST_U16_0, 0, 0, 0, 0, 0, 0, 1);
+LL +     let _ = Ipv6Addr::LOCALHOST;
+   |
+
+error: hand-coded well-known IP address
+  --> tests/ui/ip_constant.rs:106:13
+   |
+LL |     let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL -     let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1);
+LL +     let _ = Ipv6Addr::LOCALHOST;
+   |
+
+error: aborting due to 25 previous errors
+
diff --git a/tests/ui/ip_constant_from_external.rs b/tests/ui/ip_constant_from_external.rs
new file mode 100644
index 00000000000..7fd27022f12
--- /dev/null
+++ b/tests/ui/ip_constant_from_external.rs
@@ -0,0 +1,12 @@
+//@error-in-other-file: hand-coded well-known IP address
+//@no-rustfix
+#![warn(clippy::ip_constant)]
+
+fn external_constant_test() {
+    let _ = include!("localhost.txt");
+    // lint in external file `localhost.txt`
+}
+
+fn main() {
+    external_constant_test();
+}
diff --git a/tests/ui/ip_constant_from_external.stderr b/tests/ui/ip_constant_from_external.stderr
new file mode 100644
index 00000000000..99dd827d41f
--- /dev/null
+++ b/tests/ui/ip_constant_from_external.stderr
@@ -0,0 +1,16 @@
+error: hand-coded well-known IP address
+  --> tests/ui/localhost.txt:1:1
+   |
+LL | std::net::Ipv4Addr::new(127, 0, 0, 1)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::ip-constant` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::ip_constant)]`
+help: use
+   |
+LL - std::net::Ipv4Addr::new(127, 0, 0, 1)
+LL + std::net::Ipv4Addr::LOCALHOST
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/localhost.txt b/tests/ui/localhost.txt
new file mode 100644
index 00000000000..4502ec2b234
--- /dev/null
+++ b/tests/ui/localhost.txt
@@ -0,0 +1 @@
+std::net::Ipv4Addr::new(127, 0, 0, 1)
\ No newline at end of file