- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
For the token sequence #! to start a shebang which would get stripped, it must be located at the very start of the file (modulo Unicode BOM) and not be followed by (whitespace | line_comment | block_comment)* [. If that's not given, the lexer won't remove it for the parser to digest instead. Meaning if the #! doesn't start an inner attribute, the parser will emit a relatively opaque / terse error of the form expected `[`, found $ACTUAL.
The most common trigger would be leading whitespace (incl. leading newlines). Example:
 #!/usr/bin/env -S cargo +nightly -Zscripterror: expected `[`, found `/`
 --> src/lib.rs:1:4
  |
1 |  #!/usr/bin/env -S cargo +nightly -Zscript
  |    ^ expected `[`
Ideally the parser would helpfully point out that the #! doesn't start a shebang here because $reasons.
I suspect this to get hit increasingly more often with the advent of RFC3424 Cargo scripts but we're generally still in uncommon and P-low territory I'd say.
This diagnostic was originally encountered by @epage in the context of doctests (source). Example reproducer:
//! ```
//! #!/usr/bin/env -S cargo +nightly -Zscript
//! fn main() {}
//! ```
rustdoc file.rs --test currently yields (abbreviated):
---- file.rs - (line 1) stdout ----
error: expected `[`, found `/`
 --> file.rs:2:3
  |
2 | #!/usr/bin/env rustc
  |   ^ expected `[`
error: aborting due to 1 previous error
Couldn't compile the test.
NB: Whether rustdoc should interpret the  #! in #[doc = "#!..."] (notice: no leading space!) or equivalently /// #!... as the start of a shebang (right now it doesn't) assuming the doc attr/comment is sandwiched in between /// ``` of course  is a separate question for T-rustdoc to decide.#! will likely never start a shebang inside doctests and that's good, too.
Once rustc supports frontmatter (#136889) which will get treated very similarly, we can think about improving diagnostics for their "lookalikes", too (i.e., detecting "stray" --- (etc.) in the parser).