"unresolved import" when using an item from a nested module - module

I have a small program that I've been trying to get working, but I keep getting unresolved import messages.
main.rs:
mod sub_module;
use sub_module::a_structure;
fn main() {
let x: a_structure = /* init code */;
}
sub_module.rs:
pub mod sub_sub_module;
pub use sub_sub_module::a_structure;
sub_sub_module.rs:
pub struct a_structure<T> {
some_field: i32,
}
However, on executing cargo build I get an "unresolved import sub_sub_module::a_structure". Everything I've found regarding visibility says that this should work however it doesn't. What am I missing here?

Think of Rust modules as being like a directory tree. Modules are directories, everything else is a file [1]. :: is basically /.
So, you have this structure:
/ (crate root)
└┬─ sub_module
│ └┬─ sub_sub_module
│ │ └── a_structure
│ └─ a_structure [x]
├─ a_structure
└─ main
The problem is in how you define the a_structure [x] "symlink". As explained in the book, use paths in Rust are absolute, meaning in this analogy that they all implicitly start with /. Meaning that use sub_sub_module::a_structure is referring to /sub_sub_module/a_structure, which doesn't exist.
The solution is to use a relative path by explicitly starting the path with self (effectively .) or super (effectively ..). You want ./sub_sub_module/a_structure, so the path in Rust should be self::sub_sub_module::a_structure. A full, compiling (with warnings) example looks like:
mod sub_module {
pub mod sub_sub_module {
pub struct a_structure {
some_field: i32,
}
}
pub use self::sub_sub_module::a_structure;
}
use sub_module::a_structure;
fn main() {
let x: a_structure = panic!("TODO");
}
You should also note that paths used anywhere outside of a use have the exact opposite default: they are relative to the containing module by default. If you want an absolute path in that case, you need to explicitly ask for one by starting the path with :: (just like a filesystem path that is, by default, interpreted as relative).
Aside: The conventional style is to use PascalCase for type names. Also, I had to remove the type parameter because it wasn't being used.
[1]: This is, in fact, a lie, as you can have items associated with other items. For example, associated consts, while unstable, are a thing. I suppose you could think of them in terms of resource forks or something, I don't know; it's just a metaphor!

Related

Deserializing an enum using a combination of #[serde(untagged)] and #[serde(with)]

