Repository: rust
Issue: IPv4-in-IPv6 Address Support
Labels: C-enhancement,T-libs

This issue is split out of the larger discussion around stabilization of the `ip` feature (tracking issue: #27709). The focus of this issue on the question of how Rust should support IPv4-in-IPv6 adresses.

There are two ways of representing an IPv4 address in a IPv6 address:
- As an IPv4-compatible IPv6 address:  `::1.2.3.4`
- As an IPv4-mapped IPv6 address:  `::ffff:1.2.3.4`

IPv4-compatible IPv6 addresses have been officially deprecated, see [IEFT RFC #4291 Section 2.5.5.1](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1).

To convert between `Ipv4Addr` and `Ipv6Addr` there are the following methods:

```rust
impl Ipv4Addr {
    fn to_ipv6_mapped(&self) -> Ipv6Addr;
    fn to_ipv6_compatible(&self) -> Ipv6Addr;
}

impl Ipv6Addr {
    fn to_ipv4(&self) -> Option<Ipv4Addr>; // supports converting both IPv4-compatible and Ipv4-mapped addresses

    #[unstable]
    fn to_ipv4_mapped(&self) -> Option<Ipv4Addr>; // only supports converting IPv4-mapped addresses
}
```

## Open Problems

### Converting IPv4-compatible addresses

As pointed out in (https://github.com/rust-lang/rust/pull/75019#issue-461267709) [IEFT RFC #4291 Section 2.5.5.1](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1) states:
> Note: The IPv4 address used in the "IPv4-Compatible IPv6 address" must be a globally-unique IPv4 unicast address. 

Currently `to_ipv6_compatible` performs no such check. Because of this, and the fact that IPv4-compatible addresses have been deprecated it was suggested (https://github.com/rust-lang/rust/pull/75019#issuecomment-667659821) that `to_ipv6_compatible` should be deprecated. There was reservation against this (https://github.com/rust-lang/rust/pull/75019#issuecomment-667654211), and instead the docs were updated to reflect that users will almost always want to use `to_ipv6_mapped` and not `to_ipv6_compatible` (#75150).

In the other direction it was suggested to change the behaviour of `to_ipv4` to that of `to_ipv4_mapped` (https://github.com/rust-lang/rust/pull/76098#discussion_r530465408), and thus only support IPv4-mapped addresses and no longer IPv4-compatible addresses. `to_ipv4_mapped` could then be removed. Another suggestion (https://github.com/rust-lang/rust/pull/76098#discussion_r558190149) was to avoid changing the behaviour and instead stabilizie `to_ipv4_mapped` and deprecate `to_ipv4`.

Unresolved: Should `to_ipv6_compatible` be changed or deprecated? Should `to_ipv4` be changed or deprecated?

### Handling IPv4-in-IPv6 addresses

#69772 raises the concern that other languages consider the IPv4-mapped `::ffff:127.0.0.1` to be localhost and Rust does not. This raised the broader question about which (if any) methods of `Ipv6Addr` should consider IPv4-mapped or IPv4-compatible addresses. A [tool](https://github.com/KodrAus/ipcheck) was created to check what multiple other languages were doing, however Rust offers much more helper methods than many other languages so there is often nothing to compare against. See the tool output (https://github.com/rust-lang/rust/pull/76098#issuecomment-760651861) and conclusion (https://github.com/rust-lang/rust/pull/76098#issuecomment-761234042). The results of this were:

- Probably nothing should take IPv4-compatible addresses into account (https://github.com/rust-lang/rust/pull/76098#discussion_r528738546)
- `is_unspecified` should not take IPv4-mapped addresses into account (https://github.com/rust-lang/rust/pull/76098#discussion_r558679462)
- `is_loopback` should take IPv4-mapped addresses into account (#69772, https://github.com/rust-lang/rust/pull/76098#discussion_r528738546), see PR  #85655
- For methods like `is_documentation` from the naming it unclear if we want this to mean "any address for documentation", and thus include IPv4 mapped addresses, or "addresses specifically reserved for documentation as per [IETF RFC 3849](https://datatracker.ietf.org/doc/html/rfc3849)"
- For `is_global` it is also not clear what semantics we want (https://github.com/rust-lang/rust/pull/76098#discussion_r558690082)

Unresolved: Nail down semantics of `is_global` and other helper methods. See also #85612 IP Utility Methods.

## RFCs

- IPv6 Addresses with Embedded IPv4 Addresses: [IETF RFC #4291 Section 2.5.5](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5)
- IPv6 Address Prefix Reserved for Documentation: [IETF RFC 3849](https://datatracker.ietf.org/doc/html/rfc3849)

## Previous Discussion

- stabilize the "ip" feature: [PR #66584](https://github.com/rust-lang/rust/pull/66584)
- Stabilize the "IP" feature: [PR #76098](https://github.com/rust-lang/rust/pull/76098)
- Stabilize the "IP" feature (continued from #76098): [PR #85585](https://github.com/rust-lang/rust/pull/85585)