Meta-traits and trait polymorphism (ideally part of HKT), allowing a non-duck-typed `write!` macro and more!
| //// PART 1: non-duck-typed write! macro //// | |
| trait trait WriteFmt { | |
| type Error; | |
| fn write_fmt<T: Self>(&mut T, Arguments) -> Result<(), Self::Error>; | |
| } | |
| impl WriteFmt for io::Write { | |
| type Error = io::Error; | |
| fn write_fmt<T: io::Write>(s: &mut T, fmt: Arguments) -> Result<(), io::Error> { | |
| io::Write::write_fmt(s, fmt) | |
| } | |
| } | |
| impl WriteFmt for fmt::Write { | |
| type Error = fmt::Error; | |
| fn write_fmt<T: fmt::Write>(s: &mut T, fmt: Arguments) -> Result<(), fmt::Error> { | |
| fmt::Write::write_fmt(s, fmt) | |
| } | |
| } | |
| macro_rules! write { | |
| ($dst:expr, $($arg:tt)*) => { | |
| // Locating the correct meta-trait impl for this call would be difficult | |
| WriteFmt::write_fmt(&mut *$dst, format_args!($($arg)*)) | |
| } | |
| } | |
| //// PART 2: growable trait object (and more) pointer //// | |
| struct Grow<T: ?Sized> { | |
| _ptr: Unique<T>, | |
| cap: usize, | |
| } | |
| // `ObjectSafe` is a built-in metatrait (`trait trait ObjectSafe`) | |
| impl<trait Tr: ObjectSafe> Grow<Tr> { | |
| fn set<T: Tr>(&mut self, t: T) { | |
| // pseudocode | |
| self.set_capacity(size_of::<T>()); // this also performs reallocation if necessary | |
| unsafe { | |
| self.set_vtable(get_vtable(&mut t as &mut Tr as *mut Tr)); | |
| self.set_ptr(&t); | |
| } | |
| } | |
| } | |
| // Other impls for Grow<[T]> and Grow<str> that replace Vec<T> and String respectively | |
| // could go here, but they don’t use metatraits so they aren’t as cool. | |
| // Here there should also be a few inherent impls + a lot of trait implementations like Box has. | |
| fn growable_trait_object() { | |
| trait Foo { | |
| fn foo(&self); | |
| } | |
| impl Foo for i32 { | |
| fn foo(&self) { println!("{}i32", self); } | |
| } | |
| impl Foo for u32 { | |
| fn foo(&self) { println!("{}u32", self); } | |
| } | |
| let mut x: Grow<Foo> = box 1i32; // using the coming-soon box syntax | |
| x.foo(); // 1i32 | |
| x.set(2u32); | |
| x.foo(); // 2u32 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment