When I run use crate::feed; in src/cmdline.rs I expect that to import src/feed.rs, but it doesn't. Instead I get,
error[E0432]: unresolved import `crate::feed`
--> src/cmdline.rs:2:5
|
2 | use crate::feed;
| ^^^^^^^^^^^ no `feed` in the root
Despite the fact that src/feed.rs exists. However, if I panic and change it to mod feed; then I get
error[E0583]: file not found for module `feed`
--> src/cmdline.rs:2:1
|
2 | mod feed;
| ^^^^^^^^^
|
= help: to create the module `feed`, create file "src/cmdline/feed.rs"
Using mod super::
error: expected identifier, found keyword `super`
--> src/cmdline.rs:2:5
|
2 | mod super::feed;
| ^^^^^ expected identifier, found keyword
Or with use super::
error[E0432]: unresolved import `super::feed`
--> src/cmdline.rs:2:5
|
2 | use super::feed;
| ^^^^^^^^^^^ no `feed` in the root
File structure for files in question looks like this,
src/feed.rs
src/cmdline.rs
src/main.rs
I figured it out. The rust module system doesn't permit importing sibling files,
src/a.rs
src/b.rs
Full stop: a.rs can not import b.rs. What it will do is try to source it from
src/a/b.rs
If you're on this answer, none of this probably makes sense to you and you've wasted hours on this. This was a source of my confusion:
src/main.rs
Is actually special. Inside src/main.rs a mod will import a sibling file, (and also with the now deprecated mod.rs; or, with lib.rs). But the point is that your own rust files can't make use of rust code in sibling files.
I was able to make my imports work the way you describe by doing the following.
First in main.rs I import the module cmdline and each module I want to be able to use via crate::.
// file src/main.rs
mod cmdline;
mod feed; // <== import module to be able to use via `crate::feed`
fn main() {
cmdline::do_something();
}
Then in cmdline.rs I use create::feed.
// file src/cmdline.rs
use crate::feed; // <== import sibling module
pub fn do_something() {
feed::do_something_else();
}
And my feed.rs looks something like this.
// file src/feed.rs
pub fn d_something_else() {
// ...
}
From what I understand from experimenting is that you need to first use mod in your main.rs to define which modules are included in your crate.
Related
Error I get:
error[E0433]: failed to resolve: could not find `openssl` in `backend`
--> ...\src\...\swagger-0.12.1\src\connector.rs:41:34
|
41 | native_tls::backend::openssl::TlsConnectorBuilderExt::from_openssl(ssl);
| ^^^^^^^ could not find `openssl` in `backend`
error[E0433]: failed to resolve: could not find `openssl` in `backend`
--> ...\swagger-0.12.1\src\connector.rs:85:34
|
85 | native_tls::backend::openssl::TlsConnectorBuilderExt::from_openssl(ssl);
| ^^^^^^^ could not find `openssl` in `backend`
Compiling hyper v0.2.1
error: expected identifier, found `"rustc-serialize"`
--> ...\hyper-0.2.1\src\lib.rs:129:14
|
129 | extern crate "rustc-serialize" as serialize;
| ^^^^^^^^^^^^^^^^^ expected identifier
Generated a server stub user swagger. Ran into issues where cargo couldn't find openssl, giving an error like 'custom build something openssl-sys 0.9.24'. This was a known issue and I overcame it by downloading vcpkg, and using vcpkg to download openssl. Then using environment variables to point to the download folder so cargo could use openssl. But now the error seems to be that openssl doesn't exist in backend?
It also seems to specific to windows, any ideas?
Tried changing the version of native-tls to the most up to date version but it doesn't seem to have an affect at all. It looks like swagger's dependencies need updating but I literally just generated this stub...
You've landed on a flaw from the Rust documentation tools; it picks up what is in a package, but doesn't show the limits.
The backend module definition is defined as:
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub mod security_framework;
#[cfg(target_os = "windows")]
pub mod schannel;
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
pub mod openssl;
In other words, the situation is the following:
If you are on linux (i.e. not macOS, not windows, not iOS), then openssl is available
If you are on windows, then schannel is available
If you are on MacOS or iOS security_framework is available
You should, however, not be trying to target a specific backend, as this defeats the purpose of the library. Instead of importing native_tls::backend::openssl::TlsConnectorBuilderExt, import native_tls::TlsConnectorBuilder and let it decide what backend you need.
This may be easier said than done, however, since by the looks of your error this is caused by a third-party library, which indicates that it was only tested on Linux.
This question already has answers here:
Including a file from another that is not main.rs nor lib.rs
(1 answer)
How do I import from a sibling module?
(1 answer)
How can I include a module from another file from the same project?
(6 answers)
How to use one module from another module in a Rust cargo project?
(3 answers)
Closed 3 years ago.
Rust cannot find local file through declaration. I have the following file structure in src:
| main.rs
| lib.rs
| test.rs
| prog.rs
| file.rs
In main.rs I have
extern crate cratename;
mod prog;
use cratename::file1::File1;
...
prog::function() // This works
...
#[cfg(test)]
mod test;
In lib.rs I have
pub mod file1;
In test.rs I have
extern crate cratename
use cratename::file1::File1;
mod prog;
#[test]
...
prog::function() // This does not work
...
I keep getting the error
error[E0583]: file not found for module `prog`
I tried putting the declaration in lib.rs but that didn't work. I've tried numerous other permutations involving this declaration along with main.rs but none of it worked. If it helps, prog.rs doesn't contain a struct and it doesn't use the mod keyword, it only contains public functions. This has stumped me for a while. Thank you for your help.
I want to compile a simple rust program using a third party library named warp:
[package]
name = "hello-world-warp"
version = "0.1.0"
[dependencies]
warp = "0.1.18"
In src/main.rs:
use warp::{self, path, Filter};
fn main() {
// GET /hello/warp => 200 OK with body "Hello, warp!"
let hello = warp::path!("hello" / String)
.map(|name| format!("Hello, {}!", name));
warp::serve(hello)
.run(([127, 0, 0, 1], 3030));
}
When I run cargo build I see it download warp and lots of transitive dependencies, then I get the errors:
Compiling hello-world-warp v0.1.0 (<path>) error[E0432]: unresolved import `warp`
--> src/main.rs:3:12
|
3 | use warp::{self, path, Filter};
| ^^^^ no `warp` in the root
error: cannot find macro `path!` in this scope
I've gone through various docs on modules and crates. What am I doing wrong in this simple scenario?
The example you copied uses a syntax that works in the most recent edition of Rust, but you've accidentally set your Rust to emulate an old "2015" version of the language.
You must add:
edition = "2018"
to your Cargo.toml's [package] section.
When starting new projects, always use cargo new. It will ensure the latest edition flag is set correctly.
I have a Cargo project consisting of three files in the same directory: main.rs, mod1.rs and mod2.rs.
I want to import functions from mod2.rs to mod1.rs the same way I would import functions from mod1.rs to main.rs.
I've read about the file structure required but I don't get it - naming all the imported files mod will lead to minor confusion in the editor and also this just complicates the project hierarchy.
Is there a way to import/include files independently of directory structure as I would in Python or C++?
main.rs:
mod mod1; // Works
fn main() {
println!("Hello, world!");
mod1::mod1fn();
}
mod1.rs:
mod mod2; // Fails
pub fn mod1fn() {
println!("1");
mod2::mod2fn();
}
mod2.rs:
pub fn mod2fn() {
println!("2");
}
Building results in:
error: cannot declare a new module at this location
--> src\mod1.rs:1:5
|
1 | mod mod2;
| ^^^^
|
note: maybe move this module `src` to its own directory via `src/mod.rs`
--> src\mod1.rs:1:5
|
1 | mod mod2;
| ^^^^
note: ... or maybe `use` the module `mod2` instead of possibly redeclaring it
--> src\mod1.rs:1:5
|
1 | mod mod2;
| ^^^^
I can't use it as it doesn't exist as a module anywhere, and I don't want to modify the directory structure.
All of your top level module declarations should go in main.rs, like so:
mod mod1;
mod mod2;
fn main() {
println!("Hello, world!");
mod1::mod1fn();
}
You can then use crate::mod2 inside mod1:
use crate::mod2;
pub fn mod1fn() {
println!("1");
mod2::mod2fn();
}
I'd recommend reading the chapter on modules in the new version of the Rust book if you haven't already - they can be a little confusing for people who are new to the language.
Every file is a module and cannot import another without creating a new nested module.
a. Define modules in module index file
As #giuliano-oliveira's answer recommends.
Add pub mod mod1; pub mod mod2; in src/lib.rs / src/main.rs / src/foo/mod.rs.
b. Use #[path]
main.rs
#[path = "./mod2.rs"]
mod mod2;
fn run() { mod2::mod2fn() }
Why?
This is a common pitfall for new Rust devs and understandably so.
The reason for the confusion comes from an inconsistency in behavior of mod X for files in the same folder. You can use mod X in lib.rs which appears to import a file adjacent to it, but you can't do the same in mod1.rs or mod2.rs.
The code of every file belongs to a module. The full path of the file's module (e.g. foo::bar::baz) rather than the location of the file, determines how it resolves mod X. You can think of it as every module having a fixed spiritual home, but it may have members defined further up in the hierarchy (e.g. src/lib.rs might contain: mod foo { mod bar { pub fn hello() {} } } - although then you cannot use mod foo; alone in lib.rs).
In main.rs, you are in the top-level module crate.
mod mod1; creates a new module mod1, and adds the contents of ./mod1.ts to that module.
So all code inside ./mod1.rs is inside the crate::mod1 module.
When you call use mod2 inside ./mod1.rs, it sees that it is inside crate::mod1, whose spiritual home dir is src/mod1, and looks for either:
src/mod1/mod2.rs
src/mod1/mod2/mod.rs
The complexity comes from allowing modules to be directories and also files, instead of forcing each module to be its own directory (maybe trying to avoid the Java folder structure) which would have removed the ambiguity.
The key thing to remember is that lib.rs and mod.rs are special files that behave differently to other files in a directory.
They will always be in the module described by the parent folder path (e.g. src/foo/bar/mod.rs = foo::bar) while all other files belong to their own modules (src/foo/bar/baz.rs = foo::bar::baz).
The Rustonic Way
Rust has some opinions on this.
Using mod.rs is not recommended anymore, which is good because it has this special behavior from its siblings. But lib.rs and main.rs are still special.
If you want to put tests alongside your code (foo.rs + foo_test.rs), it's recommended you don't. I don't like this, so I use the path thing above, which I think is fine for tests because they are not exported anywhere. Having to declare tests in the module above feels wrong, and I don't like having to use foo/test.rs either.
If you don't want your mod statements all in your main file (eg: in main.rs you won't use some public members inside some module, in this example it is mod2) you can do the following:
structure your src this way:
main.rs
my_module:
mod.rs
mod1.rs
mod2.rs
then you can just mod my_module and use my_module::mod1, like so:
main.rs:
mod my_module;
use my_module::mod1;
fn main() {
println!("Hello, world!");
mod1::mod1fn();
}
my_module/mod.rs
pub mod mod1;
pub mod mod2;
my_module/mod1.rs
use super::mod2;
pub fn mod1fn() {
println!("1");
mod2::mod2fn();
}
While trying to use the sphinx matlab domain I can't get the MWE to work, provided on the extensions pypi site
There is always this Can't import module error. I'd guess, that the extension kind of generates pseudo modules from the m-code, but up to know I actually could not figure out, how this mechanism works.
The dir structure looks like this
root
|--test_data
| |--MyHandleClass.m
|
|--doc
|--------conf.py
|--------Makefile
|--------index.rst
The files MyHandleClass.m and index.rst contain the example code given on the package site and the conf.py starts like this
import sys, os
sys.path.append(os.path.abspath('.'))
sys.path.append(os.path.abspath('./test_data'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
"sphinxcontrib.matlab",
"sphinx.ext.autosummary",
"sphinx.ext.autodoc"]
autodoc_default_flags = ['members','show-inheritance','undoc-members']
autoclass_content = 'both'
mathjax_path = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default'
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
Error msg
WARNING: autodoc: failed to import module u'test_data'; the following exception was raised:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\sphinx\ext\autodoc.py", line 335, in import_object
__import__(self.modname)
ImportError: No module named test_data
E:\ME\doc\index.rst:13: WARNING: don't know which module to import for autodocumenting u'MyHandleClass' (try placing a "module" or "currentmodule" directive in the document, or giving an explicit module name)
After varying this and that maybe somebody out there has a clue?
Thanks for trying the matlabdomain sphinxcontrib extension. In order to use Sphinx to document MATLAB m-files, you need to add matlab_src_dir in conf.py as described in the Configuration section of the documenation. This is because the Python interpreter can't import a MATLAB m-file. Therefore you should not add your MATLAB root to the Python sys.path, or you will get the error you received. Instead set matlab_src_dir to the path containing the folder of your MATLAB project which you want to document.
Given your file structure, in order to document test_data use a conf.py with the following:
import os
# NOTE: don't add MATLAB m-files to `sys.path`
#sys.path.insert(0, os.path.abspath('.'))
# instead add them to `matlab_src_dir
matlab_src_dir = os.path.abspath('..') # MATLAB
Hope that does it! Please feel free to ask any more questions. I'm happy to help!