chiark / gitweb /
refs
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 5 Jun 2023 16:30:28 +0000 (17:30 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 5 Jun 2023 16:30:28 +0000 (17:30 +0100)
src/main.rs

index 1c4ea5dc4cbda9997c27754c1974bf49ce2590cb..67878f6f0ee27c2994899b2be340d871b0f8b9f8 100644 (file)
@@ -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<dyn HasPseudoMethods>, tp: TypeId) -> Option<Box<dyn Any>>;
+    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<dyn HasPseudoMethods>, tp: TypeId) -> Option<Box<dyn Any>> {
-       if tp == TypeId::of::<Arc<dyn HasFeet>>() {
-           let arc: Arc<dyn Any + Send + Sync> = 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<dyn Any + Send + Sync> = DowncastSync::into_any_arc(arc.clone());
            let arc: Arc<Frog> = Arc::downcast::<Frog>(arc).unwrap();
            let arc: Arc<dyn HasFeet> = 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::<Arc<dyn EatsFood>>() {
            let arc: Arc<dyn EatsFood> = 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<dyn HasPseudoMethods> = frog as _;
+    let frog = Arc::new(Frog);
+    let erased_frog: Arc<dyn HasPseudoMethods> = frog as _;
+    let erased_frog: &dyn HasPseudoMethods = &*erased_frog;
 
-    let with_feet: Box<dyn Any> = erased_frog.cast_to_instance(
-        &erased_frog,
-        TypeId::of::<Arc<dyn HasFeet>>(),
-    ).unwrap();
+    let caster: &'static dyn Any
+        = erased_frog.get_caster(TypeId::of::<&'static dyn HasFeet>()).unwrap();
 
-    let with_feet: Box<Arc<dyn HasFeet>> = 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()*/)