Description
Someone on IRC asked how to reference a pub static
in an external crate, noting that cratename::value
was not resolving (it turned out they were writing this reference in a sub-module, not the top-level library).
While making sample code to illustrate the ways to get such code to work, I found an oddity.
(Note: It is probably just something where our error messages need to be improved. Though there may be a reasonable argument that use cratename
should just work anywhere, to ease cut-and-pasting code from sub-modules into the top-level lib.)
It is valid to say use cratename::value
and it is valid to say use local_name = cratename;
, but it is not valid to say use cratename;
in the top-most level of the library/program. (It is valid to say use cratename
in an inner module within the lib; just not the lib itself.)
From my tests, it appears that the reason for this is that an extern crate cratename
declaration implicitly imports cratename
into the relative-path roots for the top-level of the library.
Test code:
// n.rs
#![crate_type="lib"]
pub static C : int = 3;
// end of n.rs
// m.rs
extern crate n;
#[cfg(version1a)] use n::C;
#[cfg(version2a)] use local_n = n;
#[cfg(version3a)] use n;
#[cfg(version1a)] pub fn read() -> int { C }
#[cfg(version2a)] pub fn read() -> int { local_n::C }
#[cfg(version3a)] pub fn read() -> int { n::C }
#[cfg(version4a)] pub fn read() -> int { ::n::C }
#[cfg(version5a)] pub fn read() -> int { n::C }
#[cfg(version6a)] pub fn read() -> int { self::n::C }
#[cfg(version1b)]
#[cfg(version2b)]
#[cfg(version3b)]
#[cfg(version4b)]
#[cfg(version5b)]
pub fn read() -> int { sub_m::read() }
mod sub_m {
#[cfg(version1b)] use n::C;
#[cfg(version2b)] use local_n = n;
#[cfg(version3b)] use n;
#[cfg(version1b)] pub fn read() -> int { C }
#[cfg(version2b)] pub fn read() -> int { local_n::C }
#[cfg(version3b)] pub fn read() -> int { n::C }
#[cfg(version4b)] pub fn read() -> int { ::n::C }
#[cfg(version5b)] pub fn read() -> int { super::n::C }
}
pub fn main() {
println!("n::C is {}", read());
}
// end of m.rs
Here's what currently happens:
% rustc -L/tmp /tmp/n.rs
% rustc --out-dir /tmp /tmp/n.rs
% for v in version{1a,2a,4a,5a,6a,1b,2b,3b,4b,5b,3a} ; do echo $v; rustc -L/tmp --cfg $v /tmp/m.rs && ./m ; done
version1a
n::C is 3
version2a
n::C is 3
version4a
n::C is 3
version5a
n::C is 3
version6a
n::C is 3
version1b
n::C is 3
version2b
n::C is 3
version3b
n::C is 3
version4b
n::C is 3
version5b
n::C is 3
version3a
/tmp/m.rs:6:23: 6:24 error: unresolved import (maybe you meant `n::*`?)
/tmp/m.rs:6 #[cfg(version3a)] use n;
^
error: aborting due to previous error
%
This is a hint that the problem is probably that we end up with some sort of resolve collision when we do use n
at the top-level. It is possible that the fix here would simply be a better error message explaining the problem.