I have encountered a strange error preventing one of my files from importing a module
This is my src directory
src/
functions.rs
main.rs
unit_test.rs
Here is unit_test.rs
mod functions;
#[cfg(test)] // only compiles on test
// make module f_test
mod f_test{
// mark function as test
#[test]
#[should_panic]
fn test_basic() {
assert_eq!();
panic!("oh no");
}
#[test]
fn test_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
#[test]
#[should_panic]
fn test_bad_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
}
When I try to run cargo test I get this
[vinessa#komputilo unitTest]$ cargo test
Compiling unitTest v0.1.0 (/home/vinessa/Dev/Rust/unitTest)
error[E0583]: file not found for module `functions`
--> src/unit_test.rs:1:5
|
1 | mod functions;
| ^^^^^^^^^
|
= help: name the file either unit_test/functions.rs or unit_test/functions/mod.rs inside the directory "src"
Strange thing, if I add "mod functions;" to main.rs, cargo won't complain about that file, only for unit_test.rs
I am lost please help
I think you want to declare mod functions in main.rs:
mod unit_test;
mod functions; // declare this module here
fn main() {
println!("Hello, world!");
}
I think you want this in unit_test.rs:
#[cfg(test)] // only compiles on test
// make module f_test
mod f_test{
use crate::functions; // use module here
// mark function as test
#[test]
#[should_panic]
fn test_basic() {
assert_eq!(1, 1);
panic!("oh no");
}
#[test]
fn test_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
#[test]
#[should_panic]
fn test_bad_add(){
assert_eq!(functions::add(1,2), 1 + 2);
}
}
Additionally, your #[should_panic] is incorrect as it stands.
Obligatory link: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
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 override/wrap the Libc vprintf(format, va_list) function with Rust code. To do so, I need to pass a VaList argument into unsafe code that also needs to catch unwind errors:
#![feature(c_variadic)]
extern crate libc;
use libc::{c_char, c_int};
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
if true {
::std::panic::catch_unwind(|| hook_fn(format, args)).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, args))
}
pub unsafe fn hook_fn(format: *const c_char, args: std::ffi::VaList) -> c_int {
0
}
fn main() {
println!("Hello, world!");
}
My code does not compile:
error[E0277]: the type `&mut std::ffi::VaListImpl<'_>` may not be safely transferred across an unwind boundary
--> src/main.rs:8:9
|
8 | ::std::panic::catch_unwind(|| hook_fn(format, args)).ok()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------ within this `[closure#src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`
| |
| `&mut std::ffi::VaListImpl<'_>` may not be safely transferred across an unwind boundary
|
= help: within `[closure#src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`, the trait `std::panic::UnwindSafe` is not implemented for `&mut std::ffi::VaListImpl<'_>`
= note: `std::panic::UnwindSafe` is implemented for `&std::ffi::VaListImpl<'_>`, but not for `&mut std::ffi::VaListImpl<'_>`
= note: required because it appears within the type `std::ffi::VaList<'_, '_>`
= note: required because it appears within the type `[closure#src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`
Some types, especially FFI types, can cause Undefined Behaviour if used after a panic. This safety is tracked by whether or not a type implements UnwindSafe, and VaList does not.
This is explained in the first "help" line of the error message:
= help: within `[closure#src/main.rs:8:36: 8:61 format:&*const i8, args:std::ffi::VaList<'_, '_>]`,
the trait `std::panic::UnwindSafe` is not implemented for `&mut std::ffi::VaListImpl<'_>`
The first "note" also gives you a possible solution:
note: `std::panic::UnwindSafe` is implemented for `&std::ffi::VaListImpl<'_>`, but not for `&mut std::ffi::VaListImpl<'_>`
It's telling you that it is safe to share immutable references to a VaListImpl across an unwind boundary. So you can fix your code by passing the value by reference instead:
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
if true {
::std::panic::catch_unwind(|| hook_fn(format, &args)).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, &args))
}
pub unsafe fn hook_fn(format: *const c_char, args: &std::ffi::VaList) -> c_int {
0
}
This helped fix the problem.
Not sure if this is the right way to fix this. Peter Halls suggestion above might still be right one. But it did not seem to fix the error for me.
#![feature(c_variadic)]
extern crate libc;
use libc::{c_char, c_int};
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
let ap : VaListImpl = args.clone();
if true {
::std::panic::catch_unwind(|| hook_fn(format, ap.clone())).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, args))
}
pub unsafe fn hook_fn(format: *const c_char, args: std::ffi::VaList) -> c_int {
0
}
fn main() {
println!("Hello, world!");
}
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
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.
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,
}
}
}