Course contentsShow
← Rust
Lesson 752 of 1,9106. Generics and Static DispatchFree lesson

Interoperability between Generic Systems

Bridge two separate generic codebases by defining a common unifying trait interface.

In this lesson, you will learn how to unify two independent generic systems by creating a shared trait interface that acts as a bridge.

The Challenge of Siloed Generics

Imagine you have two separate libraries in your codebase. Library A defines a Processor<T> that handles data, and Library B defines a Transformer<U> that modifies data. Because these systems were developed independently, they don't know about each other. If you try to pass the output of one into the input of the other, the compiler will complain because the generic types T and U don't share a common language.

Creating the Bridge

To make these systems interoperate, you define a unifying trait. This trait acts as a "common denominator" that both systems agree to satisfy. By defining a trait that both Processor and Transformer can implement, you allow your code to treat them as compatible parts of the same pipeline.

Consider this example where we bridge a Logger system and a Sender system:

// The unifying interface
trait DataPayload {
    fn format_data(&self) -> String;
}

// System A
struct GenericLogger<T: DataPayload>(T);

// System B
struct GenericSender<U: DataPayload>(U);

// Implementation for a custom type
struct UserMessage(String);
impl DataPayload for UserMessage {
    fn format_data(&self) -> String { self.0.clone() }
}

By requiring T: DataPayload and U: DataPayload, you’ve created a contract. Now, any type that implements DataPayload can flow seamlessly between your logger and your sender. Even though the two systems were written in total isolation, the trait provides the glue required for them to communicate.

Why this works

This approach uses static dispatch. Because you are bounding your generics with a shared trait, the compiler knows exactly which methods are available at compile time. This maintains the high performance expected in Rust while effectively "speaking" to two different generic designs simultaneously. Instead of changing the internals of your libraries, you simply force them to adhere to a common standard through trait bounds.

Key Takeaway: You can bridge independent generic systems by defining a shared trait interface that forces both systems to conform to the same data contract.