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.
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;
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.)
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 nolibc
name defined inlib.rs
, so the compiler is raising an error. There are 3 easy solutions here:use self::libc::size_t;
use foo::libc::size_t;
extern crate libc;
tolib.rs
.