# Module Traits

**URL:** <https://internals.rust-lang.org/t/module-traits/7532>\
**Category:** Uncategorized\
**Created:** [May 15, 2018, 6:09pm UTC](https://internals.rust-lang.org/t/module-traits/7532 "2018-05-15T18:09:42Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![zesterer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zesterer/32/4878_2.png) [@zesterer](https://internals.rust-lang.org/u/zesterer)\
**Post date:** [May 15, 2018, 6:09pm UTC](https://internals.rust-lang.org/t/module-traits/7532/1 "2018-05-15T18:09:42Z")

</div>

Recently, I’ve been having to write a lot of contract-driven code. I’ve been needing to use conditional compilation upon modules, ensuring that the modules provide the same external interface. Unfortunately, modules do not have traits, so I’ve had to reinterpret ‘modules’ as ‘static struct types’. For example:

```rust
trait MyTrait {
    fn foo();
}

struct A {}
struct B {}

impl MyTrait for A {
    fn foo() {
        // Do something
    }
}

impl MyTrait for B {
    fn foo() {
        // Do something else
    }
}

#[cfg(config_variable = "A")] use A as MyFakeModule;
#[cfg(config_variable = "B")] use B as MyFakeModule;

fn do_something() {
    MyFakeModule::foo();
}

```

Here, A and B are contractually obliged to implement the same ‘MyTrait’ interface. There are a few problems with this approach:

1. There’s a useless empty struct declaration
2. The syntax `use MyFakeModule::x::y::z;` doesn’t work, with complaints that MyFakeModule is not a module.
3. I run into this problem: [https://github.com/rust-lang/rust/issues/38078](https://github.com/rust-lang/rust/issues/38078)

This would be 10 times easier to do if modules could implement traits, or if there way such a thing as ‘module traits’. Alternatively, is there another way to improve this?

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 15, 2018, 7:39pm UTC](https://internals.rust-lang.org/t/module-traits/7532/2 "2018-05-15T19:39:39Z")

</div>

The standard way of doing this seems to be to have two modules that are `#[cfg]`d to only load one or the other and named the same. Unfortunately this doesn’t/cannot provide a language guarantee that they provide the same interface, so you have to rely on testing over any combinations of config that matter.

---

<div class="post-metadata">

**Author:** ![dtolnay](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dtolnay/32/1447_2.png) [@dtolnay](https://internals.rust-lang.org/u/dtolnay)\
**Post date:** [May 15, 2018, 9:39pm UTC](https://internals.rust-lang.org/t/module-traits/7532/3 "2018-05-15T21:39:53Z")

</div>

It’s not perfect but how about a macro?

One advantage is you get to write doc comments once instead of for each different implementation of the “module trait.”

```rust
macro_rules! my_module {
    {
        pub fn foo() {
            $($foo:tt)*
        }

        // private helpers or whatever at the end
        $($rest:item)*
    } => {
        pub mod my_module {
            /// Documentation comment for foo.
            pub fn foo() {
                $($foo)*
            }

            $($rest)*
        }
    };
}

#[cfg(config_variable = "A")]
my_module! {
    pub fn foo() {
        // Do something
    }
}

#[cfg(config_variable = "B")]
my_module! {
    pub fn foo() {
        // Do something else
    }
}

```

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:30am UTC](https://internals.rust-lang.org/t/module-traits/7532/4 "2019-03-25T08:30:13Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