I'm trying to use an actix-web server as a gateway to a small stack to guarantee a strict data format inside of the stack while allowing some freedoms for the user.
To do that, I want to deserialize a JSON string to the struct, then validate it, serialize it again and publish it on a message broker. The main part of the data is an array of arrays that contain integers, floats and datetimes. I'm using serde for deserialization and chrono to deal with datetimes.
I tried using a struct combined with an enum to allow the different types:
#[derive(Serialize, Deserialize)]
pub struct Data {
pub column_names: Option<Vec<String>>,
pub values: Vec<Vec<ValueType>>,
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum ValueType {
I32(i32),
F64(f64),
#[serde(with = "datetime_handler")]
Dt(DateTime<Utc>),
}
Since chrono::DateTime<T> does not implement Serialize, I added a custom module for that similar to how it is described in the serde docs.
mod datetime_handler {
use chrono::{DateTime, TimeZone, Utc};
use serde::{self, Deserialize, Deserializer, Serializer};
pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = dt.to_rfc3339();
serializer.serialize_str(&s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
println!("Checkpoint 1");
let s = String::deserialize(deserializer)?;
println!("{}", s);
println!("Checkpoint 2");
let err1 = match DateTime::parse_from_rfc3339(&s) {
Ok(dt) => return Ok(dt.with_timezone(&Utc)),
Err(e) => Err(e),
};
println!("Checkpoint 3");
const FORMAT1: &'static str = "%Y-%m-%d %H:%M:%S";
match Utc.datetime_from_str(&s, FORMAT1) {
Ok(dt) => return Ok(dt.with_timezone(&Utc)),
Err(e) => println!("{}", e), // return first error not second if both fail
};
println!("Checkpoint 4");
return err1.map_err(serde::de::Error::custom);
}
}
This tries 2 different time formats one after the other and works for DateTime strings.
The Problem
It seems like the combination of `#[derive(Serialize, Deserialize)]`, `#[serde(untagged)]` and `#[serde(with)]` does something unexpected. `serde:from_str(...)` tries to deserialize every entry in the array with my custom `deserialize` function.
I would expect it to either try to deserialize into `ValueType::I32` first, succeed and continue with the next entry, as [the docs](https://serde.rs/enum-representations.html) say:
Serde will try to match the data against each variant in order and the first one that deserializes successfully is the one returned.
What happens is that the custom deserializeis applied to e.g. "0" fails and the deserialization stops.
What's going on? How do I solve it?
My ideas are that I either fail to deserialize in the wrong way or that I somehow "overwrite" the derived deserialize with my own.
#jonasbb helped me realize the code works when using [0,16.9,"2020-12-23 00:23:14"] but it does not when trying to deserialize ["0","16.9","2020-12-23 00:23:14"]. Serde does not serialize numbers from strings by default, the attempts for I32 and F64 just fail silently. This is discussed in this serde-issue and can be solved using the inofficial serde-aux crate.
Many crates will implement serde and other common utility crates, but will leave them as optional features. This can help save time when compiling. You can check a crate by viewing the Cargo.toml file to see if there is a feature for it or the dependency is included but marked as optional.
In your case, I can go to chrono on crates.io and select the Repository link to view the source code for the crate. In the Cargo.toml file, I can see that serde is used, but is not enabled by default.
[features]
default = ["clock", "std", "oldtime"]
alloc = []
std = []
clock = ["libc", "std", "winapi"]
oldtime = ["time"]
wasmbind = ["wasm-bindgen", "js-sys"]
unstable-locales = ["pure-rust-locales", "alloc"]
__internal_bench = []
__doctest = []
[depenencies]
...
serde = { version = "1.0.99", default-features = false, optional = true }
To enable it you can go into the Cargo.toml for your project and add it as a feature to chrono.
[depenencies]
chrono = { version: "0.4.19", features = ["serde"] }
Alternatively, chrono lists some (but not all?) of their optional features in their documentation. However, not all crates do this and docs can sometimes be out of date so I usually prefer the manual method.
As for the issue between the interaction of deserialize_with and untagged on enums, I don't see any issue with your code. It may be a bug in serde so I suggest you create an issue on the serde Repository so they can further look into why this error occurs.

Forbid runtime dependency on package in Nix overlay

Task description
I want to make sure that no derivation I install has no run-time dependency on specified set of derivation. If I ask nix-env to install package that has such run-time dependency, I want it to say that I am asking for impossible. Build-dependencies are fine. I want to avoid huge cascade rebuilds, though.
In other words, I want to make sure that derivation with name = evil never reaches my Nix store, but I am fine that it was used to build other derivations on Hydra. Here is what I tried:
Failed attempt: use derivation meta attribute
self: super: {
evil = super.evil // { meta.broken = True; };
}
but this makes nix-env to refuse install programs that has build-time dependencies on evil, for example it refuses to install go or haskell programs (which are statically linked) because compiler has some transitive dependency on evil.
Failed attempt: replace evil with something harmless
I write overlay that replaces evil:
self: super {
evil = super.harmless; # e.g super.busybox
}
it causes major cascade rebuild.
Random idea
If there is function, like this:
self: super: {
ghc = forget_about_dependencies_but_retain_hash_yes_I_know_what_I_Do [super.evil] super.ghc;
# same for rustc, go and other compilers that link statically.
}
that would be 90% solution for me.
It seems impossible to prevent some derivation from being in store, but it is possible to make sure profile does not contain run-time dependencies:
self: super: {
world = (super.buildEnv {
name = "world";
paths = with super; [ foo bar baz ];
}).overrideAttrs (_: { disallowedRequisites = [ super.evil super.ugly ]; });
}
So, if you put all derivations you want in "world", you can be sure that evil and ugly are not in dependencies. But they will be downloaded into store to build "world", even if they are not actually used by any derivations in paths.

How to access the function in main.rs which has been written in a file in different directory in rust in same package [duplicate]

This question already has answers here:
How can I include a module from another file from the same project?
(6 answers)
How do I "use" or import a local Rust file? [duplicate]
(1 answer)
Closed 3 years ago.
I want to call a function inside a main.rs file. I have made one directory name "library" inside the same src folder as main.rs exist.
src/main.rs
mod library;
fn main() {
println!("{}", library::name1::name(4));
}
src/library/file.rs
pub mod name1 {
pub fn name(a: i32) -> i32 {
println!("from diff file {}", a);
a * a
}
}
when I call this function name in main.rs, compiler throws an error:
error[E0583]: file not found for module library
I think I am missing something. What is the correct way to do this? Keep in mind that the library directory is just an ordinary directory not a cargo package
You can fix this issue in 2 different ways:
1 ) Using Module
2 ) Using Library
Using Module
Simply create a file next to main.rs in src directory and name it name1.rs
name1.rs will look like:
//no need to specify "pub mod name1;" explicitly
pub fn name(a: i32) -> i32 {
println!("from diff file {}", a);
a * a
}
main.rs will look like:
//name of the second file will be treated as module here
pub mod name1;
fn main() {
println!("{}", name1::name(4));
}
Using Library
a) create a library, standing in main project directory (i.e. parent of src directory) and run the command below:
//In your case library name "file"
$ cargo new --lib file
This command will create another directory of name file same as your main project.
b) Add this library(file) in the dependency section of Cargo.toml file of main project
[package]
name = "test_project"
version = "0.1.0"
authors = ["mohammadrajabraza <mohammadrajabraza#gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
file = {path ="file"}
c) A file under main_project>file(library)>src>lib.rs will be created, once you created library using command above.
lib.rs will be look like:
pub fn name(a: i32) -> i32 {
println!("from diff file {}", a);
a * a
}
d) and finally your main.rs will be:
//importing library in thescope
use file;
fn main() {
println!("{}", file::name(4));
}
Create a file in src directory named as library.rs and than in library.rs write the following code:
pub mod file;
Than access the same function from your main file as you are doing right now.Than it will work properly.
You can follow this method too
https://github.com/Abdul-sid/PIAIC-IOT-RUST-CLASS/tree/master/13th-Oct-chapter-7-part-2/dir-mod-bin/src
You can use the concept of library which rust have in it.
Simply making a library project having the --lib flag.
cargo build library --lib
After doing it. You will write this in your dependency section in Cargo.toml.
library = {path = "./src/library"}
You can even use the absolute path of your directory.
library = {path = "C:/Users/Admin/Desktop/Rust/jawwad/src/library"}
Then write your library code in lib.rs file.
pub mod name1 {
pub fn name(a: i32) -> i32 {
println!("from diff file {}", a);
a * a
}
}
Here is the main.rs file.
use library;
fn main() {
println!("{}", library::name1::name(4));
}

