RustのCake Pattern実装で発生した謎の事象

# はじめに

[Rust の DI を考える –– Part 2: Rust における DI の手法の整理](https://techblog.paild.co.jp/entry/2023/06/12/170637)と言うすごい記事を見て、自分でもRustのCake Patternを実装してみた。併せてモジュール分割をしたところ、なぜか実装しているtraitを参照できない事象が発生した。

実装結果: [cake_pattern](https://github.com/miyatama/learn_rust/tree/main/projects/cake_pattern)

# 実装の概要

記事にある内容をディレクトリ分割して実装しただけ。traitの名前とかもそのまま。

```text
.
├── Cargo.toml
└── src
    ├── domain
    │ ├── data
    | | └── database.rs 
    │ ├── di
    | | └── app_module.rs 
    │ ├── entity
    | | └── user.rs 
    │ ├── repository
    | | └── user_repository.rs 
    │ ├── service
    | | └── user_service.rs 
    │ ├── data.rs
    │ ├── di.rs
    │ ├── entity.rs
    │ ├── repository.rs
    │ └── service.rs
    └── main.rs
```

AppModuleにProvidesとかのtraitを実装させてmainから呼び出す想定

<details><summary>AppModuleの実装</summary>

```rust
impl Database for AppModule {}
impl UserRepository for AppModule {}
impl UserService for AppModule {}

impl ProvidesDatabase for AppModule {
    type T = Self;
    fn database(&self) -> &Self::T {
        self
    }
}

impl ProvidesUserRepository for AppModule {
    type T = Self;
    fn user_repository(&self) -> &Self::T {
        self
    }
}

impl ProvidesUserService for AppModule {
    type T = Self;
    fn user_service(&self) -> &Self::T {
        self
    }
}
```

</details>


<details><summary>mainからの呼び出し</summary>

```rust
fn main() {
    let app = AppModule {};
    let user = app.user_service().find_user("100".to_string());
    match user {
        Ok(Some(user)) => HttpResponse::Ok().json(user),
        Ok(None) => HttpResponse::NotFound().finish(),
        Err(_) => HttpResponse::InternalServerError().finish(),
    };
}
```

</details>


# 謎の事象

一見よさげに見えるが、実際にビルドすると下記エラーが発生する

```text
error[E0599]: no method named `user_service` found for struct `AppModule` in the current scope
  --> src/main.rs:18:20
   |
18 |     let user = app.user_service().find_user("100".to_string());
   |                    ^^^^^^^^^^^^ method not found in `AppModule`
   |
  ::: src\domain\di\app_module.rs:5:1
   |
5  | pub struct AppModule;
   | -------------------- method `user_service` not found for this struct
   |
  ::: src\domain\service\user_service.rs:31:8
   |
31 |     fn user_service(&self) -> &Self::T;
   |        ------------ the method is available for `AppModule` here
   |
   = help: items from traits can only be used if the trait is in scope
help: trait `ProvidesUserService` which provides `user_service` is implemented but not in scope; perhaps you want to import it
   |
1  + use crate::domain::service::user_service::ProvidesUserService;
   |
```

app_module.rsでAppModuleにProvidesUserServiceを実装しているのに、なぜか認識されていない。

# 回避

やけくそでProvidesUserServiceの実装をmainに移したらなぜかビルド通った。

```rust
use crate::domain::service::{UsesUserService, ProvidesUserService};

impl ProvidesUserService for AppModule {
    type T = Self;
    fn user_service(&self) -> &Self::T {
        self
    }
}

fn main() {
    // Cake Pattern
    let app = AppModule {};
    let user = app.user_service().find_user("100".to_string());
    match user {
        Ok(Some(user)) => HttpResponse::Ok().json(user),
        Ok(None) => HttpResponse::NotFound().finish(),
        Err(_) => HttpResponse::InternalServerError().finish(),
    };
}
```

# 振り返り

やけくそで何とかなったけど、原因不明でもやもやする。