Why do I need to use self::core::ops? - rust

I'm trying to use Mul from core.
This is suggested by the compiler and works:
extern crate core;
use self::core::ops::Mul;
but why doesn't
extern crate core;
use core::ops::Mul;
work?
I get the error error: unresolved import `core::ops::Mul`. Did you mean `self::core::ops`?

An extern crate x; loads x into the current namespace. use statements are absolute paths unless they start with self::, so if you put your extern crate core; anywhere but the crate root then you need to specify an absolute path or use self::.
mod foo {
mod bar {
extern crate core;
use foo::bar::core::ops::Mul;
// or `use self::core::ops::Mul;`
// or even `use super::bar::core::ops::Mul;` if you’re mad
// but not `use core::ops::Mul;`.
}
}
… but as a general rule you shouldn’t use core directly anyway. All the stable stuff from it is available in std which is included automatically.

It turns out that I am supposed to use use std::ops::Mul;.

Related

Project structure in rust -- adding extra files

I am learning rust and am super confused at the project structure for cargo projects. I am using this page (and the rust book) for reference.
I am trying to separate my project for different structs so they can have their own file, similar to cpp and classes.
so if I have
src/main.rs
src/struct_name.rs
and I create the mod for it:
pub mod struct_name
{
pub struct _struct_name
{}
}
I should be able to do this in main.rs:
mod struct_name;
But the problem I am having is when I am trying to include external crates. For example, I'm trying to implement clap and use macros. So I do the following in igloo.rs:
#[macro_use]
extern crate clap;
use clap::{Arg, App};
pub mod struct_name
{
pub struct _struct_name
{//do clap things}
}
I am given the error E0468 "an 'extern crate' loading macros must be at the crate root". Does this mean I can never use macros outside of main.rs or lib.rs? How can I somehow export these functions so that I can use them in struct_name.rs? I get that I could make export functions in main.rs or lib.rs, but if I am using the mod in main.rs and lib.rs, then struct_name.rs would never see the exported functions, right?
In main.rs:
Macros imported at the top of the crate are avaliable everywhere in the crate.
#[macro_use]
extern crate clap;
mod struct_name
In struct_name.rs:
You only need to define a module in its parent.
use clap::{Arg, App};
// do things

What does #[cfg(test)] do when placed at the top of lib.rs?

I'm writing a Rust library (generated from cargo) with unit tests.
I'd like to use the extern crate maplit in my unit tests to be able to use JavaScript-like hashmap literals. I don't want to use maplit in my library code.
maplit provides a macro that apparently must be activated using #[macro_use]. The only way I've been able to get this all working is to place this at the top of lib.rs:
#[cfg(test)] #[macro_use] extern crate maplit;
// my crate-specific stuff
At this point I realized I don't know what exactly #[cfg(test)] does. I'm using it in my tests. These are included with library code, as per the convention, like so:
// some library code
#[cfg(test)]
mod test {
use super::*;
// tests here
}
I had thought that the line #[cfg(test)] was marking what follows until the end of the file (or block?) as only applicable to the test configuration.
If so, then putting this directive at the top of lib.rs seems like a problem. Won't my entire library be dropped when I compile a distribution?
I've tried to find documentation on what exactly #[cfg(test)] does, but to no avail.
#[....]
The above is a Rust Attribute which is like an annotation in other languages. For example; in Java we have #Annotation(....) for methods and classes. Unlike annotation the rust attribute can be an expression that follows the attribute syntax.
#[cfg(....)]
The above is a compiler configuration attribute. The cfg() is one of many built-in attributes.
#[cfg(test)]
The above tells the Rust compiler that the following code should only be compiled when the test configuration is active. You can have other configuration attributes like debug, windows or features.
#[cfg(test)] #[macro_use] extern crate maplit;
Is the same as
#[cfg(test)]
#[macro_use]
extern crate maplit;
Which tells the Rust compiler to only compile the next line if the test configuration is active, and the next line tells Rust to only use macros from the following crate.
If so, then putting this directive at the top of lib.rs seems like a problem. Won't my entire library be dropped when I compile a distribution?
The #[cfg(...)] attribute only applies the compiler condition upon the thing it is attached to.
When you place the attribute at the top of the file followed by a space. The attribute is attached to the current module or crate.
As shown here from the documentation example, the crate_type is applied to the entire file:
// General metadata applied to the enclosing module or crate.
#![crate_type = "lib"]
// A function marked as a unit test
#[test]
fn test_foo() {
/* ... */
}
// A conditionally-compiled module
#[cfg(target_os = "linux")]
mod bar {
/* ... */
}
// A lint attribute used to suppress a warning/error
#[allow(non_camel_case_types)]
type int8_t = i8;
// Inner attribute applies to the entire function.
fn some_unused_variables() {
#![allow(unused_variables)]
let x = ();
let y = ();
let z = ();
}

Bring custom derive macro into namespace via plugin

Is it possible to reduce the boilerplate in using a library (as the library author) from:
#![feature(plugin)]
#![plugin(myplugin)]
#[macro_use]
extern crate myplugin_derive;
#[derive(MyPlugin)]
// ...
to something more like:
#![feature(plugin)]
#![plugin(myplugin)]
#[derive(MyPlugin)]
// ...
That is, since I know anyone using myplugin wants to use #[derive(MyPlugin)], is there a way of bringing MyPlugin into scope with #![plugin(myplugin)] only?

How do you refer to functions in a crate from an exported crate macro in rust?

I'm trying to write some debugging helper macros. So I create a crate to hold all of them, and referred to the crate externally using phase(plugin):
#[cfg(test)]
#[phase(plugin)]
extern crate debugging;
That successfully exports the macros into the crate.
However, for some of these tools I wanted to invoke functions from the crate, for example:
#[macro_export]
macro_rules! trace(
{$($arg:tt)*} => {
{
extern crate debug;
let s = ::macros::logger(); // <---- This!
let _ = s.write_line(format_args!(::std::fmt::format, $($arg)*).as_slice());
}
};
)
Using a global namespace, ie. ::macros::logger works if the macro is placed into macros.rs and imported from the crate root of a crate.
However, what I'm trying to achieve here is the same thing when the macro has to invoke a call from its own crate.
If the macro expanded correctly, I believe:
let s = ::crate_name::logger();
Would be the way to do it, but the crate with the macro cannot refer to itself by name in this way. It generates errors like:
src/macros.rs:52:15: 52:20 error: failed to resolve. Maybe a missing `extern crate debugging`?
src/macros.rs:52 let s = ::debugging::logger();
^~~~~
src/macros.rs:49:1: 56:2 note: in expansion of trace!
src/file.rs:26:11: 26:29 note: expansion site
...and finally just so we're completely clear about what I'm trying to do:
crate debugging:
lib.rs
fn logger()
macros.rs
macro_rules! trace(...) // <--- Trying to figure out what to put here...
crate foo:
lib.rs
#[phase(plugin)] extern crate debugging;
fn test_thing() {
trace!("{}", ...); // <--- So debugging::logger() is invoked here
}
So, is there some way to do this from a macro?
For now, the correct thing to do is use an absolute path like that and then do some reexports in the original crate so that path resolves.
I.e. in lib.rs put
mod debugging {
pub use logger;
}
which reexports the top level function logger as debugging::logger. There is work being done that makes this saner, e.g. $crate which expands to name of the crate from which the macro came (when used externally), or to nothing (when used internally); this isn't necessarily the final design, but it is improving.
For anyone else who finds this, it's worth noting that you cannot use from a crate marked with phase plugin. To import the symbols locally (as per the accepted answer), you need to do this:
#[cfg(test)]
mod debug {
#[phase(plugin)]
extern crate debugging;
extern crate debugging;
pub use self::debugging::debug;
}
Notice the double extern crate debugging, because typically you wouldn't want to export a syntax extension module as part of the code.

How do I compile a multi-file crate in 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.
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
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
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.)

Resources