1#![deny(unsafe_code,rustdoc::bare_urls)]
2#![cfg_attr(not(feature = "std"), no_std)]
3#[doc(hidden)]
171#[cfg(not(feature = "std"))]
172pub extern crate core as __std;
173#[doc(hidden)]
174#[cfg(feature = "std")]
175pub extern crate std as __std;
176#[doc(hidden)]
177pub extern crate alloc as __alloc;
178
179use __std::any::Any;
180use __alloc::{boxed::Box, rc::Rc};
181
182#[cfg(feature = "sync")]
183use __alloc::sync::Arc;
184
185pub trait Downcast: Any {
187 fn into_any(self: Box<Self>) -> Box<dyn Any>;
190 fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
193 fn as_any(&self) -> &dyn Any;
196 fn as_any_mut(&mut self) -> &mut dyn Any;
199}
200
201impl<T: Any> Downcast for T {
202 fn into_any(self: Box<Self>) -> Box<dyn Any> { self }
203 fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> { self }
204 fn as_any(&self) -> &dyn Any { self }
205 fn as_any_mut(&mut self) -> &mut dyn Any { self }
206}
207
208pub trait DowncastSend: Downcast + Send {
210 fn into_any_send(self: Box<Self>) -> Box<dyn Any + Send>;
213}
214
215impl<T: Any + Send> DowncastSend for T {
216 fn into_any_send(self: Box<Self>) -> Box<dyn Any + Send> { self }
217}
218
219#[cfg(feature = "sync")]
220pub trait DowncastSync: DowncastSend + Sync {
223 fn into_any_sync(self: Box<Self>) -> Box<dyn Any + Send + Sync>;
227 fn into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
230}
231
232#[cfg(feature = "sync")]
233impl<T: Any + Send + Sync> DowncastSync for T {
234 fn into_any_sync(self: Box<Self>) -> Box<dyn Any + Send + Sync> { self }
235 fn into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> { self }
236}
237
238#[macro_export(local_inner_macros)]
244macro_rules! impl_downcast {
245 (@impl_full
246 $trait_:ident [$($param_types:tt)*]
247 for [$($forall_types:ident),*]
248 where [$($preds:tt)*]
249 ) => {
250 impl_downcast! {
251 @inject_where
252 [impl<$($forall_types),*> dyn $trait_<$($param_types)*>]
253 types [$($forall_types),*]
254 where [$($preds)*]
255 [{
256 impl_downcast! { @impl_body $trait_ [$($param_types)*] }
257 }]
258 }
259 };
260
261 (@impl_full_sync
262 $trait_:ident [$($param_types:tt)*]
263 for [$($forall_types:ident),*]
264 where [$($preds:tt)*]
265 ) => {
266 impl_downcast! {
267 @inject_where
268 [impl<$($forall_types),*> dyn $trait_<$($param_types)*>]
269 types [$($forall_types),*]
270 where [$($preds)*]
271 [{
272 impl_downcast! { @impl_body $trait_ [$($param_types)*] }
273 impl_downcast! { @impl_body_sync $trait_ [$($param_types)*] }
274 }]
275 }
276 };
277
278 (@impl_body $trait_:ident [$($types:tt)*]) => {
279 #[inline]
281 pub fn is<__T: $trait_<$($types)*>>(&self) -> bool {
282 $crate::Downcast::as_any(self).is::<__T>()
283 }
284 #[inline]
287 pub fn downcast<__T: $trait_<$($types)*>>(
288 self: $crate::__alloc::boxed::Box<Self>
289 ) -> $crate::__std::result::Result<$crate::__alloc::boxed::Box<__T>, $crate::__alloc::boxed::Box<Self>> {
290 if self.is::<__T>() {
291 Ok($crate::Downcast::into_any(self).downcast::<__T>().unwrap())
292 } else {
293 Err(self)
294 }
295 }
296 #[inline]
299 pub fn downcast_rc<__T: $trait_<$($types)*>>(
300 self: $crate::__alloc::rc::Rc<Self>
301 ) -> $crate::__std::result::Result<$crate::__alloc::rc::Rc<__T>, $crate::__alloc::rc::Rc<Self>> {
302 if self.is::<__T>() {
303 Ok($crate::Downcast::into_any_rc(self).downcast::<__T>().unwrap())
304 } else {
305 Err(self)
306 }
307 }
308 #[inline]
311 pub fn downcast_ref<__T: $trait_<$($types)*>>(&self) -> $crate::__std::option::Option<&__T> {
312 $crate::Downcast::as_any(self).downcast_ref::<__T>()
313 }
314 #[inline]
317 pub fn downcast_mut<__T: $trait_<$($types)*>>(&mut self) -> $crate::__std::option::Option<&mut __T> {
318 $crate::Downcast::as_any_mut(self).downcast_mut::<__T>()
319 }
320 };
321
322 (@impl_body_sync $trait_:ident [$($types:tt)*]) => {
323 #[inline]
326 pub fn downcast_arc<__T: $trait_<$($types)*> + $crate::__std::any::Any + $crate::__std::marker::Send + $crate::__std::marker::Sync>(
327 self: $crate::__alloc::sync::Arc<Self>,
328 ) -> $crate::__std::result::Result<$crate::__alloc::sync::Arc<__T>, $crate::__alloc::sync::Arc<Self>>
329 {
330 if self.is::<__T>() {
331 Ok($crate::DowncastSync::into_any_arc(self).downcast::<__T>().unwrap())
332 } else {
333 Err(self)
334 }
335 }
336 };
337
338 (@inject_where [$($before:tt)*] types [] where [] [$($after:tt)*]) => {
339 impl_downcast! { @as_item $($before)* $($after)* }
340 };
341
342 (@inject_where [$($before:tt)*] types [$($types:ident),*] where [] [$($after:tt)*]) => {
343 impl_downcast! {
344 @as_item
345 $($before)*
346 where $( $types: $crate::__std::any::Any + 'static ),*
347 $($after)*
348 }
349 };
350 (@inject_where [$($before:tt)*] types [$($types:ident),*] where [$($preds:tt)+] [$($after:tt)*]) => {
351 impl_downcast! {
352 @as_item
353 $($before)*
354 where
355 $( $types: $crate::__std::any::Any + 'static, )*
356 $($preds)*
357 $($after)*
358 }
359 };
360
361 (@as_item $i:item) => { $i };
362
363 ($trait_:ident ) => { impl_downcast! { @impl_full $trait_ [] for [] where [] } };
365 ($trait_:ident <>) => { impl_downcast! { @impl_full $trait_ [] for [] where [] } };
366 (sync $trait_:ident ) => { impl_downcast! { @impl_full_sync $trait_ [] for [] where [] } };
367 (sync $trait_:ident <>) => { impl_downcast! { @impl_full_sync $trait_ [] for [] where [] } };
368 ($trait_:ident < $($types:ident),* >) => {
370 impl_downcast! { @impl_full $trait_ [$($types),*] for [$($types),*] where [] }
371 };
372 (sync $trait_:ident < $($types:ident),* >) => {
373 impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [$($types),*] where [] }
374 };
375 ($trait_:ident < $($types:ident),* > where $($preds:tt)+) => {
377 impl_downcast! { @impl_full $trait_ [$($types),*] for [$($types),*] where [$($preds)*] }
378 };
379 (sync $trait_:ident < $($types:ident),* > where $($preds:tt)+) => {
380 impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [$($types),*] where [$($preds)*] }
381 };
382 ($trait_:ident assoc $($atypes:ident),*) => {
384 impl_downcast! { @impl_full $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [] }
385 };
386 (sync $trait_:ident assoc $($atypes:ident),*) => {
387 impl_downcast! { @impl_full_sync $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [] }
388 };
389 ($trait_:ident assoc $($atypes:ident),* where $($preds:tt)+) => {
391 impl_downcast! { @impl_full $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [$($preds)*] }
392 };
393 (sync $trait_:ident assoc $($atypes:ident),* where $($preds:tt)+) => {
394 impl_downcast! { @impl_full_sync $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [$($preds)*] }
395 };
396 ($trait_:ident < $($types:ident),* > assoc $($atypes:ident),*) => {
398 impl_downcast! {
399 @impl_full
400 $trait_ [$($types),*, $($atypes = $atypes),*]
401 for [$($types),*, $($atypes),*]
402 where []
403 }
404 };
405 (sync $trait_:ident < $($types:ident),* > assoc $($atypes:ident),*) => {
406 impl_downcast! {
407 @impl_full_sync
408 $trait_ [$($types),*, $($atypes = $atypes),*]
409 for [$($types),*, $($atypes),*]
410 where []
411 }
412 };
413 ($trait_:ident < $($types:ident),* > assoc $($atypes:ident),* where $($preds:tt)+) => {
415 impl_downcast! {
416 @impl_full
417 $trait_ [$($types),*, $($atypes = $atypes),*]
418 for [$($types),*, $($atypes),*]
419 where [$($preds)*]
420 }
421 };
422 (sync $trait_:ident < $($types:ident),* > assoc $($atypes:ident),* where $($preds:tt)+) => {
423 impl_downcast! {
424 @impl_full_sync
425 $trait_ [$($types),*, $($atypes = $atypes),*]
426 for [$($types),*, $($atypes),*]
427 where [$($preds)*]
428 }
429 };
430 (concrete $trait_:ident < $($types:ident),* >) => {
432 impl_downcast! { @impl_full $trait_ [$($types),*] for [] where [] }
433 };
434 (sync concrete $trait_:ident < $($types:ident),* >) => {
435 impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [] where [] }
436 };
437 (concrete $trait_:ident assoc $($atypes:ident = $aty:ty),*) => {
439 impl_downcast! { @impl_full $trait_ [$($atypes = $aty),*] for [] where [] }
440 };
441 (sync concrete $trait_:ident assoc $($atypes:ident = $aty:ty),*) => {
442 impl_downcast! { @impl_full_sync $trait_ [$($atypes = $aty),*] for [] where [] }
443 };
444 (concrete $trait_:ident < $($types:ident),* > assoc $($atypes:ident = $aty:ty),*) => {
446 impl_downcast! { @impl_full $trait_ [$($types),*, $($atypes = $aty),*] for [] where [] }
447 };
448 (sync concrete $trait_:ident < $($types:ident),* > assoc $($atypes:ident = $aty:ty),*) => {
449 impl_downcast! { @impl_full_sync $trait_ [$($types),*, $($atypes = $aty),*] for [] where [] }
450 };
451}
452
453
454#[cfg(all(test, feature = "sync"))]
455mod test {
456 macro_rules! subst_downcast_send {
458 (@impl { $($parsed:tt)* }, {}) => { $($parsed)* };
459 (@impl { $($parsed:tt)* }, { Downcast $($rest:tt)* }) => {
460 subst_downcast_send!(@impl { $($parsed)* DowncastSend }, { $($rest)* });
461 };
462 (@impl { $($parsed:tt)* }, { $first:tt $($rest:tt)* }) => {
463 subst_downcast_send!(@impl { $($parsed)* $first }, { $($rest)* });
464 };
465 ($($body:tt)+) => {
466 subst_downcast_send!(@impl {}, { $($body)* });
467 };
468 }
469
470 macro_rules! test_mod {
471 (
472 $test_mod_name:ident,
473 trait $base_trait:path { $($base_impl:tt)* },
474 non_sync: { $($non_sync_def:tt)+ },
475 sync: { $($sync_def:tt)+ }
476 ) => {
477 test_mod! {
478 $test_mod_name,
479 trait $base_trait { $($base_impl:tt)* },
480 type dyn $base_trait,
481 non_sync: { $($non_sync_def)* },
482 sync: { $($sync_def)* }
483 }
484 };
485
486 (
487 $test_mod_name:ident,
488 trait $base_trait:path { $($base_impl:tt)* },
489 type $base_type:ty,
490 non_sync: { $($non_sync_def:tt)+ },
491 sync: { $($sync_def:tt)+ }
492 ) => {
493 mod $test_mod_name {
494 test_mod!(
496 @test
497 $test_mod_name,
498 test_name: test_non_sync,
499 trait $base_trait { $($base_impl)* },
500 type $base_type,
501 { $($non_sync_def)+ },
502 []);
503
504 test_mod!(
506 @test
507 $test_mod_name,
508 test_name: test_send,
509 trait $base_trait { $($base_impl)* },
510 type $base_type,
511 { subst_downcast_send! { $($non_sync_def)+ } },
512 [{
513 let base: $crate::__alloc::boxed::Box<$base_type> = $crate::__alloc::boxed::Box::new(Foo(42));
515 fn impls_send<T: ::std::marker::Send>(_a: T) {}
516 impls_send(base.into_any_send());
517 }]);
518
519 test_mod!(
521 @test
522 $test_mod_name,
523 test_name: test_sync,
524 trait $base_trait { $($base_impl)* },
525 type $base_type,
526 { $($sync_def)+ },
527 [{
528 let base: $crate::__alloc::boxed::Box<$base_type> = $crate::__alloc::boxed::Box::new(Foo(42));
530 fn impls_send<T: ::std::marker::Send>(_a: T) {}
531 impls_send(base.into_any_send());
532 let base: $crate::__alloc::boxed::Box<$base_type> = $crate::__alloc::boxed::Box::new(Foo(42));
534 fn impls_send_sync<T: ::std::marker::Send + ::std::marker::Sync>(_a: T) {}
535 impls_send_sync(base.into_any_sync());
536
537 let arc: $crate::__alloc::sync::Arc<$base_type> = $crate::__alloc::sync::Arc::new(Foo(42));
539 let res = arc.downcast_arc::<Bar>();
540 assert!(res.is_err());
541 let arc = res.unwrap_err();
542 assert_eq!(
544 42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
545 }]);
546 }
547 };
548
549 (
550 @test
551 $test_mod_name:ident,
552 test_name: $test_name:ident,
553 trait $base_trait:path { $($base_impl:tt)* },
554 type $base_type:ty,
555 { $($def:tt)+ },
556 [ $($more_tests:block)* ]
557 ) => {
558 #[test]
559 fn $test_name() {
560 #[allow(unused_imports)]
561 use super::super::{Downcast, DowncastSend, DowncastSync};
562
563 #[allow(dead_code)] struct Any;
566 #[allow(dead_code)] struct Arc;
567 #[allow(dead_code)] struct Box;
568 #[allow(dead_code)] struct Option;
569 #[allow(dead_code)] struct Result;
570 #[allow(dead_code)] struct Rc;
571 #[allow(dead_code)] struct Send;
572 #[allow(dead_code)] struct Sync;
573
574 $($def)*
576
577 #[derive(Debug)]
579 struct Foo(u32);
580 impl $base_trait for Foo { $($base_impl)* }
581 #[derive(Debug)]
582 struct Bar(f64);
583 impl $base_trait for Bar { $($base_impl)* }
584
585 fn get_val(base: &$crate::__alloc::boxed::Box<$base_type>) -> u32 {
587 match base.downcast_ref::<Foo>() {
588 Some(val) => val.0,
589 None => 0
590 }
591 }
592 fn set_val(base: &mut $crate::__alloc::boxed::Box<$base_type>, val: u32) {
593 if let Some(foo) = base.downcast_mut::<Foo>() {
594 foo.0 = val;
595 }
596 }
597
598 let mut base: $crate::__alloc::boxed::Box<$base_type> = $crate::__alloc::boxed::Box::new(Foo(42));
599 assert_eq!(get_val(&base), 42);
600
601 if let Some(foo) = base.downcast_ref::<Foo>() {
603 assert_eq!(foo.0, 42);
604 } else if let Some(bar) = base.downcast_ref::<Bar>() {
605 assert_eq!(bar.0, 42.0);
606 }
607
608 set_val(&mut base, 6*9);
609 assert_eq!(get_val(&base), 6*9);
610
611 assert!(base.is::<Foo>());
612
613 let res = base.downcast::<Bar>();
615 assert!(res.is_err());
616 let base = res.unwrap_err();
617 assert_eq!(
619 6*9, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
620
621 let rc: $crate::__alloc::rc::Rc<$base_type> = $crate::__alloc::rc::Rc::new(Foo(42));
623 let res = rc.downcast_rc::<Bar>();
624 assert!(res.is_err());
625 let rc = res.unwrap_err();
626 assert_eq!(
628 42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
629
630 $($more_tests)*
631 }
632 };
633 (
634 $test_mod_name:ident,
635 trait $base_trait:path { $($base_impl:tt)* },
636 non_sync: { $($non_sync_def:tt)+ },
637 sync: { $($sync_def:tt)+ }
638 ) => {
639 test_mod! {
640 $test_mod_name,
641 trait $base_trait { $($base_impl:tt)* },
642 type $base_trait,
643 non_sync: { $($non_sync_def)* },
644 sync: { $($sync_def)* }
645 }
646 };
647
648 }
649
650 test_mod!(non_generic, trait Base {},
651 non_sync: {
652 trait Base: Downcast {}
653 impl_downcast!(Base);
654 },
655 sync: {
656 trait Base: DowncastSync {}
657 impl_downcast!(sync Base);
658 });
659
660 test_mod!(generic, trait Base<u32> {},
661 non_sync: {
662 trait Base<T>: Downcast {}
663 impl_downcast!(Base<T>);
664 },
665 sync: {
666 trait Base<T>: DowncastSync {}
667 impl_downcast!(sync Base<T>);
668 });
669
670 test_mod!(constrained_generic, trait Base<u32> {},
671 non_sync: {
672 trait Base<T: Copy>: Downcast {}
673 impl_downcast!(Base<T> where T: Copy);
674 },
675 sync: {
676 trait Base<T: Copy>: DowncastSync {}
677 impl_downcast!(sync Base<T> where T: Copy);
678 });
679
680 test_mod!(associated,
681 trait Base { type H = f32; },
682 type dyn Base<H=f32>,
683 non_sync: {
684 trait Base: Downcast { type H; }
685 impl_downcast!(Base assoc H);
686 },
687 sync: {
688 trait Base: DowncastSync { type H; }
689 impl_downcast!(sync Base assoc H);
690 });
691
692 test_mod!(constrained_associated,
693 trait Base { type H = f32; },
694 type dyn Base<H=f32>,
695 non_sync: {
696 trait Base: Downcast { type H: Copy; }
697 impl_downcast!(Base assoc H where H: Copy);
698 },
699 sync: {
700 trait Base: DowncastSync { type H: Copy; }
701 impl_downcast!(sync Base assoc H where H: Copy);
702 });
703
704 test_mod!(param_and_associated,
705 trait Base<u32> { type H = f32; },
706 type dyn Base<u32, H=f32>,
707 non_sync: {
708 trait Base<T>: Downcast { type H; }
709 impl_downcast!(Base<T> assoc H);
710 },
711 sync: {
712 trait Base<T>: DowncastSync { type H; }
713 impl_downcast!(sync Base<T> assoc H);
714 });
715
716 test_mod!(constrained_param_and_associated,
717 trait Base<u32> { type H = f32; },
718 type dyn Base<u32, H=f32>,
719 non_sync: {
720 trait Base<T: Clone>: Downcast { type H: Copy; }
721 impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
722 },
723 sync: {
724 trait Base<T: Clone>: DowncastSync { type H: Copy; }
725 impl_downcast!(sync Base<T> assoc H where T: Clone, H: Copy);
726 });
727
728 test_mod!(concrete_parametrized, trait Base<u32> {},
729 non_sync: {
730 trait Base<T>: Downcast {}
731 impl_downcast!(concrete Base<u32>);
732 },
733 sync: {
734 trait Base<T>: DowncastSync {}
735 impl_downcast!(sync concrete Base<u32>);
736 });
737
738 test_mod!(concrete_associated,
739 trait Base { type H = u32; },
740 type dyn Base<H=u32>,
741 non_sync: {
742 trait Base: Downcast { type H; }
743 impl_downcast!(concrete Base assoc H=u32);
744 },
745 sync: {
746 trait Base: DowncastSync { type H; }
747 impl_downcast!(sync concrete Base assoc H=u32);
748 });
749
750 test_mod!(concrete_parametrized_associated,
751 trait Base<u32> { type H = f32; },
752 type dyn Base<u32, H=f32>,
753 non_sync: {
754 trait Base<T>: Downcast { type H; }
755 impl_downcast!(concrete Base<u32> assoc H=f32);
756 },
757 sync: {
758 trait Base<T>: DowncastSync { type H; }
759 impl_downcast!(sync concrete Base<u32> assoc H=f32);
760 });
761}