Rust: Unresolved import: extern crate ignored in submodules

Created on 7 Sep 2014  路  8Comments  路  Source: rust-lang/rust

Given a module lib.rs:

pub mod foo;

and a submodule foo.rs:

extern crate libc;
use libc::size_t;
fn test() {
    let sz: size_t = 1024;
}

Compiling it with:

$ rustc --crate-type=rlib lib.rs

gives the following error:

foo.rs:4:5: 4:9 error: unresolved import `libc::size_t`. Did you mean `self::libc`?
foo.rs:4 use libc::size_t;
             ^~~~
error: aborting due to previous error

The extern crate line in foo.rs is ignored without any message, and compilation only succeeds if this line is moved to lib.rs. This behaviour is quite confusing as the error message doesn't lead you to the correct solution.

It would be nice if you could have extern crate declarations in all modules, but failing that, at least there should be a diagnostic that it is ignored in the submodule and required in the top level module of the crate.

A-diagnostics

Most helpful comment

You can have extern crate declarations in all modules. The error here is caused for a different reason.

use statements default to taking absolute paths from the crate root. There is no libc name defined in lib.rs, so the compiler is raising an error. There are 3 easy solutions here:

  • use self::libc::size_t;
  • use foo::libc::size_t;
  • Move extern crate libc; to lib.rs.

All 8 comments

You can have extern crate declarations in all modules. The error here is caused for a different reason.

use statements default to taking absolute paths from the crate root. There is no libc name defined in lib.rs, so the compiler is raising an error. There are 3 easy solutions here:

  • use self::libc::size_t;
  • use foo::libc::size_t;
  • Move extern crate libc; to lib.rs.

The error message mentions the first solution, btw.

When I read the first solution in the error message, I thought "well I'm not defining libc in this crate, so that doesn't apply here!".

use statements default to taking absolute paths from the crate root

Even though I have read this before, I still forgot this time (I work with 3 or 4 different languages in a given week!). Again, it's the difference between the intended behaviour and the _apparent_ behaviour wrt the user's mental model. It _appears_ to ignore the extern crate directly above the line with the error, which is confusing due to the implicit behaviour you describe. Perhaps the message could be clarified?

This is even more confusing (and I think a bug?) if you are trying to use parser macros (is that the right term?) from the module in question:

submodule foo.rs

extern crate serialize;
use self::serialize::json;

#[deriving(Decodable, Encodable)]
pub struct WindowOptions {
    pub width: u32,
    pub height: u32,
    pub fullscreen: bool,
}

This doesn't compile, but instead spews errors about unresolved names "Decodable" and "Encodable". If I move the extern crate json to the crate root and remove the self::, this compiles fine.

@jasonroelofs that's just due to how #[deriving] works. That just expands to

impl ::serialize::Decodable for WindowOptions { ... }

so it'll only work if serialize is imported in the crate root.

While that makes sense, the whole thing (modules, paths, use, etc) feels like a big "gotcha!" and is very confusing trying to learn all of the ins and outs.

The fact that deriving requires serialize to be brought in in the crate root is essentially a bug that will be fixed with hygienic top-level identifiers.

I think the serialize-not-at-the-root is fixed by $crate and otherwise I believe there's not much to do here (working as intended, solution in diagnostics, etc.)

Was this page helpful?
0 / 5 - 0 ratings