Change:
When trying to compile any Rocket application in the 2015 edition the compiler says an error occured without showing any actual error: Switching to the 2018 edition fixes the problem, by either showing errors or properly compiling the application. Minimal reproduction: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This leads to in the parser, which apparently does not produce any output nor tracing. label +I-ICE
The fatal error is raised here:
Here's an overview of what is happening. The proc-macro creates something along the lines of: In 2015, when it goes to parse the arguments, it sees as a normal identifier. It then sees which is unexpected, which creates an unexpected error in the parser. However, it attempts to recover by assuming the user forgot a . The parser then sees and assumes that must be the start of a closure. However, it then sees when it expected a to start the closure arguments. This emits another unexpected error. However, this hits the FatalError because it believes it has not made any progress. The original error has not yet been emitted, and the compiler exits without a message. Normally this sequence of events won't happen because the would be different, and it would just emit a normal error. However, rocket is using which causes all of the tokens to end up with the same span. I think the use of in is questionable, and not really explained in the code why it is there. Maybe this is to prevent the parser from getting stuck somehow? That could really use some comments explaining its purpose. Without understanding the purpose there, it is hard to guess at a possible fix. Here is a minimal repro: And a proc-macro named :
That check was in , but unfortunately there isn't much of a description explaining why it was .
IIRC I believe that it was to deduplicate some redundant errors that occurred otherwise. This whole ordeal reminds me that we should be trying to parse blocks in 2015 when encountering the kw in idents and then encountering parse errors to emit clear diagnostics about setting the edition (I thought we were doing that already). Macros can also set the edition metadata in the , IIRC (it might be an unstable API), which can let 2018 proc-macros work even in 2015 crates (do we even want to open that can of worms, I don't think so). I'm glad to see this is a parser error, it means that we can fix it "easily".
Triage: Can someone please give a concrete example of a minimal "Rocket application" that reproduces this?
Is there any particular reason you'd like a Rocket application specifically? There is a minimal reproduction without Rocket listed above at I believe this is mostly addressed via . The reproduction now prints the error: However, I would suggest someone adding that reproduction to the UI testsuite, since it is a relatively subtle construction of tokens, and the test in doesn't test anything like what that is doing. I'd also defer to if they think there is anything more fundamental that should be done, particularly around the use of and in . I'm a bit uneasy about the use of there, since it is capable of stopping the compiler even if no errors have been emitted. Similarly, comparing spans against may not always work if something like a proc-macro ends up using the same span across multiple tokens. I would imagine someone could cook up a different example that has the same problem where the compiler exits with no error.
My bad, sorry about that. I'm trying to keep a high pace when triaging ICE-issues since there are so many of them. In this case the pace was too high, so I missed that comment of yours.
We discuss this in the wg-macros and will work on it If you want to join the discussion, please join our
claim

Discussion:
<ins> // force-host // no-prefer-dynamic // Proc macro helper for issue #89699, used by tests/ui/proc-macro/edition-gated-async-move- // syntax-issue89699.rs, emitting an `async move` closure. This syntax is only available in // editions 2018 and up, but is used in edition 2015 in the test. #![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; #[proc_macro_attribute] pub fn foo(_attr: TokenStream, item: TokenStream) -> TokenStream { let tt = item.into_iter().next().unwrap(); let sp = tt.span(); let mut arg = TokenStream::new(); let mut g = Group::new(Delimiter::Brace, TokenStream::new()); g.set_span(sp); arg.extend([ TokenTree::Ident(Ident::new("async", sp)), TokenTree::Ident(Ident::new("move", sp)), TokenTree::Group(g), ]); let mut body = TokenStream::new(); body.extend([ TokenTree::Ident(Ident::new("async_main", sp)), TokenTree::Group(Group::new(Delimiter::Parenthesis, arg)), ]); let mut ret = TokenStream::new(); ret.extend([ TokenTree::Ident(Ident::new("fn", sp)), TokenTree::Ident(Ident::new("main", sp)), TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), TokenTree::Group(Group::new(Delimiter::Brace, body)), ]); ret } </ins>

<ins> // aux-build:edition-gated-async-move-syntax.rs // edition: 2015 // Non-regression test for issue #89699, where a proc-macro emitting syntax only available in // edition 2018 and up (`async move`) is used on edition 2015 extern crate edition_gated_async_move_syntax; #[edition_gated_async_move_syntax::foo] fn foo() {} //~ ERROR `async move` blocks are only allowed in Rust 2018 or later </ins>

<ins> error: `async move` blocks are only allowed in Rust 2018 or later --> $DIR/edition-gated-async-move-syntax-issue89699.rs:10:1 | LL | fn foo() {} | ^^ error: aborting due to previous error </ins>