Can't get Rust's name scoping rules to work with a test sub module

Hi there

I have a test which basically copies a function. The function compiles, the test module, however, does not:

Cargo.toml

[dependencies]
pest = "2.0"
pest_derive = "2.0"

src/lib.rs

extern crate pest;
#[macro_use]
extern crate pest_derive;

use pest::Parser;
#[derive(Parser)]
#[grammar = "parser.pest"]
pub struct MathParser;

pub fn dummy() {
    let parse_number = MathParser::parse(Rule::number, "-273.15");
    println!("{:?}", parse_number);
    match parse_number {
        Ok(_) => (),
        Err(_) => panic!("parse of number failed"),
    }

}

#[cfg(test)]
mod tests {
    use pest::Parser;
    pub struct MathParser;
    #[test]
    fn parse_number() {
        let parse_number = MathParser::parse(Rule::number, "-273.15");
        println!("{:?}", parse_number);
        match parse_number {
            Ok(_) => (),
            Err(_) => panic!("parse of number failed"),
        }
    }
}

src/parser.pest

field = { (ASCII_DIGIT | "." | "-")+ }

float = @{ "-"? ~ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }

number = { float }

unitful_quantity = @{ number ~ "u\"" ~ ANY ~ "\""}

quantity = { unitful_quantity | number }

atomic_expression = { LETTER+ | quantity }

expression =  { atomic_expression | bracketed_expression }
bracketed_expression = {" (" ~ expression ~ ")" }


WHITESPACE = _{ " " | "\t" | "\n" }
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!"\n" ~ ANY)* ~ "\n") }

cargo build builds dummy without any error message, cargo test yields

error[E0433]: failed to resolve: use of undeclared type `Rule`
  --> mathparserlib/src/lib.rs:26:46
   |
26 |         let parse_number = MathParser::parse(Rule::number, "-273.15");
   |                                              ^^^^ use of undeclared type `Rule`

error[E0599]: no function or associated item named `parse` found for struct `tests::MathParser` in the current scope
  --> mathparserlib/src/lib.rs:26:40
   |
23 |     pub struct MathParser;
   |     ---------------------- function or associated item `parse` not found for this
...
26 |         let parse_number = MathParser::parse(Rule::number, "-273.15");
   |                                        ^^^^^ function or associated item not found in `tests::MathParser`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `parse`, perhaps you need to implement it:
           candidate #1: `Parser`

warning: unused import: `pest::Parser`
  --> mathparserlib/src/lib.rs:22:9
   |
22 |     use pest::Parser;
   |         ^^^^^^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default

error: aborting due to 2 previous errors; 1 warning emitted

Some errors have detailed explanations: E0433, E0599.
For more information about an error, try `rustc --explain E0433`.
error: could not compile `mathparserlib`

I tried MathParser::Rule but to no avail.

Inside of mod tests you defined a second struct MathParser type, but this inner type does not have #[derive(Parser)] so it does not implement the Parser trait.

Instead of defining a new type with the same name, I expect you want your test module to refer to the type defined in its parent module:

mod tests {
    use pest::Parser;
    use super::MathParser;
    // ...
}

It's also a common pattern to use a wildcard import to allow a test module to easily refer to all names from the parent module:

mod tests {
    use super::*;
    // ...
}
1 Like

thank you very much

I should not have stupidly copied the top level definitions, I got something along the lines of "can only derive on top level so I deleted that"

the use super::* is also pretty useful, thank you

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.