Make nested module public in Rust

I'm starting a project to learn Rust and I fail at the most basic things, like setting up a proper module structure. My code looks like this:
// src/theorem/math.rs
pub mod theorem {
pub mod math {
use std::ops::{Add, Sub};
pub struct Point {
x: i32,
y: i32,
}
impl Add for Point {
// Omitted...
}
}
pub use math::{Point};
}
#[cfg(test)]
mod tests {
use theorem::math::{Point};
#[test]
fn add_point() {
let v1 = Point { x: 1, y: 1 };
let v2 = Point { x: 2, y: 2 };
assert_eq!(v1 + v1, v2);
}
}
I tried pub use, and I tried to write pub in front of everything, everywhere, but all I get is the message
error[E0432]: unresolved import `math::Point`
--> src/theorem/math.rs:28:20
|
28 | pub use math::{Point};
| ^^^^^ no `Point` in `math`
Which is a nice insight but does not help me. I read through the docs but there are no real examples for this case, but... it must be possible, right?
I have also tried to have a proper directory structure like src/theorem/math/point.rs but that did not work either.
What compiler version do you use? Since version 1.13, the error message looks like this:
error[E0432]: unresolved import `math::Point`
--> <anon>:16:20
|
16 | pub use math::{Point};
| ^^^^^ Did you mean `self::math`?
And pub use self::math::{Point}; is in fact the solution to your question! When you use a path, this path is always an absolute path. This means it is interpreted from the root of your crate. But there is no math module as direct child of the root module, hence the error.

