MCPcopy Index your code
hub / github.com/CodeChain-io/intertrait

github.com/CodeChain-io/intertrait @0.2.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release 0.2.2 ↗ · + Follow
133 symbols 200 edges 26 files 8 documented · 6%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Intertrait

Build Status Latest Version Rust Documentation

This library provides direct casting among trait objects implemented by a type.

In Rust, a trait object for a sub-trait of [std::any::Any] can be downcast to a concrete type at runtime if the type is known. But no direct casting between two trait objects (i.e. without involving the concrete type of the backing value) is possible (even no coercion from a trait object for a trait to that for its super-trait yet).

With this crate, any trait object for a sub-trait of [CastFrom] can be cast directly to a trait object for another trait implemented by the underlying type if the target traits are registered beforehand with the macros provided by this crate.

Dependencies

Add the following two dependencies to your Cargo.toml:

[dependencies]
intertrait = "0.2"
linkme = "0.2"

The linkme dependency is required due to the use of linkme macro in the output of intertrait macros.

Usage

use intertrait::*;
use intertrait::cast::*;

struct Data;

trait Source: CastFrom {}

trait Greet {
    fn greet(&self);
}

#[cast_to]
impl Greet for Data {
    fn greet(&self) {
        println!("Hello");
    }
}

impl Source for Data {}

fn main() {
    let data = Data;
    let source: &dyn Source = &data;
    let greet = source.cast::<dyn Greet>();
    greet.unwrap().greet();
}

Target traits must be explicitly designated beforehand. There are three ways of doing it:

#[cast_to] to impl item

The trait implemented is designated as a target trait.

use intertrait::*;

struct Data;
trait Greet { fn greet(&self); }

#[cast_to]
impl Greet for Data {
    fn greet(&self) {
        println!("Hello");
    }
}

#[cast_to(Trait)] to type definition

For the type, the traits specified as arguments to the #[cast_to(...)] attribute are designated as target traits.

use intertrait::*;

trait Greet { fn greet(&self); }

impl Greet for Data {
    fn greet(&self) {
        println!("Hello");
    }
}

#[cast_to(Greet, std::fmt::Debug)]
#[derive(std::fmt::Debug)]
struct Data;

castable_to!(Type => Trait1, Trait2)

For the type, the traits following : are designated as target traits.

use intertrait::*;

#[derive(std::fmt::Debug)]
struct Data;
trait Greet { fn greet(&self); }
impl Greet for Data {
    fn greet(&self) {
        println!("Hello");
    }
}
// Only in an item position due to the current limitation in the stable Rust.
// https://github.com/rust-lang/rust/pull/68717
castable_to!(Data => Greet, std::fmt::Debug);

fn main() {}

Arc Support

std::sync::Arc is unique in that it implements downcast method only on dyn Any + Send + Sync + 'static'. To use withArc`, the following steps should be taken:

  • Mark source traits with [CastFromSync] instead of [CastFrom]
  • Add [sync] flag to #[cast_to] and castable_to! as follows: ignore #[cast_to([sync])] #[cast_to([sync] Trait1, Trait2)] castable_to!(Type => [sync] Trait, Trait2);

How it works

First of all, [CastFrom] trait makes it possible to retrieve an object of [std::any::Any] from an object for a sub-trait of [CastFrom].

And the macros provided by intertrait generates trampoline functions for downcasting a trait object for [std::any::Any] back to its concrete type and then creating a trait object for the target trait from it.

Those trampoline functions are aggregated into a global registry using linkme crate, which involves no (generally discouraged) life-before-main trick. The registry is keyed with a pair of [TypeId]s, which are those of the concrete type backing a trait object for a sub-trait of [CastFrom] and the target trait (the actual implementation is a bit different here, but conceptually so).

In the course, it doesn't rely on any unstable Rust implementation details such as the layout of trait objects that may be changed in the future.

Credits

intertrait has taken much of its core ideas from the great traitcast crate.

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Extension points exported contracts — how you extend this code

CastFrom (Interface)
`CastFrom` must be extended by a trait that wants to allow for casting into another trait. It is used for obtaining a t [3 …
src/lib.rs
CastRef (Interface)
A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting of a trait object for it behind [1 …
src/cast/cast_ref.rs
Source (Interface)
(no doc) [1 implementers]
tests/on-struct.rs
Source (Interface)
(no doc) [1 implementers]
tests/on-trait-impl.rs
Source (Interface)
(no doc) [1 implementers]
tests/on-trait-impl-assoc-type2.rs
Source (Interface)
(no doc) [1 implementers]
tests/on-enum.rs
Source (Interface)
(no doc) [1 implementers]
tests/on-trait-impl-assoc-type1.rs
Source (Interface)
(no doc) [1 implementers]
tests/on-type-multi-traits.rs

Core symbols most depended-on inside this repo

generate_caster
called by 3
macros/src/gen_caster.rs
process
called by 2
macros/src/item_type.rs
fully_bound_trait
called by 1
macros/src/item_impl.rs
ref_any
called by 1
src/lib.rs
mut_any
called by 1
src/lib.rs
box_any
called by 1
src/lib.rs
rc_any
called by 1
src/lib.rs
arc_any
called by 1
src/lib.rs

Shape

Function 48
Interface 34
Method 33
Class 16
Enum 2

Languages

Rust100%

Modules by API surface

src/lib.rs40 symbols
tests/on-type-multi-traits.rs9 symbols
tests/castable_to.rs9 symbols
tests/ui/unknown-flag.rs5 symbols
tests/ui/on-generic-type.rs5 symbols
tests/ui/duplicate-flags.rs5 symbols
tests/on-trait-impl.rs5 symbols
tests/on-trait-impl-assoc-type3.rs5 symbols
tests/on-trait-impl-assoc-type2.rs5 symbols
tests/on-trait-impl-assoc-type1.rs5 symbols
tests/on-struct.rs5 symbols
tests/on-enum.rs5 symbols

For agents

$ claude mcp add intertrait \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact