Skip to content

Instantly share code, notes, and snippets.

@mikeyhew
Created August 2, 2018 20:45
Show Gist options
  • Save mikeyhew/5fa7a0f75f6a2434d46e98de1542ee19 to your computer and use it in GitHub Desktop.
Save mikeyhew/5fa7a0f75f6a2434d46e98de1542ee19 to your computer and use it in GitHub Desktop.
Any<'a> demo
#![feature(arbitrary_self_types)]
use std::ptr;
type TypeId = String;
trait Any<'a>: 'a {
fn type_id(self: *const Self) -> TypeId;
}
impl<'a> Any<'a> {
fn downcast_box<T: Any<'a>>(self: Box<Self>) -> Option<Box<T>> {
if (&*self as *const Self).type_id() == ptr::null::<T>().type_id() {
let ptr = Box::into_raw(self) as *mut Self as *mut T;
Some(unsafe { Box::from_raw(ptr) })
} else {
None
}
}
fn downcast_ref<T: Any<'a>>(&self) -> Option<&T> {
if (self as *const Self).type_id() == ptr::null::<T>().type_id() {
let ptr = self as *const Self as *const T;
Some(unsafe { &*ptr })
} else {
None
}
}
}
impl<'a> Any<'a> for i32 {
fn type_id(self: *const Self) -> TypeId {
format!("i32")
}
}
impl<'a, T: Any<'a>> Any<'a> for Vec<T> {
fn type_id(self: *const Self) -> TypeId {
format!("Vec<{}>", ptr::null::<T>().type_id())
}
}
#[derive(Clone, Copy)]
struct ContainsRef<'a>(&'a Vec<i32>);
impl<'a> Any<'a> for ContainsRef<'a> {
fn type_id(self: *const Self) -> TypeId {
format!("ContainsRef<'_>")
}
}
fn main() {
}
// switch the return type to use 'a instead of 'static, and it will compile
fn enlarge_lifetime_ref<'a>(x: ContainsRef<'a>) -> Option<ContainsRef<'static>> {
let any = &x as &(dyn Any<'a> + 'a);
any.downcast_ref()
.map(|r| *r)
}
fn enlarge_lifetime_box<'a>(x: ContainsRef<'a>) -> Option<ContainsRef<'static>> {
let any = Box::new(x) as Box<Any<'a> + 'a>;
any.downcast_box()
.map(|bx| *bx)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment