Skip to content

Commit c08d3cc

Browse files
Make Error::type_id() an inherent method on dyn Error
Resolves the soundness issues with this method, and ensures we don't rely on #57893 weirdness in a user-visible way.
1 parent 365c0e1 commit c08d3cc

1 file changed

Lines changed: 27 additions & 14 deletions

File tree

library/core/src/error.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@ pub trait Error: Debug + Display {
112112
None
113113
}
114114

115-
/// Gets the `TypeId` of `self`.
116115
#[doc(hidden)]
117116
#[unstable(
118-
feature = "error_type_id",
119-
reason = "this is memory-unsafe to override in user code",
120-
issue = "60784"
117+
feature = "error_type_id_internals",
118+
reason = "this is an perma-unstable implementation detail of `<dyn Error + 'static>::type_id()`, \
119+
and memory-unsafe to override in user code",
120+
issue = "none"
121121
)]
122-
fn type_id(&self, _: private::Internal) -> TypeId
122+
fn __type_id(&self) -> TypeId
123123
where
124124
Self: 'static,
125125
{
@@ -260,19 +260,18 @@ pub trait Error: Debug + Display {
260260
fn provide<'a>(&'a self, request: &mut Request<'a>) {}
261261
}
262262

263-
mod private {
264-
// This is a hack to prevent `type_id` from being overridden by `Error`
265-
// implementations, since that can enable unsound downcasting.
266-
#[unstable(feature = "error_type_id", issue = "60784")]
267-
#[derive(Debug)]
268-
pub struct Internal;
269-
}
270-
271263
#[unstable(feature = "never_type", issue = "35121")]
272264
impl Error for ! {}
273265

274266
// Copied from `any.rs`.
275267
impl dyn Error + 'static {
268+
/// Gets the [`TypeId`] of the concrete type underlying `self`.
269+
#[unstable(feature = "error_type_id", issue = "60784")]
270+
#[inline]
271+
pub fn type_id(&self) -> TypeId {
272+
self.__type_id()
273+
}
274+
276275
/// Returns `true` if the inner type is the same as `T`.
277276
#[stable(feature = "error_downcast", since = "1.3.0")]
278277
#[inline]
@@ -281,7 +280,7 @@ impl dyn Error + 'static {
281280
let t = TypeId::of::<T>();
282281

283282
// Get `TypeId` of the type in the trait object (`self`).
284-
let concrete = self.type_id(private::Internal);
283+
let concrete = self.type_id();
285284

286285
// Compare both `TypeId`s on equality.
287286
t == concrete
@@ -315,6 +314,13 @@ impl dyn Error + 'static {
315314
}
316315

317316
impl dyn Error + 'static + Send {
317+
/// Gets the [`TypeId`] of the concrete type underlying `self`.
318+
#[unstable(feature = "error_type_id", issue = "60784")]
319+
#[inline]
320+
pub fn type_id(&self) -> TypeId {
321+
<dyn Error + 'static>::type_id(self)
322+
}
323+
318324
/// Forwards to the method defined on the type `dyn Error`.
319325
#[stable(feature = "error_downcast", since = "1.3.0")]
320326
#[inline]
@@ -338,6 +344,13 @@ impl dyn Error + 'static + Send {
338344
}
339345

340346
impl dyn Error + 'static + Send + Sync {
347+
/// Gets the [`TypeId`] of the concrete type underlying `self`.
348+
#[unstable(feature = "error_type_id", issue = "60784")]
349+
#[inline]
350+
pub fn type_id(&self) -> TypeId {
351+
<dyn Error + 'static>::type_id(self)
352+
}
353+
341354
/// Forwards to the method defined on the type `dyn Error`.
342355
#[stable(feature = "error_downcast", since = "1.3.0")]
343356
#[inline]

0 commit comments

Comments
 (0)