From: Ian Jackson Date: Mon, 5 Jun 2023 16:30:28 +0000 (+0100) Subject: refs X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=f445cd2d770f4acf497982d088467c01d62b63be;p=rust-experiments.git refs --- diff --git a/src/main.rs b/src/main.rs index 1c4ea5d..67878f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,10 @@ use std::any::{Any,TypeId}; use std::sync::Arc; -use downcast_rs::{DowncastSync, impl_downcast}; +use downcast_rs::{Downcast, DowncastSync, impl_downcast}; pub trait HasPseudoMethods: DowncastSync { - fn cast_to_instance(&self, arc: &Arc, tp: TypeId) -> Option>; + fn get_caster(&self, tp: TypeId) -> Option<&'static dyn Any>; } impl_downcast!(sync HasPseudoMethods); /* @@ -45,12 +45,23 @@ impl HasPseudoMethods for Frog { // Note: if you wanted to be able to add more traits to Frog elsewhere, you would // need a registry of cast-to-trait objects, similar to the existing dispatch // table. I'm not sure if that's needed. - fn cast_to_instance(&self, arc: &Arc, tp: TypeId) -> Option> { - if tp == TypeId::of::>() { - let arc: Arc = DowncastSync::into_any_arc(arc.clone()); + fn get_caster(&self, tp: TypeId) -> Option<&'static dyn Any> { + if tp == TypeId::of::< + &'static dyn HasFeet + >() { +/* let arc: Arc = DowncastSync::into_any_arc(arc.clone()); let arc: Arc = Arc::downcast::(arc).unwrap(); let arc: Arc = arc as _; - return Some(Box::new(arc)); + */ + static CASTER: fn(&dyn HasPseudoMethods) -> &dyn HasFeet + = |self_| { + let self_: &dyn Any = Downcast::as_any(self_); + let self_: &Frog = self_.downcast_ref().unwrap(); + let self_: &dyn HasFeet = self_ as _; + self_ + }; + + return Some(&CASTER); /* } else if tp == TypeId::of::>() { let arc: Arc = self.clone(); return Some(Box::new(arc)); @@ -61,16 +72,18 @@ impl HasPseudoMethods for Frog { } fn main() { - let frog = Arc::new(Frog); - let erased_frog: Arc = frog as _; + let frog = Arc::new(Frog); + let erased_frog: Arc = frog as _; + let erased_frog: &dyn HasPseudoMethods = &*erased_frog; - let with_feet: Box = erased_frog.cast_to_instance( - &erased_frog, - TypeId::of::>(), - ).unwrap(); + let caster: &'static dyn Any + = erased_frog.get_caster(TypeId::of::<&'static dyn HasFeet>()).unwrap(); - let with_feet: Box> = with_feet.downcast().unwrap(); + let caster: &'static fn(&dyn HasPseudoMethods) -> &dyn HasFeet + = caster.downcast_ref().unwrap(); + let with_feet: &dyn HasFeet = caster(erased_frog); + println!("A frog has {} feet and eats .", with_feet.how_many_feet(),/* eats_food.favorite_food()*/)