From 00f08d015cbccb1d6a75133bc95e2e1cf337d43a Mon Sep 17 00:00:00 2001 From: Edward Shen Date: Wed, 29 Apr 2026 20:24:12 -0700 Subject: [PATCH] Support NonZero in ToSocketAddr impls All tuple From implementations for ToSocketAddr currently only accept a u16 as the port number. This results in a small ergonomics penalty for users that parse out a NonZero port number from the program's arguments. This adds a small set of implementations that copies any tuple implementation on ToSocketAddr that takes in a u16 as a port and instead accepts a NonZero. For consistency, a From<(I, NonZeroU16)> implementation for SocketAddr was also implemented. --- library/core/src/net/socket_addr.rs | 15 +++++++++++ library/std/src/net/socket_addr.rs | 41 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs index ccc53c156d3a1..2d8ddeb49d3c7 100644 --- a/library/core/src/net/socket_addr.rs +++ b/library/core/src/net/socket_addr.rs @@ -1,6 +1,7 @@ use super::display_buffer::DisplayBuffer; use crate::fmt::{self, Write}; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use crate::num::NonZero; /// An internet socket address, either IPv4 or IPv6. /// @@ -625,6 +626,20 @@ impl> const From<(I, u16)> for SocketAddr { } } +#[stable(feature = "nonzerou16_to_socket_addrs", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_unstable(feature = "const_convert", issue = "143773")] +impl> const From<(I, NonZero)> for SocketAddr { + /// Converts a tuple struct (Into<[`IpAddr`]>, [`NonZero`]) into a [`SocketAddr`]. + /// + /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`] + /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`]. + /// + /// `u16` is treated as port of the newly created [`SocketAddr`]. + fn from(pieces: (I, NonZero)) -> SocketAddr { + SocketAddr::new(pieces.0.into(), pieces.1.get()) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for SocketAddr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index cae14e34e73e7..5414a099a0024 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -4,6 +4,7 @@ mod tests; #[stable(feature = "rust1", since = "1.0.0")] pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; +use core::num::NonZero; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use crate::{io, iter, option, slice, vec}; @@ -171,6 +172,14 @@ impl ToSocketAddrs for (IpAddr, u16) { } } +#[stable(feature = "nonzerou16_to_socket_addrs", since = "CURRENT_RUSTC_VERSION")] +impl ToSocketAddrs for (IpAddr, NonZero) { + type Iter = <(IpAddr, u16) as ToSocketAddrs>::Iter; + fn to_socket_addrs(&self) -> io::Result { + (self.0, self.1.get()).to_socket_addrs() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (Ipv4Addr, u16) { type Iter = option::IntoIter; @@ -180,6 +189,14 @@ impl ToSocketAddrs for (Ipv4Addr, u16) { } } +#[stable(feature = "nonzerou16_to_socket_addrs", since = "CURRENT_RUSTC_VERSION")] +impl ToSocketAddrs for (Ipv4Addr, NonZero) { + type Iter = <(Ipv4Addr, u16) as ToSocketAddrs>::Iter; + fn to_socket_addrs(&self) -> io::Result { + (self.0, self.1.get()).to_socket_addrs() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (Ipv6Addr, u16) { type Iter = option::IntoIter; @@ -189,6 +206,14 @@ impl ToSocketAddrs for (Ipv6Addr, u16) { } } +#[stable(feature = "nonzerou16_to_socket_addrs", since = "CURRENT_RUSTC_VERSION")] +impl ToSocketAddrs for (Ipv6Addr, NonZero) { + type Iter = <(Ipv6Addr, u16) as ToSocketAddrs>::Iter; + fn to_socket_addrs(&self) -> io::Result { + (self.0, self.1.get()).to_socket_addrs() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (&str, u16) { type Iter = vec::IntoIter; @@ -206,6 +231,14 @@ impl ToSocketAddrs for (&str, u16) { } } +#[stable(feature = "nonzerou16_to_socket_addrs", since = "CURRENT_RUSTC_VERSION")] +impl<'a> ToSocketAddrs for (&'a str, NonZero) { + type Iter = <(&'a str, u16) as ToSocketAddrs>::Iter; + fn to_socket_addrs(&self) -> io::Result { + (self.0, self.1.get()).to_socket_addrs() + } +} + #[stable(feature = "string_u16_to_socket_addrs", since = "1.46.0")] impl ToSocketAddrs for (String, u16) { type Iter = vec::IntoIter; @@ -214,6 +247,14 @@ impl ToSocketAddrs for (String, u16) { } } +#[stable(feature = "nonzerou16_to_socket_addrs", since = "CURRENT_RUSTC_VERSION")] +impl ToSocketAddrs for (String, NonZero) { + type Iter = <(String, u16) as ToSocketAddrs>::Iter; + fn to_socket_addrs(&self) -> io::Result { + (&*self.0, self.1).to_socket_addrs() + } +} + // accepts strings like 'localhost:12345' #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for str {