Why is the `std` module undeclared? [duplicate] - rust

This question already has answers here:
Use of undeclared type or module `std` when used in a separate module
(2 answers)
Closed 6 years ago.
I'm trying to read a single character from stdin, but I can't get it working. In different program, I used this exact same method and it worked.
let mut buffer = [0];
let _ = std::io::stdin().read(&mut buffer);
let a = buffer[0];
Compiling it gives this error:
src/befunge.rs:220:17: 220:31 error: failed to resolve. Use of undeclared type or module `std::io` [E0433]
src/befunge.rs:220 let _ = std::io::stdin().read(&mut buffer);

I assume that befunge.rs is not your crate root, but a submodule. Paths like std::io::stdin() that are used outside of a use ...; declaration are relative to the current module, not absolute. To make the path absolute, prefix :: (like a prefixed / in unix paths) -> ::std::io::stdin(). Alternatively you can use some part of the path, like:
use std;
std::io::stdin();
or
use std::io;
io::stdin();
If you are using a subpath, like std::io more than once in your module, it's usually best to use it at the top.
If you are in the crate root, there is no difference between ::std and std, because the relative lookup path is the root. It only matters in submodules. Also: paths in use declarations are always absolute -- to make them relative to the current module prefix self::.

Related

Saving a binary as a rust variable

I would like to have a rust program compiled, and afterwards have that compiled binary file's contents saved in another rust program as a variable, so that it can write that to a file. So for example, if I have an executable file which prints hello world, I would like to copy it as a variable to my second rust program, and for it to write that to a file. Basically an executable which creates an executable. I dont know if such thing is possible, but if it is I would like to know how it's done.
Rust provides macros for loading files as static variables at compile time. You might have to make sure they get compiled in the correct order, but it should work for your use case.
// The compiler will read the file put its contents in the text section of the
// resulting binary (assuming it doesn't get optimized out)
let file_contents: &'static [u8; _] = include_bytes!("../../target/release/foo.exe");
// There is also a version that loads the file as a string, but you likely don't want this version
let string_file_contents: &'static str = include_str!("data.txt");
So you can put this together to create a function for it.
use std::io::{self, Write};
use std::fs::File;
use std::path::Path;
/// Save the foo executable to a given file path.
pub fn save_foo<P: AsRef<Path>>(path: P) -> io::Result<()> {
let mut file = File::create(path.as_ref().join("foo.exe"))?;
file.write_all(include_bytes!("foo.exe"))
}
References:
https://doc.rust-lang.org/std/macro.include_bytes.html
https://doc.rust-lang.org/std/macro.include_str.html

No method write found in TcpStream in rust [duplicate]

I tried to compile the following program:
use std::io;
fn main() {
io::stdout().write(b"Please enter your name: ");
io::stdout().flush();
}
Unfortunately, compiler resisted:
error: no method named `write` found for type `std::io::Stdout` in the current scope
--> hello.rs:4:18
|
4 | io::stdout().write(b"Please enter your name: ");
| ^^^^^
|
= help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
= help: candidate #1: `use std::io::Write`
I found that I needed to do use std::io::{self, Write};. What does use std::io; actually do then and how do (if possible) I pull all names defined in std::io? Also, would it be a bad style?
What does use std::io; actually do then?
It does what every use-statement does: makes the last part of the used path directly available (pulling it into the current namespace). That means that you can write io and the compiler knows that you mean std::io.
How do I pull all names defined in std::io?
With use std::io::*;. This is commonly referred to as glob-import.
Also, would it be a bad style?
Yes, it would. Usually you should avoid glob-imports. They can be handy for certain situations, but cause a lot of trouble on most cases. For example, there is also the trait std::fmt::Write... so importing everything from fmt and io would possibly result in name-clashes. Rust values explicitness over implicitness, so rather avoid glob-imports.
However, there is one type of module that is usually used with a glob-import: preludes. And in fact, there is even a std::io::prelude which reexports important symbols. See the documentation for more information.

Dynamically generating arguments Clap

I'm trying to figure out how to dynamically generating arguments from input arguments with Clap.
What I'm trying to emulate with Clap is the following python code:
parser = argparse.ArgumentParser()
parser.add_argument("-i", type=str, nargs="*")
(input_args, additional_args) = parser.parse_known_args()
for arg in input_args:
parser.add_argument(f'--{arg}-bar', required=true, type=str)
additional_config = parser.parse_args(additional_args)
So that you can do the following in your command:
./foo.py -i foo bar baz --foo-bar foo --bar-bar bar --baz-bar bar
and have the additional arguments be dynamically generated from the first arguments. Not sure if it's possible to do in Clap but I assumed it was maybe possible due to the Readme stating you could use the builder pattern to dynamically generate arguments[1].
So here is my naive attempt of trying to do this.
use clap::{Arg, App};
fn main() {
let mut app = App::new("foo")
.arg(Arg::new("input")
.short('i')
.value_name("INPUT")
.multiple(true)
.required(true));
let matches = app.get_matches_mut();
let input: Vec<_> = matches.values_of("input").unwrap().collect()
for i in input {
app.arg(Arg::new(&*format!("{}-bar", i)).required(true))
}
}
Which does not obviously having the compiler scream at you for both !format lifetime and app.arg I'm mostly interesting in solving how I could generate new arguments to the app which then could be matched against again. I'm quite new to rust so it's quite possible this is not possible with Clap.
[1] https://github.com/clap-rs/clap
I assumed it was maybe possible due to the Readme stating you could use the builder pattern to dynamically generate arguments[1].
Dynamically generating argument means that, you can .arg with runtime values and it'll work fine (aka the entire CLI doesn't need to be fully defined at compile-time, this distinction doesn't exist in Python as everything is done at runtime).
What you're doing here is significantly more complicated (and specialised, and odd) as you're passing through unknown parameters then re-parsing them.
Now first of all, you literally can't reuse App in clap: most of its methods (very much including get_matches) take self and therefore "consume" the App and return something else, either the original App or a result. Although you can clone the original App before you get_matches it I guess.
But I don't think that's useful here: though I have not tried it should be possible do do what you want using TrailingVarArg: this would collect all trailing arguments into a single positional arg slice (you will probably need AllowLeadingHyphen as well), then you can create a second App with dynamically generated parameters in order to parse that sub-set of arguments (get_matches_from will parse from an iterator rather than the env args, this is useful for testing... or for this exact sort of situations).

