From c18dfb02ac90d2884f2e3ea46afe96cea34057bb Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 1 Mar 2026 18:00:32 +0800 Subject: [PATCH 1/2] Make Error::type_id final --- library/core/src/error.rs | 12 ++---------- library/core/src/lib.rs | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 011d6ac4a1c78..20068be6798e1 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -119,7 +119,7 @@ pub trait Error: Debug + Display { reason = "this is memory-unsafe to override in user code", issue = "60784" )] - fn type_id(&self, _: private::Internal) -> TypeId + final fn type_id(&self) -> TypeId where Self: 'static, { @@ -260,14 +260,6 @@ pub trait Error: Debug + Display { fn provide<'a>(&'a self, request: &mut Request<'a>) {} } -mod private { - // This is a hack to prevent `type_id` from being overridden by `Error` - // implementations, since that can enable unsound downcasting. - #[unstable(feature = "error_type_id", issue = "60784")] - #[derive(Debug)] - pub struct Internal; -} - #[unstable(feature = "never_type", issue = "35121")] impl Error for ! {} @@ -281,7 +273,7 @@ impl dyn Error + 'static { let t = TypeId::of::(); // Get `TypeId` of the type in the trait object (`self`). - let concrete = self.type_id(private::Internal); + let concrete = self.type_id(); // Compare both `TypeId`s on equality. t == concrete diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 29869dd91982d..524f1a24353de 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -138,6 +138,7 @@ #![feature(f16)] #![feature(f128)] #![feature(field_projections)] +#![feature(final_associated_functions)] #![feature(freeze_impls)] #![feature(fundamental)] #![feature(funnel_shifts)] From fccebf57540b918be1282b82f7e52a8290ce1b77 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Mon, 9 Mar 2026 16:19:17 +0800 Subject: [PATCH 2/2] Add test for impl final error-type-id --- tests/ui/std/impl-error-type-id.rs | 19 +++++++++++++++++++ tests/ui/std/impl-error-type-id.stderr | 11 +++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/ui/std/impl-error-type-id.rs create mode 100644 tests/ui/std/impl-error-type-id.stderr diff --git a/tests/ui/std/impl-error-type-id.rs b/tests/ui/std/impl-error-type-id.rs new file mode 100644 index 0000000000000..793d4c7e82a52 --- /dev/null +++ b/tests/ui/std/impl-error-type-id.rs @@ -0,0 +1,19 @@ +#![feature(error_type_id)] + +#[derive(Debug)] +struct T; + +impl std::fmt::Display for T { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "T") + } +} + +impl std::error::Error for T { + fn type_id(&self) -> std::any::TypeId { + //~^ ERROR cannot override `type_id` because it already has a `final` definition in the trait + std::any::TypeId::of::() + } +} + +fn main() {} diff --git a/tests/ui/std/impl-error-type-id.stderr b/tests/ui/std/impl-error-type-id.stderr new file mode 100644 index 0000000000000..acce2214e30e0 --- /dev/null +++ b/tests/ui/std/impl-error-type-id.stderr @@ -0,0 +1,11 @@ +error: cannot override `type_id` because it already has a `final` definition in the trait + --> $DIR/impl-error-type-id.rs:13:5 + | +LL | fn type_id(&self) -> std::any::TypeId { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `type_id` is marked final here + --> $SRC_DIR/core/src/error.rs:LL:COL + +error: aborting due to 1 previous error +