Skip to content

Instantly share code, notes, and snippets.

@p7g
Last active February 19, 2021 18:09
Show Gist options
  • Save p7g/f157c7a54d115fd2f3f19cd07d27610f to your computer and use it in GitHub Desktop.
Save p7g/f157c7a54d115fd2f3f19cd07d27610f to your computer and use it in GitHub Desktop.
Dynamically implementing a Rust trait

Dynamically implementing a Rust trait

Sometimes one might need to create an object at run-time that implements a Rust trait. This is one way to do so, provided the trait to be implemented is known statically.

Here's how:

  1. Define a struct that will hold the implementation of each trait method.
  2. Define a second "object" struct that holds a "self" value and a reference to an implementation struct.
  3. Implement the desired trait for the object struct, dispatching to the function pointers in the implementation struct.

An example:

// example trait
trait Greeter {
	fn greet(&self) -> String;
}

// make a wrapper struct
struct GreeterImpl<T> {
	// all the implementation function pointers go here
	greet_fn: fn(&T) -> String,
}

impl<T> GreeterImpl<T> {
	fn create_instance(&self, slf: T) -> GreeterObject<T> {
		GreeterObject { slf, impl_: self }
	}
}

struct GreeterObject<'a, T> {
	slf: T,
	impl_: &'a GreeterImpl<T>,
}

impl<'a, T> Greeter for GreeterObject<'a, T> {
	fn greet(&self) -> String {
		(self.impl_.greet_fn)(&self.slf)
	}
}

This means you can JIT-compile the implementation of a trait's methods and then create objects that implement the trait dynamically.

Obviously this means that the implementations of the trait methods will be called indirectly (through a function pointer) and cannot be inlined by the compiler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment