Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
950 views
in Technique[技术] by (71.8m points)

rust - Why do I get "expected struct file1::A found struct file2::A" error when using a struct in multiple files?

I am trying to share a struct between two files, but I am getting an error.

I have the following folder structure:

src/
  Models/
    Login.rs
  Routes/
    LoginRoute.rs
  Services/
    LoginService.rs
  main.rs

In Login.rs I have:

#[derive(Serialize, Deserialize, Debug)]
pub struct UserLoginResponse { 
    id: i32, 
    username: String, 
    token: String
}

In LoginRoute.rs I have:

#[path = "../Models/Login.rs"]
pub mod Login;

#[path = "../Services/LoginService.rs"]
pub mod LoginService;

#[post("/login", format = "application/json", data = "<user>")]
pub async fn login(user: String) -> Json<Login::UserLoginResponse> {      
     
    if let Ok(sk) = LoginService::callAuthenticate(user).await {       
       return sk
......

In LoginService.rs I have:

#[path = "../Models/Login.rs"]
pub mod Login;

pub async fn callAuthenticate(user: String)->  Result<Json<Login::UserLoginResponse>, Error> {
...
let userLoginResponse :Login::UserLoginResponse = Login::UserLoginResponse::new(1,  "admin".to_string(), api_reponse.return_result); 
    Ok(Json(userLoginResponse))
}

I am getting error in LoginRoute.rs on the return sk line:

expected struct 'LoginRoute::Login::UserLoginResponse', found struct 'LoginService::Login:UserLoginResponse'
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Please do not use the #[path = ...] attribute for your typical organization; it should only be used in obscure cases. Each time you do mod something, you are declaring a new module. Even if two modules point to the same file due to #[path = ...], they will be distinct.

So you have multiple UserLoginResponse structs declared:

  • one at crate::LoginRoute::Login::UserLoginResponse
  • one at crate::LoginService::Login:UserLoginResponse
  • and maybe another if you've also declared Login in main.rs.

Since they're in distinct modules, the Rust compiler sees them as different types, which is not what you want.

Just use the idiomatic way of declaring modules. If you want to keep your existing folder structure without intermediate mod.rs files, you can declare them all in main.rs like so:

mod Models {
    pub mod Login;
}
mod Routes {
    pub mod LoginRoute;
}
mod Services {
    pub mod LoginService;
}

And then access them elsewhere via crate::Models::Login and whatnot.

See:


You've probably already run into warnings from the compiler trying to encourage a specific style: "module [...] should have a snake case name". Idiomatic file structure would typically look like this:

src/
  models/
    login.rs
    mod.rs
  routes/
    login_route.rs
    mod.rs
  services/
    login_service.rs
    mod.rs
  main.rs

Where main.rs would have:

mod models;
mod routes;
mod services;

And src/models/mod.rs (for example) would have:

pub mod login;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...