How do I use a macro across module files?

I have two modules in separate files within the same crate, where the crate has macro_rules enabled. I want to use the macros defined in one module in another module.
// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)
// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
I currently hit the compiler error "macro undefined: 'my_macro'"... which makes sense; the macro system runs before the module system. How do I work around that?
Macros within the same crate
New method (since Rust 1.32, 2019-01-17)
foo::bar!(); // works
mod foo {
macro_rules! bar {
() => ()
}
pub(crate) use bar; // <-- the trick
}
foo::bar!(); // works
With the pub use, the macro can be used and imported like any other item. And unlike the older method, this does not rely on source code order, so you can use the macro before (source code order) it has been defined.
Old method
bar!(); // Does not work! Relies on source code order!
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
bar!(); // works
If you want to use the macro in the same crate, the module your macro is defined in needs the attribute #[macro_use]. Note that macros can only be used after they have been defined!
Macros across crates
Crate util
#[macro_export]
macro_rules! foo {
() => ()
}
Crate user
use util::foo;
foo!();
Note that with this method, macros always live at the top-level of a crate! So even if foo would be inside a mod bar {}, the user crate would still have to write use util::foo; and not use util::bar::foo;. By using pub use, you can export a macro from a module of your crate (in addition to it being exported at the root).
Before Rust 2018, you had to import macro from other crates by adding the attribute #[macro_use] to the extern crate util; statement. That would import all macros from util. This syntax should not be necessary anymore.
Alternative approach as of 1.32.0 (2018 edition)
Note that while the instructions from #lukas-kalbertodt are still up to date and work well, the idea of having to remember special namespacing rules for macros can be annoying for some people.
EDIT: it turns out their answer has been updated to include my suggestion, with no credit mention whatsoever 😕
On the 2018 edition and onwards, since the version 1.32.0 of Rust, there is another approach which works as well, and which has the benefit, imho, of making it easier to teach (e.g., it renders #[macro_use] obsolete). The key idea is the following:
A re-exported macro behaves as any other item (function, type, constant, etc.): it is namespaced within the module where the re-export occurs.
It can then be referred to with a fully qualified path.
It can also be locally used / brought into scope so as to refer to it in an unqualified fashion.
Example
macro_rules! macro_name { ... }
pub(crate) use macro_name; // Now classic paths Just Work™
And that's it. Quite simple, huh?
Feel free to keep reading, but only if you are not scared of information overload ;) I'll try to detail why, how and when exactly does this work.
More detailed explanation
In order to re-export (pub(...) use ...) a macro, we need to refer to it! That's where the rules from the original answer are useful: a macro can always be named within the very module where the macro definition occurs, but only after that definition.
macro_rules! my_macro { ... }
my_macro!(...); // OK
// Not OK
my_macro!(...); /* Error, no `my_macro` in scope! */
macro_rules! my_macro { ... }
Based on that, we can re-export a macro after the definition; the re-exported name, then, in and of itself, is location agnostic, as all the other global items in Rust 🙂
In the same fashion that we can do:
struct Foo {}
fn main() {
let _: Foo;
}
We can also do:
fn main() {
let _: A;
}
struct Foo {}
use Foo as A;
The same applies to other items, such as functions, but also to macros!
fn main() {
a!();
}
macro_rules! foo { ... } // foo is only nameable *from now on*
use foo as a; // but `a` is now visible all around the module scope!
And it turns out that we can write use foo as foo;, or the common use foo; shorthand, and it still works.
The only question remaining is: pub(crate) or pub?
For #[macro_export]-ed macros, you can use whatever privacy you want; usually pub.
For the other macro_rules! macros, you cannot go above pub(crate).
Detailed examples
For a non-#[macro_export]ed macro
mod foo {
use super::example::my_macro;
my_macro!(...); // OK
}
mod example {
macro_rules! my_macro { ... }
pub(crate) use my_macro;
}
example::my_macro!(...); // OK
For a #[macro_export]-ed macro
Applying #[macro_export] on a macro definition makes it visible after the very module where it is defined (so as to be consistent with the behavior of non-#[macro_export]ed macros), but it also puts the macro at the root of the crate (where the macro is defined), in an absolute path fashion.
This means that a pub use macro_name; right after the macro definition, or a pub use crate::macro_name; in any module of that crate will work.
Note: in order for the re-export not to collide with the "exported at the root of the crate" mechanic, it cannot be done at the root of the crate itself.
pub mod example {
#[macro_export] // macro nameable at `crate::my_macro`
macro_rules! my_macro { ... }
pub use my_macro; // macro nameable at `crate::example::my_macro`
}
pub mod foo {
pub use crate::my_macro; // macro nameable at `crate::foo::my_macro`
}
When using the pub / pub(crate) use macro_name;, be aware that given how namespaces work in Rust, you may also be re-exporting constants / functions or types / modules. This also causes problems with globally available macros such as #[test], #[allow(...)], #[warn(...)], etc.
In order to solve these issues, remember you can rename an item when re-exporting it:
macro_rules! __test__ { ... }
pub(crate) use __test__ as test; // OK
macro_rules! __warn__ { ... }
pub(crate) use __warn__ as warn; // OK
Also, some false positive lints may fire:
from the trigger-happy clippy tool, when this trick is done in any fashion;
from rustc itself, when this is done on a macro_rules! definition that happens inside a function's body: https://github.com/rust-lang/rust/issues/78894
This answer is outdated as of Rust 1.1.0-stable.
You need to add #![macro_escape] at the top of macros.rs and include it using mod macros; as mentioned in the Macros Guide.
$ cat macros.rs
#![macro_escape]
#[macro_export]
macro_rules! my_macro {
() => { println!("hi"); }
}
$ cat something.rs
#![feature(macro_rules)]
mod macros;
fn main() {
my_macro!();
}
$ rustc something.rs
$ ./something
hi
For future reference,
$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
Adding #![macro_use] to the top of your file containing macros will cause all macros to be pulled into main.rs.
For example, let's assume this file is called node.rs:
#![macro_use]
macro_rules! test {
() => { println!("Nuts"); }
}
macro_rules! best {
() => { println!("Run"); }
}
pub fn fun_times() {
println!("Is it really?");
}
Your main.rs would look sometime like the following:
mod node; //We're using node.rs
mod toad; //Also using toad.rs
fn main() {
test!();
best!();
toad::a_thing();
}
Finally let's say you have a file called toad.rs that also requires these macros:
use node; //Notice this is 'use' not 'mod'
pub fn a_thing() {
test!();
node::fun_times();
}
Notice that once files are pulled into main.rs with mod, the rest of your files have access to them through the use keyword.
I have came across the same problem in Rust 1.44.1, and this solution works for later versions (known working for Rust 1.7).
Say you have a new project as:
src/
main.rs
memory.rs
chunk.rs
In main.rs, you need to annotate that you are importing macros from the source, otherwise, it will not do for you.
#[macro_use]
mod memory;
mod chunk;
fn main() {
println!("Hello, world!");
}
So in memory.rs you can define the macros, and you don't need annotations:
macro_rules! grow_capacity {
( $x:expr ) => {
{
if $x < 8 { 8 } else { $x * 2 }
}
};
}
Finally you can use it in chunk.rs, and you don't need to include the macro here, because it's done in main.rs:
grow_capacity!(8);
The upvoted answer caused confusion for me, with this doc by example, it would be helpful too.
Note: This solution does work, but do note as #ineiti highlighted in the comments, the order u declare the mods in the main.rs/lib.rs matters, all mods declared after the macros mod declaration try to invoke the macro will fail.