Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions 2_idioms/2_6_sealing/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
pub mod my_error;
pub mod my_iterator_ext;

use std::fmt::{Display, Formatter};

pub use self::{my_error::MyError, my_iterator_ext::MyIteratorExt};

#[derive(Debug)]
struct Dummy {}
impl Display for Dummy {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "X")
}
}
impl MyError for Dummy {
// // sealed
// fn type_id(&self, token: private::Token) -> std::any::TypeId
// where
// Self: 'static,
// {
// TypeId::of::<Self>()
// }
}

impl Iterator for Dummy {
type Item = i32;

fn next(&mut self) -> Option<Self::Item> {
None
}
}
// // sealed, but it's anyway a conflicting implementation
// impl MyIteratorExt for Dummy {}
28 changes: 27 additions & 1 deletion 2_idioms/2_6_sealing/src/my_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,29 @@ pub trait MyError: Debug + Display {
/// Gets the `TypeId` of `self`.
///
/// __This is memory-unsafe to override in user code.__
///
/// # Examples
///
/// This method is sealed and cannot be overridden:
///
/// ```rust,compile_fail
/// # use step_2_6::MyError;
/// # use std::any::TypeId;
/// # #[derive(Debug)]
/// # struct MyErrorType;
/// # impl std::fmt::Display for MyErrorType {
/// # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// # write!(f, "error")
/// # }
/// # }
/// impl MyError for MyErrorType {
/// fn type_id(&self, _: step_2_6::my_error::private::Token) -> TypeId {
/// TypeId::of::<Self>()
/// }
/// }
/// ```
#[doc(hidden)]
fn type_id(&self) -> TypeId
fn type_id(&self, _: private::Token) -> TypeId
where
Self: 'static,
{
Expand All @@ -80,3 +101,8 @@ impl<'a, T: MyError + ?Sized> MyError for &'a T {
MyError::source(&**self)
}
}

// making this public will make test fail
mod private {
pub struct Token;
}
22 changes: 21 additions & 1 deletion 2_idioms/2_6_sealing/src/my_iterator_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,22 @@ use std::fmt;
use self::format::{Format, FormatWith};

/// Extension trait for an [`Iterator`].
pub trait MyIteratorExt: Iterator {
///
/// This trait is sealed and cannot be implemented outside of this crate.
///
/// ```compile_fail
/// use step_2_6::MyIteratorExt;
///
/// struct MyIter;
///
/// impl Iterator for MyIter {
/// type Item = i32;
/// fn next(&mut self) -> Option<Self::Item> { None }
/// }
///
/// impl MyIteratorExt for MyIter {}
/// ```
pub trait MyIteratorExt: Iterator + private::Sealed {
/// Format all iterator elements, separated by `sep`.
///
/// All elements are formatted (any formatting trait)
Expand Down Expand Up @@ -71,6 +86,7 @@ pub trait MyIteratorExt: Iterator {
}

impl<T> MyIteratorExt for T where T: Iterator {}
impl<T> private::Sealed for T where T: Iterator {}

mod format {
use std::{cell::RefCell, fmt};
Expand Down Expand Up @@ -193,3 +209,7 @@ mod format {
Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer
}
}

pub mod private {
pub trait Sealed {}
}