Problem with dependencies in Macros


I have tried my hand at a macro that should wrap slog macro calls to make it easier to have consistent messages.

I can use this macro like this:

gen_log_error!(1010, "Things are {how} bad");

Which generates a mcro called log_error_1010.

I have one issue and one question:

Whenever I try to call my macro from another crate I get an error:

use of undeclared type or module `slog`

I'm not sure why.
In my proc_macro created I declared slog as a dependency so it should transitively be also available in the crate using it, no?
I've also specified the full name slog::error

What am I missing?

I'd love to auto generate documentation for the inner macro and put all required named arguments in it.
In my example above I'd love to say that how is a required parameter.
But I can't find a way to parse the string and get the named arguments. format_args requires a string literal which I don't have at that point.

Any ideas?

Bonus Question: Does another library maybe already exist to define log message catalogs?

Here is the code in full

use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, ExprLit, Lit, Token};

struct Log {
    code: ExprLit,
    msg: ExprLit,

impl Parse for Log {
    fn parse(input: ParseStream) -> Result<Self> {
        let code: ExprLit = input.parse()?;
        let msg = input.parse()?;

        Ok(Log {

pub fn gen_log_error(input: TokenStream) -> TokenStream {
    let Log {
    } = parse_macro_input!(input as Log);

    let code = match &code.lit {
        Lit::Int(code) => code,
        _ => panic!("[code] needs to be Not a number")

    let msg = match &msg.lit {
        Lit::Str(msg) => msg,
        _ => panic!("[msg] needs to be a string literal")

    let msg = format!("E{code}: {msg}", code = code, msg = msg.value());
    let macro_name= format_ident!("log_error_{}", code.base10_digits());

    let expanded = quote! {
        macro_rules! #macro_name {
            ($log:expr, #$tag:expr, $($arg:tt)*) => {
                slog::error!($log, #$tag, #msg, $($arg)*);
            ($log:expr, $($arg:tt)*) => {
                slog::error!($log, #msg, $($arg)*);


This is my very first time using Rust so any other pointers are welcome as well.

You need to re-export slog in your crate using:

pub use slog;

Then your macro can emit imports into your crate like ::your_crate::slog::foo_bar.

When you say your crate which one do you mean?
The proc-macro crate or the "customer" using the crate?

I tried it before in the proc-macro crate but I get this error:

error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`

I tried various other combinations but no luck so far.

Right.. Usually you have a non-proc-macro crate that users import, which re-exports the proc-macro along with any dependencies the proc-macro needs. See @Yandros' post for more details.

@alice & @Yandros Thank you very much.

I got it working using your solution.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.