I have a main.rs file and a logging module inside logging.rs file. My file layout is:
.
├── Cargo.toml
├── src
│ ├── logging.rs
│ └── main.rs
The contents of my main.rs
mod logging;
fn main(){}
The contents of logging.rs
extern crate serialize;
use self::serialize::{json, Encoder, Encodable};
#[deriving(Encodable)]
pub struct Person {
pub age: i32
}
However this does not compile. The error is:
error: failed to resolve. Did you mean `self::serialize`?
/Users/valentin/../src/logging.rs:7 #[deriving(Encodable)]
Three questions:
Why does not it compile?
Why does moving the struct and use directive to main.rs makes it compile?
Why does changing serialize::Encodable to Show trait makes it compile even inside logging module?
However
If I add
extern crate serialize;
use self::serialize::{json, Encoder, Encodable};
to main.rs, it all starts compiling.
This is very confusing, the fourth questions is why isn't it sufficient to have only one extern crate + use serialize::.. inside logging module?
Let’s look at the code that’s generated, with rustc main.rs --pretty expanded:
#![feature(phase)]
#![no_std]
#![feature(globs)]
#[phase(plugin, link)]
extern crate std = "std";
extern crate rt = "native";
use std::prelude::*;
mod logging {
extern crate serialize;
use std::prelude::*;
use self::serialize::{json, Encoder, Encodable};
pub struct Person {
pub age: i32,
}
#[automatically_derived]
impl <__S: ::serialize::Encoder<__E>, __E>
::serialize::Encodable<__S, __E> for Person {
fn encode(&self, __arg_0: &mut __S) ->
::std::result::Result<(), __E> {
match *self {
Person { age: ref __self_0_0 } =>
__arg_0.emit_struct("Person", 1u, |_e| {
return _e.emit_struct_field("age", 0u,
|_e|
(*__self_0_0).encode(_e));
}),
}
}
}
}
fn main() { }
This demonstrates that the #[deriving(Encodable)]expands to stuff involving the paths ::serialize::*; that is, the item serialize from the crate root.
Now, extern crate serialize; from inside mod logging means that the path to serialize is ::logging::serialize, which is also accessible as self::serialize inside the module; there is no ::serialize.
The solution is moving the extern crate serialize; into the crate root. (This is where all extern crate definitions should be.) This is what fixed it for you, not the use self::serialize::{json, Encoder, Encodable};.
Related
I think there is some redundancy in my import but I cant really figure out another way to do it
main.rs
mod lib;
use lib::calc::med_calc;
fn main() {
let mut numbers = vec![1,21,22,4,2];
med_calc(& mut numbers)
}
to me it seems weird to declare the lib.rs as a module and only then I can use the structs/functions within. Since I've already declared them as modules and public in lib.rs itself.
lib.rs
pub mod calc {
pub fn med_calc(vector: & mut Vec<u8>){
vector.sort();
println!("{}", vector[vector.len()/2])
}
}
file tree (used in cargo):
src -
|- main.rs
|- lib.rs
When you have both a lib.rs and main.rs file in your project, the lib.rs file creates a library crate that can be accessed via the crate name in your crate's binary source files (like main.rs and bin/*.rs).
For example, if the crate is named rust_tmp, then you can do:
main.rs:
use rust_tmp::calc::med_calc;
fn main() {
let mut numbers = vec![1, 21, 22, 4, 2];
med_calc(&mut numbers)
}
No need for a mod lib;. Actually, a mod lib; is counterproductive to how lib.rs is meant to be used.
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'
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:
How do I import from a sibling module?
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;
I am trying to write a crate called bar, the structure looks like this
src/
├── bar.rs
└── lib.rs
My src/lib.rs looks like this
#![crate_type = "lib"]
#![crate_name = "bar"]
#![feature(ip_addr)]
#[allow(dead_code)]
pub mod bar;
My bar.rs has
pub struct baz {
// stuff
}
impl baz {
// stuff
}
Now when I try to use this crate in another crate like:
extern crate bar;
use bar::baz;
fn main() {
let cidr = baz::new("Hi");
println!("{}", cidr.say());
}
This fails with
error: unresolved import `bar::baz`. There is no `baz` in `bar`
Do I need to declare the module somewhere else?
The important part you are missing is that crates define their own module. That is, your crate bar implicitly defines a module called bar, but you also have created a module called bar inside that. Your struct resides within this nested module.
If you change your main to use bar::bar::baz; you can progress past this. You will have to decide if that's the structure you want though. Most idiomatic Rust projects would not have the extra mod and would flatten it out:
src/lib.rs
pub struct Baz {
// stuff
}
impl Baz {
// stuff
}
Unfortunately, your example code cannot compile, as you have invalid struct definitions, and you call methods that don't exist (new), so I can't tell you what else it will take to compile.
Also, structs should be PascalCase.
I am trying to write a crate called bar, the structure looks like this
src/
├── bar.rs
└── lib.rs
My src/lib.rs looks like this
#![crate_type = "lib"]
#![crate_name = "bar"]
#![feature(ip_addr)]
#[allow(dead_code)]
pub mod bar;
My bar.rs has
pub struct baz {
// stuff
}
impl baz {
// stuff
}
Now when I try to use this crate in another crate like:
extern crate bar;
use bar::baz;
fn main() {
let cidr = baz::new("Hi");
println!("{}", cidr.say());
}
This fails with
error: unresolved import `bar::baz`. There is no `baz` in `bar`
Do I need to declare the module somewhere else?
The important part you are missing is that crates define their own module. That is, your crate bar implicitly defines a module called bar, but you also have created a module called bar inside that. Your struct resides within this nested module.
If you change your main to use bar::bar::baz; you can progress past this. You will have to decide if that's the structure you want though. Most idiomatic Rust projects would not have the extra mod and would flatten it out:
src/lib.rs
pub struct Baz {
// stuff
}
impl Baz {
// stuff
}
Unfortunately, your example code cannot compile, as you have invalid struct definitions, and you call methods that don't exist (new), so I can't tell you what else it will take to compile.
Also, structs should be PascalCase.
How do I access my libraries exported functions inside the create's "tests" directory?
src/relations.rs:
#![crate_type = "lib"]
mod relations {
pub fn foo() {
println!("foo");
}
}
tests/test.rs:
use relations::foo;
#[test]
fn first() {
foo();
}
$ cargo test
Compiling relations v0.0.1 (file:///home/chris/github/relations)
/home/chris/github/relations/tests/test.rs:1:5: 1:14 error: unresolved import `relations::foo`. Maybe a missing `extern crate relations`?
/home/chris/github/relations/tests/test.rs:1 use relations::foo;
^~~~~~~~~
If I add the suggested extern crate relations, the error is:
/home/chris/github/relations/tests/test.rs:2:5: 2:19 error: unresolved import `relations::foo`. There is no `foo` in `relations`
/home/chris/github/relations/tests/test.rs:2 use relations::foo;
^~~~~~~~~~~~~~
I want to test my relations in this separate tests/test.rs file. How can I solve these use issues?
Your problem is that, first, mod relations is not public so it is not visible outside of the crate, and second, you don't import your crate in tests.
If you build your program with Cargo, then the crate name will be the one you defined in Cargo.toml. For example, if Cargo.toml looks like this:
[package]
name = "whatever"
authors = ["Chris"]
version = "0.0.1"
[lib]
name = "relations" # (1)
And src/lib.rs file contains this:
pub mod relations { // (2); note the pub modifier
pub fn foo() {
println!("foo");
}
}
Then you can write this in tests/test.rs:
extern crate relations; // corresponds to (1)
use relations::relations; // corresponds to (2)
#[test]
fn test() {
relations::foo();
}
The solution was to specify a crate_id at the top of src/relations.rs:
#![crate_id = "relations"]
#![crate_type = "lib"]
pub fn foo() {
println!("foo");
}
This seems to declare that all the contained code is part of a "relations" module, though I'm still not sure how this is different to the earlier mod block.