diff --git a/src/crates-and-source-files.md b/src/crates-and-source-files.md
index 1fb8425550..ffb2ba60c5 100644
--- a/src/crates-and-source-files.md
+++ b/src/crates-and-source-files.md
@@ -9,7 +9,7 @@
 
 > **Lexer**\
 > UTF8BOM : `\uFEFF`\
-> SHEBANG : `#!` ~[`[` `\n`] ~`\n`\*
+> SHEBANG : `#!` \~`\n`\+[†](#shebang)
 
 
 > Note: Although Rust, like any other language, can be implemented by an
@@ -65,10 +65,14 @@ apply to the crate as a whole.
 #![warn(non_camel_case_types)]
 ```
 
+## Byte order mark
+
 The optional [_UTF8 byte order mark_] (UTF8BOM production) indicates that the
 file is encoded in UTF8. It can only occur at the beginning of the file and
 is ignored by the compiler.
 
+## Shebang
+
 A source file can have a [_shebang_] (SHEBANG production), which indicates
 to the operating system what program to use to execute this file. It serves
 essentially to treat the source file as an executable script. The shebang
@@ -84,6 +88,11 @@ fn main() {
 }
 ```
 
+A restriction is imposed on the shebang syntax to avoid confusion with an
+[attribute]. The `#!` characters must not be followed by a `[` token, ignoring
+intervening [comments] or [whitespace]. If this restriction fails, then it is
+not treated as a shebang, but instead as the start of an attribute.
+
 ## Preludes and `no_std`
 
 All crates have a *prelude* that automatically inserts names from a specific
@@ -166,8 +175,10 @@ or `-` (U+002D) characters.
 [`std::prelude::v1`]: ../std/prelude/index.html
 [attribute]: attributes.md
 [attributes]: attributes.md
+[comments]: comments.md
 [function]: items/functions.md
 [module]: items/modules.md
 [module path]: paths.md
 [trait or lifetime bounds]: trait-bounds.md
 [where clauses]: items/generics.md#where-clauses
+[whitespace]: whitespace.md