How do I import from a sibling module?
Asked Answered
C

2

65

In src/lib.rs I have the following

extern crate opal_core;

mod functions;
mod context;
mod shader;

Then in src/context.rs I have something like this, which tries to import symbols from src/shader.rs:

use opal_core::shader::Stage;
use opal_core::shader::Shader as ShaderTrait;
use opal_core::GraphicsContext as GraphicsContextTrait;

use functions::*; // this import works fine
use shader::*; // this one doesn't

pub struct GraphicsContext {
    functions: Gl
}

fn shader_stage_to_int(stage: &Stage) -> u32 {
    match stage {
        &Stage::Vertex => VERTEX_SHADER,
        &Stage::Geometry => GEOMETRY_SHADER,
        &Stage::Fragment => FRAGMENT_SHADER,
    }
}

impl GraphicsContextTrait for GraphicsContext {

    /// Creates a shader object
    fn create_shader(&self, stage: Stage, source: &str) -> Box<ShaderTrait> {
        let id;

        unsafe {
            id = self.functions.CreateShader(shader_stage_to_int(&stage));
        }

        let shader = Shader {
            id: id,
            stage: stage,
            context: self
        };

        Box::new(shader)
    }
}

The problem is that the statement use shader::*; gives the error unresolved import.

I was reading the docs and they said that use statements always go from the root of the current crate (opal_driver_gl) so I thought shader::* should be importing opal_driver_gl::shader::* but it doesn't appear to do so. Do I need to use the self or super keywords here?

Concentric answered 5/6, 2015 at 23:27 Comment(5)
Have you looked at any of the other questions that mention the same error? If so, how does your question differ from them? Have you tried to make a smaller testcase?Armlet
I've checked out most of the 'unresolved import' questions. They mostly centre around getting symbols from outside a crate but I want to do the opposite. I'll try narrowing the problem down.Concentric
It's considered good practice to tell us what you've tried and what questions you've seen. Also include why those attempts and question don't work or what you don't understand from them. This prevents us from guessing what your real problem is, makes it easier for you to get answers, and generally improves your how useful your question is to future searchers.Armlet
I can't see any obvious cause, but... does shader contain any imports from context? Glob imports can cause issues if you end up with a module recursively depending on itself. Try removing the * and listing all the symbols you actually use.Maharashtra
Also does your shader module actually have any public items?Teacake
K
56

Note that the behavior of use has changed from Rust 2015 to Rust 2018. See What are the valid path roots in the use keyword? for details.

Rust 2018

To import a module on the same level, do the following:

random_file_0.rs

// Note how this is a public function. It has to be in order to be
// usable from other files (in this case `random_file_1.rs`)
pub fn do_something() -> bool {
    true
}

random_file_1.rs

use super::random_file_0;

#[test]
fn do_something_else() {
    assert!(random_file_0::do_something());
}

or an alternative random_file_1.rs:

use crate::random_file_0;

#[test]
fn do_something_else() {
    assert!(random_file_0::do_something());
}

lib.rs

mod random_file_0;
mod random_file_1;

See Rust By Example for more information and examples. If that doesn't work, here is the code it shows:

fn function() {
    println!("called `function()`");
}

mod cool {
    pub fn function() {
        println!("called `cool::function()`");
    }
}

mod my {
    fn function() {
        println!("called `my::function()`");
    }

    mod cool {
        pub fn function() {
            println!("called `my::cool::function()`");
        }
    }

    pub fn indirect_call() {
        // Let's access all the functions named `function` from this scope!
        print!("called `my::indirect_call()`, that\n> ");

        // The `self` keyword refers to the current module scope - in this case `my`.
        // Calling `self::function()` and calling `function()` directly both give
        // the same result, because they refer to the same function.
        self::function();
        function();

        // We can also use `self` to access another module inside `my`:
        self::cool::function();

        // The `super` keyword refers to the parent scope (outside the `my` module).
        super::function();

        // This will bind to the `cool::function` in the *crate* scope.
        // In this case the crate scope is the outermost scope.
        {
            use cool::function as root_function;
            root_function();
        }
    }
}

fn main() {
    my::indirect_call();
}

Rust 2015

To import a module on the same level, do the following:

random_file_0.rs:

// Note how this is a public function. It has to be in order to be
// usable from other files (in this case `random_file_1.rs`)
pub fn do_something() -> bool {
    true
}

random_file_1.rs:

use super::random_file_0;

#[test]
fn do_something_else() {
    assert!(random_file_0::do_something());
}

or an alternative random_file_1.rs:

use ::random_file_0;

#[test]
fn do_something_else() {
    assert!(random_file_0::do_something());
}

lib.rs:

mod random_file_0;
mod random_file_1;

Here is another example from a previous version of Rust By Example:

fn function() {
    println!("called `function()`");
}

mod my {
    pub fn indirect_call() {
        // Let's access all the functions named `function` from this scope
        print!("called `my::indirect_call()`, that\n> ");

        // `my::function` can be called directly
        function();

        {
            // This will bind to the `cool::function` in the *crate* scope
            // In this case the crate scope is the outermost scope
            use cool::function as root_cool_function;

            print!("> ");
            root_cool_function();
        }

        {
            // `self` refers to the current module scope, in this case: `my`
            use self::cool::function as my_cool_function;

            print!("> ");
            my_cool_function();
        }

        {
            // `super` refers to the parent scope, i.e. outside of the `my`
            // module
            use super::function as root_function;

            print!("> ");
            root_function();
        }
    }

    fn function() {
        println!("called `my::function()`");
    }

    mod cool {
        pub fn function() {
            println!("called `my::cool::function()`");
        }
    }
}

mod cool {
    pub fn function() {
        println!("called `cool::function()`");
    }
}

fn main() {
    my::indirect_call();
}
Knowle answered 6/6, 2015 at 21:37 Comment(3)
Thanks for the great information, unfortunately I already understand the basics. @DK i think has found the issue as i used cyclical glob imports. (I came from a Java world where import myPackage.*; is fine)Concentric
My problem is similar but I don't think you answered correctly Harrison... Infact I can't do this: play.rust-lang.org/…Habergeon
in my real problem "my" and "cool" are two different files, so two mods. But in my I can't recall cool with super:: neither with crate!Habergeon
F
0

How to use functions from file1 in another file:

file1.rs

pub fn app() {  // pub is necessary
    println("hi");
}

main.rs

// declare module you want to use here
// only main.rs and lib.rs can contain root module declarations, from other files, it becomes submodules

mod file1; 
fn main() {
    file1::app();
}
Fart answered 24/4, 2023 at 12:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.