Code change:
When building the documentation (or running the doctests) of a few crates, such as libsecp256k1, in beta or nightly, rustdoc crashes with this message (while it works fine on stable, even if with some pulldown warnings): Crate regressed from stable to beta (). Crate regressed from stable to beta (). cc
Crate is also affected, cc
Can someone investigate and see if we can fix this?
I'll give it a look.
Both and worked just fine for me...
I ran on on my own system without updating my nightly and hit the ICE:
So maybe we need a backport to beta? That may have already happened, this is a relatively old beta run.
First we'd need to find what's crashing...
I've tried bisecting in the range ... and the result is... ? Needs to reverify later. Test script: Command: Edit: Verified, in the doc test passes and in the doc test ICEs. cc
I just tried documenting with that exact nightly and it crashed for me? <details</detailsThe issue is still present on the latest nightly: <details</details
Negative, it is still crashing with . <details</details
This seems potentially somewhat suspicious from the commit we bisected to:
Here's a minimal example: We used to run everybody-loops before macro expansion. Which meant that such macros would be wiped clean (as well as all of their potential users). We now run it later. These macros get cleaned up after we've run them through resolve. This interacts badly with how we do builtin lints. Builtin lints are basically things where writing a lint pass to do the check would be annoying because it requires a global analysis, but we can instead collect up the requisite information beforehand during other global passes, and then when we are actually linting a node we can just check what lints have accumulated for that node. For example, the unused lints work by paring down a list of "used" things, and then buffering up an "unused" lint for each thing that's still unused after the resolution check. We can't warn immediately because we'd have to recompute what the lint level is. The unused macro lint is naturally a builtin lint. Macro expansion queues up a list of "this macro is unused" lints for each macro node id. Of course, with the everybody-loops pass, we delete the macros within the blocks. Whoops. And this causes the lint pass to notice that some of the accumulated builtin lints were not checked (because their nodes no longer exist), and complain and ICE. Whoops. To fix this, we can: not run early lints in rustdoc mode. Or really, any lints. Except for rustdoc-specific ones. Idk. Conditioning that invocation on rustdoc mode. Remove the invocation entirely -- whilst macros and derive can't remove nodes, proc macro attrs can. I need to check if this ICE can be triggered with a proc macro. Add complex checking that ensures that buffered lints for removed nodes stay removed I'd rather lean towards conditioning or removing that invocation
For some reason I'm not unable to get this ICE to trigger by writing a proc macro that does this. Curious. Perhaps this occurs pre-macro resolution.
Oh, I think the proc macro just "gets there first" because it's defined outside. Okay. So checking for rustdoc mode should be enough.

Related discussion:
text: // Put the lint store levels and passes back in the session. cx.lint_sess.restore(&sess.lint_store); <del> // Emit all buffered lints from early on in the session now that we've // calculated the lint levels for all AST nodes. for (_id, lints) in cx.buffered.map { for early_lint in lints { span_bug!(early_lint.span, "failed to process buffered lint here"); </del> <ins> // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. // // Rustdoc runs everybody-loops before the early lints and removes // function bodies, so it's totally possible for linted // node ids to not exist (e.g. macros defined within functions for the // unused_macro lint) anymore. So we only run this check // when we're not in rustdoc mode. (see issue #47639) if !sess.opts.actually_rustdoc { for (_id, lints) in cx.buffered.map { for early_lint in lints { span_bug!(early_lint.span, "failed to process buffered lint here"); } </ins> } } }