Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compile a multi-file crate in Rust?

Tags:

rust

I'm trying to figure out how to compile multi-file crates in Rust, but I keep getting a compile error.

I have the file I want to import into the crate thing.rs:

mod asdf {
    pub enum stuff {
        One,
        Two,
        Three
    }
}

And my crate file test.rc:

mod thing;

use thing::asdf::*;

fn main(){

} 

When I run rust build test.rc I get:

test.rc:3:0: 3:19 error: `use` and `extern mod` declarations must precede items
test.rc:3 use thing::asdf::*;
          ^~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

There's obviously something simple about how modules, crates and use work that I'm just not getting. My understanding was that mod something; for files in the same directory or extern mod something; for libraries on the library path caused the object file to be linked. Then use would allow you to import parts of the module into the current file, function or module. This seems to work for stuff in the core library.

This is with version 0.6 of the rust compiler.

like image 291
Paul Johnson Avatar asked Jun 27 '13 10:06

Paul Johnson


People also ask

What is a .crate file Rust?

A crate is a compilation unit in Rust. Whenever rustc some_file.rs is called, some_file.rs is treated as the crate file. If some_file.rs has mod declarations in it, then the contents of the module files would be inserted in places where mod declarations in the crate file are found, before running the compiler over it.

What is the crate root?

The crate root is a source file that the Rust compiler starts from and makes up the root module of your crate (we'll explain modules in depth in the “Defining Modules to Control Scope and Privacy” section). A package is a bundle of one or more crates that provides a set of functionality. A package contains a Cargo.

What is MOD RS in Rust?

From the Rust reference: Note: Previous to rustc 1.30, using mod.rs files was the way to load a module with nested children. It is encouraged to use the new naming convention as it is more consistent, and avoids having many files named mod.rs within a project.


1 Answers

You just need to put the use at the top of the file:

use thing::asdf::*;

mod thing;

fn main() {}

This looks very strange, but

  1. It's what the error message says (anything that you can put at the top level that is not use or extern mod is an "item", including mods), and
  2. It's how Rust name resolution works. use is always relative to the top of the crate, and the whole crate is loaded before name resolution happens, so use thing::asdf::*; makes rustc look for thing as a submodule of the crate (which it finds), and then asdf as a submodule of that, etc.

To illustrate this last point better (and demonstrate the two special names in use, super and self, which import directly from the parent and current module respectively):

// crate.rs

pub mod foo {
    // use bar::baz; // (an error, there is no bar at the top level)

    use foo::bar::baz; // (fine)
    // use self::bar::baz; // (also fine)

    pub mod bar {
        use super::qux; // equivalent to
        // use foo::qux; 

        pub mod baz {}
    }
    pub mod qux {}
}

fn main() {}

(Also, tangentially, the .rc file extension no longer has any special meaning to any Rust tools (including in 0.6), and is deprecated, e.g. all the .rc files in the compiler source tree were recently renamed to .rs.)

like image 91
huon Avatar answered Oct 21 '22 04:10

huon