Unable to Access Function within Same Module

Good morning!

I'm a formerly seasoned programmer with experience in Pascal, C, C++, Java, perl, and some python; however, most of my dev experience is from the late '90s to early 2000s (hence the languages you see). I'm trying to learn Rust but can't seem to understand why I can't call a function declared within my module from another function within the module. Ignore the use of print!() vice println!() inside the print_* functions because they actually contain long multiline strings rather than the dummy strings shown in this paste.

Here's the code at issue that is generating errors I can't resolve:

// module for parsing cmdline options

use std::collections::HashMap;

pub fn parse_options(argv: Vec) -> HashMap<String, String> {
return options::parse_options(argv);
}

mod options {
use std::collections::HashMap;
use std::env;
use std::io;
use std::process;

const help_opt: String = "--help".to_string();
const help_opt_short: String = "-h".to_string();

pub fn parse_options(argv: Vec<String>) -> HashMap<String, String> {
    let parsed = HashMap::new();

    // state machine for parsing arguments

    // state 0: -- if no options, print short help
    if (argv.len() == 0) {
        options::print_usage_synopsis();
        process::exit(0);
    }
    // state 1: -- check if --help passed anywhere
    else if (argv.contains(&help_opt) || argv.contains(&help_opt_short)) {
        options::print_full_help();
        process::exit(0);
    }

    return parsed;
}

fn print_usage_synposis() {
    print!("usage_synopsis\n");
}

fn print_full_help() {
    print!("full_help\n");
}

}

In my main.rs, I do the following:

use std::collections::HashMap; use std::env; use std::io; use std::process;

pub mod options;

fn main() {
let argv: Vec = env::args().collect();

println!("foo v0.0");

println!("args passed were: {:?}", argv);

options::parse_options(argv);

process::exit(0);

}

My src directory structure is as follows:

src/
|
+----main.rs
|
+----options.rs

Running cargo build results in the following:

error[E0433]: failed to resolve: use of undeclared crate or module `options` --> src/options.rs:25:13 | 25 | options::print_usage_synopsis(); | ^^^^^^^ | | | use of undeclared crate or module `options` | help: an enum with a similar name exists: `Option`

error[E0433]: failed to resolve: use of undeclared crate or module options
--> src/options.rs:30:13
|
30 | options::print_full_help();
| ^^^^^^^
| |
| use of undeclared crate or module options
| help: an enum with a similar name exists: Option

I have tried calling the print_* functions with no namespace qualifiers, with the options:: namespace, the options::options:: namespace, and with the crate::options namespace. Nothing works. What am I missing here?

FYSA, namespaces are "new" to me -- I learned programming on my own from Basic then Pascal in high school and C, C++, and Java in college from the early-mid 1990s and then Perl and Python in the early 2000s (i.e., before 2005). So I'm familiar with the namespaces concept as far as multi-module C and C++ code before the dawn of the "namespaces" as a concept that you had to declare separately from class definitions themselves.

Thank you and have a great day!

--Jason

You might want to read about modules' visibility in Rust: Visibility - Rust By Example

Thank you; I already did that and it was rather opaque and not that enlightening. :frowning:

And just to be clear -- I would not reach out for assistance from y'all if I hadn't already tried to figure it out by reading the relevant rust docs and searching for keywords to see if anyone else had had a similar struggle.

I respect y'all's time and would rather figure it out on my own rather than ask for help -- I am a strong believer in struggling through a problem before asking for help because that's the way you get a stronger understanding. However, I have hit a roadblock here because the errors don't seem to make sense to me or to jibe with what I read in the rust docs about modules and scoping.

Unless they start with crate::, another crate name, or a module imported with use, all paths (i.e., qualified names) are relative to the current module. In this case, you want to access print_usage_synopsis() and print_full_help() from parse_options(). Since they are all in the same module, the unqualified name is sufficient:

     pub fn parse_options(argv: Vec<String>) -> HashMap<String, String> {
         let parsed = HashMap::new();
 
         // state machine for parsing arguments
 
         // state 0: -- if no options, print short help
         if (argv.len() == 0) {
-            options::print_usage_synopsis();
+            print_usage_synopsis();
             process::exit(0);
         }
         // state 1: -- check if --help passed anywhere
         else if (argv.contains(&help_opt) || argv.contains(&help_opt_short)) {
-            options::print_full_help();
+            print_full_help();
             process::exit(0);
         }
 
         return parsed;
     }

But for the compiler to find print_usage_synopsis(), the typo in its name must be fixed:

-    fn print_usage_synposis() {
+    fn print_usage_synopsis() {
         print!("usage_synopsis\n");
     }

You say that you've already tried it with the unqualified name. What error are you getting when you try that?

1 Like

Could you format code according to pinned post? Currently it's a bit hard to understand how exactly does it look.

1 Like

Another problem: you have both pub mod options; and mod options {. Unlike some other languages, In Rust, modules in files don't need to declare what module they are. So, what you've done there instead is to create two modules named options, one inside the other. For example, the full path of print_full_help is crate::options::options::print_full_help.

To fix this, remove the mod options { that you have inside of options.rs.

2 Likes

Thank you -- I did not see the typo. That explains why it refused to allow me to access the function within the module. I looked at the code so many times and overlooked that.

Re the removal of "options::" the call was originally

print_usage_synopsis()

and

print_full_help()

The typo was what I was not seeing. Thank you!

Thank you. I had originally not had the pub mod options; in there. However, I added it after the first attempts did not permit accessing the functions. All caused by the overlooked typo.

Thank you!

In case it helps in the future, note that the compiler tries to suggest any similar names it finds in its error message:

error[E0425]: cannot find function `print_usage_synopsis` in this scope
  --> src/options.rs:25:13
   |
25 |             print_usage_synopsis();
   |             ^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `print_usage_synposis`
...
38 |     fn print_usage_synposis() {
   |     ------------------------- similarly named function `print_usage_synposis` defined here

For more information about this error, try `rustc --explain E0425`.

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.