Is it possible to export a function and a macro with the same name from a module?
Example lib.rs
mod log;
fn foo() {
log::info!("");
log::info("");
}
In log.rs:
Using pub(crate) use info; conflicts with pub fn info() { .. }
Using #[macro_export] and #[macro_use] doesn't allow namespaces
Macros and functions belong to different namespaces so two with the same name should happily coexist. This compiles (playground):
macro_rules! info {
($v:expr) => {}
}
fn info(v: &str) { }
However, trouble seems to arise when when trying to make them public from within a module. Exporting the macro as shown in How do I use a macro across module files? seems to conflict somehow with the function declaration (playground):
mod log {
macro_rules! info {
($v:expr) => {}
}
pub(crate) use info;
pub fn info(v: &str) { }
}
error[E0255]: the name `info` is defined multiple times
--> src/lib.rs:8:5
|
6 | pub(crate) use info;
| ---- previous import of the value `info` here
7 |
8 | pub fn info(v: &str) { }
| ^^^^^^^^^^^^^^^^^^^^ `info` redefined here
|
= note: `info` must be defined only once in the value namespace of this module
help: you can use `as` to change the binding name of the import
|
6 | pub(crate) use info as other_info;
| ~~~~~~~~~~~~~~~~~~
I do not know if this is a bug or intended behavior. Either way it is confusing.
A workaround that I found was to declare the function in a separate module and then re-export it by wildcard in the original module (playground):
mod log {
mod imp {
pub fn info(v: &str) { }
}
pub use imp::*;
macro_rules! info {
($v:expr) => { }
}
pub(crate) use info;
}
You can do it the other way (i.e. putting the macro in a separate module) but the compiler strangely yields a warning that it didn't re-export anything even when it did (playground).
Related
I have the following structure:
Inside queues.rs I have a #[macro_export],
#[macro_export]
macro_rules! queue {...}
but I am not sure how to import it in lib.rs.
What I have looks like this:
use crate::utils::queues::*;
// use it here
let mut service_queue: Queue<isize> = queue![];
This throws an error
error: cannot find macro `queue` in this scope
--> src/broker.rs:54:51
|
54 | let mut service_queue: Queue<isize> = queue![];
| ^^^^^
|
= note: consider importing this macro:
crate::queue
= help: have you added the `#[macro_use]` on the module/import?
What is the correct way to type #[macro_use] here, and import my custom macros from utils?
You can use the queue! macro from lib.rs using the #[macro_use] attribute (playground):
#[macro_use]
mod utils {
#[macro_use]
mod queues {
macro_rules! queue {
() => { vec![] };
}
}
}
pub fn foo() {
let _service_queue: Vec<isize> = queue![];
}
In your existing code you are using #[macro_export] which means it is declared in the crate root scope and not in the utils::queues module. In your error message you can see the compile is suggesting to consider importing this macro: crate::queue.
To access it in this case (playground):
mod utils {
mod queues {
#[macro_export]
macro_rules! queue {
() => { vec![] };
}
}
}
pub fn foo() {
let _service_queue: Vec<isize> = queue![];
}
Note that in either case the use crate::utils::queues::*; statement does not help, in fact you'll get an unused_imports warning (unless you happen to have other items declared in that module).
There is also this trick (playground):
pub mod utils {
pub mod queues {
macro_rules! queue {
() => { vec![] };
}
pub(crate) use queue;
}
}
pub fn foo() {
let _service_queue: Vec<isize> = crate::utils::queues::queue![];
}
Aside: if you plan to use the macro in other crates and you wish to retain the module hierarchy (i.e. access from my_crate::utils::queues::queue! from my_other_crate) there is a (convoluted) way to do that.
I was trying to understand how (sub)module imports work when using wildcard paths. The simplest demonstration I could come up with is as follows, where two modules, or perhaps two crates, share the same module structure.
pub mod primary {
pub mod a {
pub mod b {
pub struct A(pub i32);
}
}
}
pub mod import {
pub use crate::primary::*;
// Compiles and executes fine with this commented out, but fails with
// "error[E0433]: failed to resolve: could not find `b` in `a`"
// otherwise. The error refers to the usage in the assert_eq macro
// pub mod a {}
}
fn main() {
assert_eq!(import::a::b::A(42).0, 42);
}
My general thought, was, since the first case, where the pub mod a {} is commented out works, the wildcard should expand all submodules the wildcard picks up into submodules in the path in which it is expanding. Is this not the case? If so, what's the appropriate way to think about?
The Use declarations doesn't have a lot of detail on this.
use with a * imports all the names, except for those that would conflict with names that already exist in the current module.
Compare:
pub mod primary {
pub fn f() {
println!("p::f");
}
}
pub mod import {
pub use crate::primary::*;
}
fn main() {
import::f();
}
which prints p::f to
pub mod primary {
pub fn f() {
println!("p::f");
}
}
pub mod import {
pub use crate::primary::*;
pub fn f() {
println!("import::f");
}
}
fn main() {
import::f();
}
which prints import::f.
This might seem obvious for functions and constants (it would otherwise make * very limited, making it impossible for upstream libraries to add any item without risking to break downstream users), but it might seem more confusing for modules.
You have to remember though that you can't define a module multiple times (ie. "reopen" a module). The following is illegal:
pub mod primary {
pub mod a {}
pub mod a {}
}
and fails with
error[E0428]: the name `a` is defined multiple times
--> src/lib.rs:3:5
|
2 | pub mod a {}
| --------- previous definition of the module `a` here
3 | pub mod a {}
| ^^^^^^^^^ `a` redefined here
|
= note: `a` must be defined only once in the type namespace of this module
You can solve this particular case by adding one more level:
pub mod primary {
pub mod a {
pub mod b {
pub struct A(pub i32);
}
}
}
pub mod import {
pub mod a {
pub use crate::primary::a::*;
}
}
fn main() {
assert_eq!(import::a::b::A(42).0, 42);
}
A wildcard import creates aliases to all items on the top level of the module.
In your example, since primary contains only one item, a, the wildcard import creates an alias import::a, which refers to the module primary::a.
Whenever conflicts arise, explicitly named items are given higher precedence than items that were imported via a wildcard. Effectively, you can shadow a wildcard import by declaring a new item or by importing it by name from another module.
Each mod declaration declares a different module. There is no implicit merging of items in modules that happen to have the same name or alias.
Rust has support for both pub and pub(super). pub makes it so the parent module can access an item... and pub(super) seems to also do exactly the same thing. I've tried playing with the example below, and swapping pub and pub(super) seems to have no effect:
#![allow(dead_code)]
mod outer {
pub(super) fn outer_foo() { inner::inner_foo(); }
mod inner {
pub(super) fn inner_foo() { println!("hello world!"); }
}
}
fn top_level_foo() { outer::outer_foo(); }
Why would you ever use one over the other?
Playground link.
In your example, if you change your inner module to be public, then the difference would become clear.
For example, this works because outer::inner::inner_foo is visible from the main module:
#![allow(dead_code)]
mod outer {
pub(super) fn outer_foo() { inner::inner_foo(); }
pub mod inner {
pub fn inner_foo() { println!("hello world!"); }
}
}
fn top_level_foo() { outer::outer_foo(); }
fn main() {
outer::inner::inner_foo();
}
If you kept inner_foo as pub(super) it would've been only visible from the outer module (because super refers to the super-module, outer in the case of something inside inner), hence the above code wouldn't compile and you would see this error:
|
13 | outer::inner::inner_foo();
| ^^^^^^^^^ private function
|
note: the function `inner_foo` is defined here
Notice that pub can also take crate as an argument, making the function public within the crate itself, but not to other crates.
I'm building a wrapper around a DLL. This DLL gives me access to a database engine which implements an OOP design pattern. This requires me to create multiple overlapping traits that cover all the functionality:
pub trait CursorStatement { /* ... */ }
pub trait CursorTable { /* ... */ }
pub trait CursorStatementTable { /* ... */ }
...
I want to be able to bring these traits in scope so that I can call the functions without having to list every trait. Right now I'm doing:
mod traittest;
use traittest::*;
fn test() -> Result<(), AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
The problem with use foo::* is that it puts everything from the module into my namespace, which I don't want.
In the example above, I don't have to type traittest::Table or traittest::Cursor, I just have to type Table or Cursor. However, I want to have to prefix those objects with the module name so when I'm reading the code I know where the objects came from. I might want to create a Table object in my local file that is distinguished from the one coming from the module.
I also don't want to have to do the following because if I later have to add a new trait I will have to update a bunch of other source files that depend on this module:
mod traittest;
use traittest::{CursorStatement, CursorStatementTable, CursorTable, /* ... */};
I tried creating a Traits supertrait that would inherit all other traits as shown in Is there any way to create a type alias for multiple traits?, but it doesn't work because I can't implement the trait for anything because there's nothing that would be an implementation of every trait in the file:
pub trait Traits: CursorStatement, CursorTable, CursorStatementHandle, /* ... */ {}
If I could create a named scope for all the traits, that would work, but I can't figure out how to make Rust happy with this idea:
let traits = {
pub trait CursorTable { /* ... */ }
}
It looks like this trait_group macro might do the trick but it's not obvious to me how I could use it to solve my problem.
Here's my entire program
mod traittest {
#[derive(Debug)]
pub struct AceError {
code: u32,
description: String,
}
pub trait CursorTable {
fn get_handle(&self) -> u32; // impl's must write this function
fn fields(&self) -> String {
return format!("(get_handle() -> {})", self.get_handle());
}
}
pub struct Table {
pub handle: u32,
pub table_name: String,
}
pub struct Cursor {
pub handle: u32,
}
impl Table {
pub fn new(handle: u32, table_name: &str) -> Result<Table, AceError> {
let table = Table {
handle: handle,
table_name: table_name.to_string(),
};
return Ok(table);
}
}
impl CursorTable for Table {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
impl CursorTable for Cursor {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
pub trait Traits: CursorTable {} /* super trait to bring all other traits in scope */
}
use traittest::Traits;
fn test() -> Result<(), traittest::AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
and here's the error I get:
warning: unused import: `traittest::Traits`
--> src/main.rs:49:5
|
49 | use traittest::Traits;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0599]: no method named `fields` found for struct `traittest::Table` in the current scope
--> src/main.rs:54:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Table>` here
| the method is available for `std::sync::Arc<traittest::Table>` here
| the method is available for `std::rc::Rc<traittest::Table>` here
...
15 | pub struct Table {
| ---------------- method `fields` not found for this
...
54 | println!("t.fields={}", t.fields());
| ^^^^^^ method not found in `traittest::Table`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
error[E0599]: no method named `fields` found for struct `traittest::Cursor` in the current scope
--> src/main.rs:55:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Cursor>` here
| the method is available for `std::sync::Arc<traittest::Cursor>` here
| the method is available for `std::rc::Rc<traittest::Cursor>` here
...
20 | pub struct Cursor {
| ----------------- method `fields` not found for this
...
55 | println!("c.fields={}", c.fields());
| ^^^^^^ method not found in `traittest::Cursor`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
I finally figured out a solution I can live with, in case anybody else is looking for a solution to this problem.
In your module where you define your traits, create a sub-module with all the traits, like so:
pub mod Traits
{
pub trait CursorTrait
{
fn get_handle ( &self ) -> u32; // impl's must write this function
fn fields ( &self ) -> String
{
return format! ( "(get_handle() -> {})", self.get_handle() );
}
}
}
Now in your other modules, if you want to bring the traits in scope without bringing in the entire module, you can just bring in the submodule, like so:
mod foo; use foo::Traits::*;
I started grouping code for one of my projects into module files. I encountered a lot of warnings about unused code for functions in those modules, but the functions are actually used (privately within the module).
An example from my project:
// ...
// Line 46:
fn calc_p(word: &str, dict: &Dictionary) -> f32
{
if !dict.contains_key(word) {
return 0.0;
}
let total: u32 = dict.values().sum();
dict[word] as f32 / total as f32
}
...
But at line 13 in the same file, same module the function is clearly used:
// ...
pub fn suggest_corrections(to_be_corrected: &str, dict: &Dictionary) -> Vec<(f32, String)>
{
let candidates = create_candidates(to_be_corrected, dict);
let mut weighted_candidates = candidates
.into_iter()
.map(|w| (calc_p(&w, dict), w)) // Line 13 - calc_p used here
.collect::<Vec<_>>();
weighted_candidates.sort_by(|a, b| b.partial_cmp(a).unwrap());
weighted_candidates
}
// ...
Yet I get the compiler warning:
warning: function is never used: `calc_p`, #[warn(dead_code)] on by default
--> src/spellcheck/corrections.rs:46:1
|
46 | fn calc_p(word: &str, dict: &Dictionary) -> f32
| _^ starting here...
47 | | {
48 | | if !dict.contains_key(word) {
49 | | return 0.0;
50 | | }
51 | |
52 | | let total: u32 = dict.values().sum();
53 | | dict[word] as f32 / total as f32
54 | | }
| |_^ ...ending here
I thought maybe it's because the module corrections is not public, but I also marked the module as public and still get the same warning.
I tried to reproduce the behaviour using the playground, but if the module is defined in the same file it seems to work. The warnings also happen for me during a TravisCI build.
Why is the function marked as unused although it's actually used in the same file in the same module?
I'm using Rust 1.15 / 1.16.
Why is the function marked as unused although it's actually used in the same file in the same module?
Because unused code is a transitive calculation, and the code that calls that function cannot be called from outside the crate. The compiler is correct here.
The first error I see is:
warning: static item is never used: `ALPHABET`, #[warn(dead_code)] on by default
--> src/spellcheck/edits.rs:3:1
That's defined as:
src/spellcheck/edits.rs
static ALPHABET : &'static str = "abcdefghijklmnopqrstuvwxyz";
So it's not public, and can only be used from inside the module.
It's called from replaces and inserts. Both of those are used from edits1, a public function. Is the module containing it (edits) public?
src/spellcheck/mod.rs
mod edits;
pub mod corrections;
pub mod dictionary;
Nope, it is not. So where is edits1 called from? kodecheck_spellcheck::spellcheck::corrections::create_candidates, a non-public function. This is called by suggest_corrections, a public function, inside the public module corrections.
Let's look up the tree...
src/lib-spellcheck.rs
// #FIXME do we really need this here or move to sub-modules?
#[macro_use]
extern crate nom;
extern crate regex;
mod spellcheck;
Ah. For whatever reason, you've decided to introduce a completely nested private module spellcheck inside the crate (which is why the full path earlier is kodecheck_spellcheck::spellcheck::corrections::create_candidates).
From this, we can see that kodecheck_spellcheck::spellcheck cannot be accessed from outside the crate; it's not pub.
Let's create an example that uses the crate. This the the best way to see if it's true and would have been easy for you to test yourself:
examples/foo.rs
extern crate kodecheck_spellcheck;
fn main() {
kodecheck_spellcheck::spellcheck::corrections::create_candidates();
}
Compiling this has the error:
error: module `spellcheck` is private
--> examples/foo.rs:4:5
|
4 | kodecheck_spellcheck::spellcheck::corrections::create_candidates();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We could also create a MCVE:
mod spellcheck {
mod edits {
static ALPHABET: &'static str = "";
pub fn edits1() {
println!("{}", ALPHABET);
}
}
pub mod corrections {
pub fn create_candidates() {
::spellcheck::edits::edits1();
}
}
}
fn main() {}
Note that this differs from your example because main is empty. Your library crate doesn't have a mainmethod that calls anything. You could also explicitly specify that it's a library crate, but this is less well-known:
#![crate_type="lib"]
mod spellcheck {
mod edits {
static ALPHABET: &'static str = "";
pub fn edits1() {
println!("{}", ALPHABET);
}
}
pub mod corrections {
pub fn create_candidates() {
::spellcheck::edits::edits1();
}
}
}
Because there's a private module where all the code is, nothing outside this crate can call anything inside the crate. Therefore every method is unreachable.
To fix it, I'd suggest combining src/spellcheck/mod.rs into src/lib-spellcheck.rs. You could also just make the module public, but I see no reason to have the extra module.
I also see no reason to rename src/lib.rs to src/lib-spellcheck.rs; it's far more idiomatic to just leave it lib.rs.
Additionally, you should go ahead and become comfortable with Rust style. Braces go on the same line as the signature:
fn calc_p(word: &str, dict: &Dictionary) -> f32 {
// ...
Tools like rustfmt will help you apply the proper style.