I'm coding a hash in Rust for practice. The code looks like this:
pub fn get_fnv1a32(to_hash:&str) -> u32{
const OFFSET_BASIS:u32 = 2_166_136_261;
const PRIME:u32 = 16_777_619;
if !to_hash.is_empty(){
let mut hash = OFFSET_BASIS;
for b in to_hash.bytes(){
hash = hash ^ (b as u32);
hash = hash.wrapping_mul(PRIME);
}
hash
}
else
{
0
}
}
And this is the code I'm trying to use to test this:
mod fnv;
#[cfg(test)]
mod tests {
#[test]
fn get_correct_hash(){
assert_eq!(0x7a78f512, fnv::get_fnv1a32("Hello world!"));
}
#[test]
fn hash_handles_empty_string_correctly(){
assert_eq!(0, fnv::get_fnv1a32(""));
}
}
The test code is in lib.rs and the get_fnv1a32 function is in fnv.rs. They're both in the same directory. But when I try to run cargo test I keep getting these messages:
Compiling hashes v0.1.0 (U:\skunkworks\rust\hashes)
warning: function is never used: `get_fnv1a32`
--> src\fnv.rs:1:8
|
1 | pub fn get_fnv1a32(to_hash:&str) -> u32{
| ^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
error[E0433]: failed to resolve: use of undeclared type or module `fnv`
--> src\lib.rs:7:32
|
7 | assert_eq!(0x7a78f512, fnv::get_fnv1a32("Hello world!"));
| ^^^ use of undeclared type or module `fnv`
error[E0433]: failed to resolve: use of undeclared type or module `fnv`
--> src\lib.rs:12:23
|
12 | assert_eq!(0, fnv::get_fnv1a32(""));
| ^^^ use of undeclared type or module `fnv`
error: aborting due to 2 previous errors
I can't figure out what I'm doing wrong. I tried changing the mod fnv; line at the top to pub mod fnv; and that gets rid of the dead code warning but it doesn't fix the two errors. What do I need to do to get the get_fnv1a32 function to be visible in the lib.rs file?
Not that I would think it would matter but the version of rustc is rustc 1.41.0 (5e1a79984 2020-01-27)
The test module is separate from the outer module. Add
use super::*;
or an equivalent statement like use crate::fnv inside the tests module to make the fnv module visible.
Related
I have two modules with unit tests and I want to access constants/variables with expected test results from both of those modules.
File: src/lib.rs
mod other;
#[cfg( test )]
mod tests {
mod expected;
use crate::tests::expected::FOUR;
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!( result, FOUR );
}
}
File: src/other.rs
#[cfg( test )]
mod tests {
use crate::tests::expected::EIGHT;
#[test]
fn it_works() {
let result = 4 + 4;
assert_eq!( result, EIGHT );
}
}
File src/tests/expected.rs
pub const FOUR: i32 = 4;
pub const EIGHT: i32 = 8;
From src/lib.rs I can access the constants within expected.rs. But this is not true from src/other.rs. I get the follwing error:
error[E0603]: module `expected` is private
--> src/other.rs:3:20
|
3 | use crate::tests::expected::EIGHT;
| ^^^^^^^^ private module
|
note: the module `expected` is defined here
--> src/lib.rs:5:2
|
5 | mod expected;
| ^^^^^^^^^^^^^
I have no idea how to make expected public. Where would I place expected.rs or how would I make it accessible from the test code of other modules of the library?
I am trying to create a separate file/module that has functions that can deal with the LEDs or gyro for the stm32f3discovery. I am trying to pass the stm32f3 API that holds all of the registers into a function to then use inside.
When I run this code, I get an error saying "there is no field '###' on type '##'". How can I do this?
main.rs
#![no_std]
#![no_main]
use stm32f3::stm32f303;
mod my_api;
#[entry]
fn main() -> ! {
let periph = stm32f303::Peripherals::take().unwrap();
let gpioe = periph.GPIOE;
let rcc = periph.RCC;
my_api::led::setup_led(&gpioe, &rcc);
loop {
my_api::led::all_led_on(&gpioe);
}
}
my_api.rs
pub mod led {
pub fn setup_led<G, R>(gpio: &G, rcc: &R) {
*rcc.ahbenr.modify(|_, w| w.iopeen().set_bit()); //enables clock
*gpio.moder.modify(|_, w| {
w.moder8().bits(0b01);
w.moder9().bits(0b01);
w.moder10().bits(0b01);
w.moder11().bits(0b01);
w.moder12().bits(0b01);
w.moder13().bits(0b01);
w.moder14().bits(0b01);
w.moder15().bits(0b01)
});
}
pub fn all_led_on<G>(gpio: &G) {
*gpio.odr.modify(|_, w| {
w.odr8().set_bit();
w.odr9().set_bit();
w.odr10().set_bit();
w.odr11().set_bit();
w.odr12().set_bit();
w.odr13().set_bit();
w.odr14().set_bit();
w.odr15().set_bit()
});
}
pub fn all_led_off<G>(gpio: &G) {
*gpio.odr.modify(|_, w| {
w.odr8().clear_bit();
w.odr9().clear_bit();
w.odr10().clear_bit();
w.odr11().clear_bit();
w.odr12().clear_bit();
w.odr13().clear_bit();
w.odr14().clear_bit();
w.odr15().clear_bit()
});
}
}
Error
error[E0609]: no field `odr` on type `&G`
--> src/my_api.rs:30:15
|
29 | pub fn all_led_off <G> (gpio: &G) {
| - type parameter 'G' declared here
30 | *gpio.odr.modify(|_,w| {
| ^^^
It has this error for all of the calls onto any of the registers
Instead of using a generic to try and force our way into passing in a type that you don't know use something like:
let my_name: () = 39.2;
It will give an error that will tell you what the value on the right is and you can use that to work out what data type you can pass into the function. As shown printing variable type in rust
The following code fails to compile
// winservice.rs
#[macro_use] extern crate err_derive;
extern crate windows_service;
use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
#[derive(Debug, Error)]
pub enum WinServiceError {
#[error(display = "could not query windows services api")]
WinApiError(windows_service::Error),
}
impl From<windows_service::Error> for WinServiceError {
fn from(error: windows_service::Error) -> Self {
WinServiceError::WinApiError(error)
}
}
fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, WinServiceError> {
ServiceManager::local_computer(None::<&str>, request_access)
}
pub fn main() {
// get_manager();
}
I am getting the error
error[E0308]: mismatched types
--> src/winservice.rs:186:5
|
185 | fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, Error> {
| ----------------------------- expected `std::result::Result<windows_service::service_manager::ServiceManager, winservice::Error>` because of return type
186 | ServiceManager::local_computer(None::<&str>, request_access)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `winservice::Error`, found enum `windows_service::Error`
|
= note: expected type `std::result::Result<_, winservice::Error>`
found type `std::result::Result<_, windows_service::Error>`
Why isn't the Rust compiler auto converting the return type from windows_service::Error to winservice::Error?
Thanks to #Shepmaster's help, I was able resolve the error.
I did not realize that I was returning the result object directly. I had to unwrap the result object for the conversion to work.
The following code attempts to return a value of type Result<_, windows_services::Error> as Result<_, WinServiceError>.
fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, WinServiceError> {
ServiceManager::local_computer(None::<&str>, request_access)
}
But the following code works, because we are now creating a new Result object of the correct signature, and rust compiler performs the conversion between the error types while creating the new object.
fn get_manager(request_access: ServiceManagerAccess) -> Result<ServiceManager, WinServiceError> {
Ok(ServiceManager::local_computer(None::<&str>, request_access)?)
}
This question already has an answer here:
Can't understand Rust module system
(1 answer)
Closed 3 years ago.
I am reading the Rust Book, I am in the chapter 7.2, but I must be missing something, because I cannot organize my code in modules, the compiler (rustc 1.32.0) keeps giving me errors.
What I have read
I read rustc --explain E0433, which is the advice of the compiler, but I still cannot solve it.
I checked Rust by examples, and it seems that my code is correct, (my/mod.rs is using module my/nested.rs in its own folder)
I found some info on Internet, but it is of 4 years ago, and include the use of use, which is not yet in the book.
I also checked this question, but I am not using folders, and again, it gets away from the book explanation.
Minimal example
This is a minimal example that tries to mimic the "sound" example of the book, there is only two files: /src/main.rs and /src/m.rs.
main.rs
mod m;
fn main() {
let st_0 = m::St::new();
}
m.rs
pub mod m {
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
}
And this is what cargo tells me:
Compiling min v0.1.0 (/home/user/min)
error[E0433]: failed to resolve: could not find `St` in `m`
--> src/main.rs:3:19
|
3 | let st_0 = m::St::new();
| ^^ could not find `St` in `m`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
error: Could not compile `min`.
To learn more, run the command again with --verbose.
When you have everything in one file, like this:
main.rs
pub mod m {
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
}
mod m;
fn main() {
let st_0 = m::St::new();
}
you wrap the module with the
pub mod mode_name {
//code...
}
Once you put the module in another file, that wrapping goes away. The Rust book, shows it, but if you don't look carefully or if you are programming drunk, you may get confused with the pub mod instrument {...} of the nested module.
So m.rs has to look like this:
pub struct St {
a:i32,
b:i32,
}
impl St {
pub fn new() -> St{
println!("New St!");
St {
a: 12,
b: 13,
}
}
}
Why isn't Result<()> allowed when compiling this bit of Rust code? Is it a breaking change between Rust editions?
fn run() -> Result<()> {
let (tx, rx) = channel();
thread::spawn(move || {
do_things_with_tx(&exit_tx);
});
match exit_rx.recv() {
Ok(result) => if let Err(reason) = result {
return Err(reason);
},
Err(e) => {
return Err(e.into());
},
}
Ok(())
}
The compiler says:
error[E0107]: wrong number of type arguments: expected 2, found 1
--> src/main.rs:1000:18
|
1000 | fn run_wifi() -> Result<()> {
| ^^^^^^^^^^ expected 2 type arguments
When I tweak the return type to Result<(), Err>, it says:
error[E0107]: wrong number of type arguments: expected 2, found 0
--> src/main.rs:1000:29
|
1000 | fn run() -> Result<(), Err> {
| ^^^ expected 2 type arguments
This is from the wifi-connect project.
The definition of Result is, and has always been, the following:
pub enum Result<T, E> {
Ok(T),
Err(E),
}
This definition is even presented in the Rust Programming language, to show how simple it is. As a generic sum type of an OK outcome and an error outcome, it always expects two type parameters, and the compiler will complain if it cannot infer them, or the list of type arguments does not have the expected length.
On the other hand, one may find many libraries and respective docs showing a Result with a single type argument, as in Result<()>. What gives?
It's still no magic. By convention, libraries create type aliases for result types at the level of a crate or module. This works pretty well because it is common for those to produce errors of the same, locally created type.
pub type Result<T> = std::result::Result<T, Error>;
Or alternatively, a definition which can still purport as the original result type.
pub type Result<T, E = Error> = std::result::Result<T, E>;
This pattern is so common that some error helper crates such as error-chain, will automatically create a result alias type for each error declared.
As such, if you are using a library that may or may not use error-chain, you are expected to assume that mentions of Result<T> are local type aliases to a domain-specific Result<T, Error>. In case of doubt, clicking on that type in the generated documentation pages will direct you to the concrete definition (in this case, the alias).
From The Rust Programming Language section The ? Operator Can Only Be Used in Functions That Return Result
use std::error::Error;
use std::fs::File;
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("hello.txt")?;
Ok(())
}
TL;DR
use std::io::Result;
Link to the type description
Long answer
I believe that the top-voted answer given by E_net4 the comment flagger is correct. But it doesn't work if applied blindly. In both cases
this
pub type Result<T> = Result<T, Error>;
and this
pub type Result<T, E = Error> = Result<T, E>;
will give the cycle dependency error
error[E0391]: cycle detected when expanding type alias `Result`
--> src\main.rs:149:33
|
149 | pub type Result<T, E = Error> = Result<T, E>;
| ^^^^^^^^^^^^
|
= note: ...which immediately requires expanding type alias `Result` again
= note: type aliases cannot be recursive
= help: consider using a struct, enum, or union instead to break the cycle
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
So as much as users of SO don't want to admit it, but Gabriel soft is very close to elegant solution, because that type alias
pub type Result<T> = result::Result<T, Error>;
is straight from the standard library.
Here it is, our desired Result with 1 generic argument is defined in std::io (docs). To fix the problem I added
use std::io::Result;
fn some_func() -> Result<()> {
...
}
or
use std::io;
fn some_func() -> io::Result<()> {
...
}
rustc 1.62.1
i solved my own error by making a generic Result type to handle the error
As its says it require a generic of T and E, so to simplify things, i had to follow this way
pub type Result = result::Result<T, Error>;