Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The macro recursion limit is too low #22552

Closed
carllerche opened this issue Feb 20, 2015 · 11 comments
Closed

The macro recursion limit is too low #22552

carllerche opened this issue Feb 20, 2015 · 11 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.

Comments

@carllerche
Copy link
Member

I started hitting the recursion limit with the following macro (which isn't actually complete yet either)

    use nixtest::assert_errno_eq;
    use libc::c_int;

    macro_rules! check_errno {
        ($errno:ident) => {{
            assert_errno_eq(stringify!($errno), $errno as c_int);
        }};

        ($errno:ident, $($rest:ident),+) => {{
            check_errno!($errno);
            check_errno!($($rest),*);
        }};
    }

    check_errno!(
        EPERM,
        ENOENT,
        ESRCH,
        EINTR,
        EIO,
        ENXIO,
        E2BIG,
        ENOEXEC,
        EBADF,
        ECHILD,
        EAGAIN,
        ENOMEM,
        EACCES,
        EFAULT,
        ENOTBLK,
        EBUSY,
        EEXIST,
        EXDEV,
        ENODEV,
        ENOTDIR,
        EISDIR,
        EINVAL,
        ENFILE,
        EMFILE,
        ENOTTY,
        ETXTBSY,
        EFBIG,
        ENOSPC,
        ESPIPE,
        EROFS,
        EMLINK,
        EPIPE,
        EDOM,
        ERANGE,
        EDEADLK,
        ENAMETOOLONG,
        ENOLCK,
        ENOSYS,
        ENOTEMPTY,
        ELOOP,
        ENOMSG,
        EIDRM,
        ECHRNG,
        EL2NSYNC,
        EL3HLT,
        EL3RST,
        ELNRNG,
        EUNATCH,
        ENOCSI,
        EL2HLT,
        EBADE,
        EBADR,
        EXFULL,
        ENOANO,
        EBADRQC,
        EBADSLT,
        EBFONT,
        ENOSTR,
        ENODATA,
        ETIME,
        ENOSR,
        ENONET,
        ENOPKG,
        EREMOTE,
        ENOLINK,
        EADV,
        ESRMNT,
        ECOMM,
        EPROTO,
        EMULTIHOP,
        EDOTDOT,
        EBADMSG,
        EOVERFLOW,
        ENOTUNIQ,
        EBADFD,
        EREMCHG,
        ELIBACC,
        ELIBBAD,
        ELIBSCN,
        ELIBMAX,
        ELIBEXEC,
        EILSEQ,
        ERESTART,
        ESTRPIPE,
        EUSERS,
        ENOTSOCK,
        EDESTADDRREQ,
        EMSGSIZE,
        EPROTOTYPE,
        ENOPROTOOPT,
        EPROTONOSUPPORT,
        ESOCKTNOSUPPORT,
        EOPNOTSUPP,
        EPFNOSUPPORT
@kmcallister kmcallister added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Feb 20, 2015
@eddyb
Copy link
Member

eddyb commented Feb 20, 2015

You don't need recursion for this macro, was your original usecase more complicated?
Also, the example is missing at least a closing ).

@carllerche
Copy link
Member Author

Yeah, it got truncated when copying :P How would I implement the macro without recursion?

@kennytm
Copy link
Member

kennytm commented Feb 21, 2015

@carllerche

macro_rules! check_errno {
    ($($errno:ident),+) => {{
        $( assert_errno_eq(stringify!($errno), $errno as c_int); )+
    }}
}

@steveklabnik
Copy link
Member

/cc @rust-lang/lang, @rust-lang/compiler is there any discussion on what this limit should be?

@eddyb
Copy link
Member

eddyb commented Mar 4, 2016

@steveklabnik IMO we should implement macro expansion without recursing in the compiler.
That would mean it could potentially never terminate, but at least we wouldn't have errors like this.
It could also be much more efficient, by reusing ranges of tokens instead of copying them over and over again.

@jonas-schievink
Copy link
Contributor

@eddyb Isn't the recursion limit supposed to prevent never-terminating compilations? Being able to stack-overflow the compiler with a #![recursion_limit = "5000"] sounds bad. (I always thought it limits recursive user code, be it macros, monomorphizations, etc. and not rustc-internal recursion)

That said, the recursion limit isn't doing a very good job if this is what it's supposed to do:

macro_rules! m {
    ( $( $i:ident )* ) => {
        m!( $($i)* $($i)* )
    };
}

fn main() {
    let i = m!(m);
}

This hangs, but doesn't cause a stack overflow. Memory usage slowly increases starting at about 100 MB.

@eddyb
Copy link
Member

eddyb commented Mar 4, 2016

Macros and monomorphization both recurse in the Rust compiler and would otherwise end up in stack overflows.

@Mark-Simulacrum
Copy link
Member

This has been encountered in the wild once more (#38541).

I'm going to mark this as E-easy since I think the primary thing that needs to change is just this https://github.com/rust-lang/rust/blob/master/src/libsyntax/ext/expand.rs#L1041 line, which needs to be updated to a larger value. I'm going to suggest 1024.

@jseyfried Do you agree with the easy designation?

@Mark-Simulacrum Mark-Simulacrum added the E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. label May 1, 2017
@sirideain
Copy link
Contributor

I would be interested in taking this one as a good way to figure out the process of contributing.

@Mark-Simulacrum
Copy link
Member

@sirideain Great! Let us know if you need assistance.

@eddyb
Copy link
Member

eddyb commented May 2, 2017

cc @nikomatsakis Another good use for stacker!

bors added a commit that referenced this issue May 7, 2017
…fried

Increase macro recursion limit to 1024

Fixes #22552
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
Projects
None yet
Development

No branches or pull requests

8 participants