From 584c26f7e03e26f1acff78e72a9b44b2376b4acb Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 17 Aug 2026 10:42:55 -0700 Subject: [PATCH] Implement `AsMut` and `AsRef` for `!`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow e.g. `&[!]` to satisfy `&[T] where T: AsRef`. It follows the recommendation from the never documentation: > When writing your own traits, `!` should have an `impl` whenever > there is an obvious `impl` which doesn’t `panic!`. -- The test tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs had to be updated because it depended on this impl not existing. I’ve confirmed that the modified test still functions as a regression test by compiling it in nightly-2022-08-28 and seeing it ICE. --- library/core/src/convert/mod.rs | 22 +++++++++++++++++++ ...h-implicit-hrtb-without-dyn.pre2021.stderr | 13 ++++------- .../generic-with-implicit-hrtb-without-dyn.rs | 4 ++-- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index a57f3d58e3998..c21c743672014 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -863,6 +863,28 @@ const impl AsMut for str { } } +#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[expect( + clippy::explicit_auto_deref, + reason = "https://github.com/rust-lang/rust-clippy/issues/17713" +)] +impl AsRef for ! { + fn as_ref(&self) -> &T { + *self + } +} + +#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[expect( + clippy::explicit_auto_deref, + reason = "https://github.com/rust-lang/rust-clippy/issues/17713" +)] +impl AsMut for ! { + fn as_mut(&mut self) -> &mut T { + *self + } +} + //////////////////////////////////////////////////////////////////////////////// // THE NO-ERROR ERROR TYPE //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr index dc566ad50153a..54ea4882c4669 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr @@ -1,16 +1,11 @@ -error[E0277]: the trait bound `!: AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied +error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:7:13 | LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `!` + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` ... -LL | todo!() - | ------- return type was inferred to be `!` here - | -help: `!` can be coerced to any type; consider casting it to a concrete type that implements the trait - | -LL | todo!() as /* Type */ - | +++++++++++++ +LL | () + | -- return type was inferred to be `()` here error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 64311a474cade..6c538e8c8ee16 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -5,10 +5,10 @@ #![allow(warnings)] fn ice() -> impl AsRef { - //[pre2021]~^ ERROR: the trait bound `!: AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[pre2021]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] //[edition2021]~^^ ERROR: expected a type, found a trait [E0782] //[edition2021]~| ERROR: expected a type, found a trait [E0782] - todo!() + () } fn main() {}