#[allow(unused_must_use)] for one line [duplicate]

This question already has answers here:
How to disable unused code warnings in Rust?
(11 answers)
How to quiet a warning for a single statement in Rust?
(2 answers)
Closed 4 years ago.
I have lines that return Result. The result does not matter and I don't want unwrap() or any logging. (The frequent failures are expected)
How can I silence the unused warnings for only these lines?
#[allow(unused_must_use)] seems to work when applied to fn level, but this does not work:
#[allow(unused_must_use)]
std::fs::remove_file(&path1);
#[allow(unused_must_use)]
std::fs::remove_file(&path2);
Edit:
while let _ = .. works as a workaround, #[allow(unused..)] specifically exists for this case, and the compiler also suggests to use it. Reading let _ = .. adds another layer of thinking. (assign and then abandon) So I prefer #[allow(..)] although it is more verbose. (If I see let _ = .. frequent enough and I get used to it, I may change my preference)
So I searched around and found some codes that apply macros to the statement level.
This question asks for why #[allow(unused_must_use)] for a line doesn't work-- wrong syntax? bug? just unimplemented yet for unused_must_use?
Edit:
According to this:
How to quiet a warning for a single statement in Rust?
My code should work.
Reading these:
https://github.com/rust-lang/rust/issues/36675
https://github.com/rust-lang/rust/issues/15701
I tried the allow on the scope level and it worked.
#[allow(unused_must_use)] {
std::fs::remove_file(&path1);
std::fs::remove_file(&path2);
}

How can structs in separate files reference each other?

Using structs that reference each other is common in a single file, but when I separate the structs into two files, I get an error.
mod_1.rs
mod mod_2;
use mod_2::Haha;
pub struct Hehe {
obj: Haha,
}
fn main() {
Hehe(Haha);
}
mod_2.rs
mod mod_1;
use mod_1::Hehe;
pub struct Haha {
obj: Hehe,
}
fn main() {
Haha(Hehe);
}
This will produce an error. When compiling the mod_1.rs:
error: cannot declare a new module at this location
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
|
note: maybe move this module `mod_2` to its own directory via `mod_2/mod.rs`
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
note: ... or maybe `use` the module `mod_1` instead of possibly redeclaring it
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
When compiling the mod_2.rs:
error: cannot declare a new module at this location
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
|
note: maybe move this module `mod_1` to its own directory via `mod_1/mod.rs`
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
In mod_1.rs I use something from mod_2.rs and in mod_2.rs, I use mod_1.rs's thing, so I'd like to find a way to get rid of the cycle reference module problem.
Trying to get Rust to load files is a similar but different problem.
This is a common misunderstanding of Rust's module system. Basically, there are two steps:
You have to build a module-tree. This implies that there are not cycles in this module-tree and there is a clear parent-child relationship between nodes. This step is simply to tell Rust what files to load and has nothing to do with usage of certain symbols in different modules.
You can now reference each symbol in your module tree by its path (where each module and the final symbol name is separated by ::, for example std::io::read). In order to avoid writing the full path every time, you can use use declarations to refer to specific symbols by their simple name.
You can read a bit more on that in the Rust book chapter.
And again, to avoid confusion: in order to use a symbol from a module, you don't necessarily have to write mod my_module; in your module! For each non-root module of your project there is only one line in your entire project saying mod said_module; (the root module does not have such a line at all). Only once!
About your example: you first compiled mod_1.rs via rustc mod_1.rs. This means that mod_1 is the root module in your case. As explained above, the root module doesn't need to be declared via mod at all, but all other modules need to be declared exactly once. This means the mod mod_2; in mod_1.rs is completely correct, but the mod mod_1; in mod_2.rs is incorrect. The compiler even suggest the right thing to do:
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
You are already useing it, so you can just remove the line mod mod_1; and solve this error.
However, I think you are still thinking incorrectly about the module system. As mentioned above you first need to design a more or less fixed module tree which implies that you have one fixed root module. Whatever you pass to rustc is the root module and it doesn't make sense to use different modules as root module. In your project there should be one fixed root module. This could be mod_1 as explained above. But it's usually more idiomatic to call it lib for libraries and main for executables.
So again: first, draw your module tree on a piece of paper. Consider this fixed for the moment and then you can create the files and mod declarations appropriately.
Last thing: even when fixing the module system, your example won't work, because Haha and Hehe are types with infinite size. Fields of structs are directly put into the memory layout of the struct (without boxing them like in Java!). Thus you can't have cycles in struct definitions, except if you manually add a layer of indirection, like boxing the fields. Please read this excellent explanation on this issue.

Resources