Upgrade rust/crates/syn to 1.0.37 am: 7fa13b183f am: 5d6b36432c

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/syn/+/1386554

Change-Id: Icef0f7ec7b3e8cd69167b9eeb6569f37083a7301
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index ed9210d..9c6d3a1 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "8b460ba0294625a5b9069ad361cdac5d30689a7d"
+    "sha1": "e8e929bde537769933ae096165ce9d697cb33bcc"
   }
 }
diff --git a/Cargo.toml b/Cargo.toml
index 1a7cba5..e3c3bcf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "syn"
-version = "1.0.36"
+version = "1.0.37"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"]
 description = "Parser for Rust source code"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 509e2c0..5e469b9 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "syn"
-version = "1.0.36" # don't forget to update html_root_url and syn.json
+version = "1.0.37" # don't forget to update html_root_url and syn.json
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 license = "MIT OR Apache-2.0"
 description = "Parser for Rust source code"
diff --git a/METADATA b/METADATA
index 8b5c70d..c39db0b 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
     type: GIT
     value: "https://github.com/dtolnay/syn"
   }
-  version: "1.0.36"
+  version: "1.0.37"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 7
-    day: 26
+    month: 8
+    day: 3
   }
 }
diff --git a/src/expr.rs b/src/expr.rs
index 8a832e0..55a4905 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -8,7 +8,7 @@
 #[cfg(feature = "printing")]
 use std::fmt::{self, Display};
 use std::hash::{Hash, Hasher};
-#[cfg(all(feature = "parsing", feature = "full"))]
+#[cfg(feature = "parsing")]
 use std::mem;
 
 ast_enum_of_structs! {
@@ -1662,7 +1662,7 @@
                     args: content.parse_terminated(Expr::parse)?,
                 });
             } else if input.peek(Token![.]) && !input.peek(Token![..]) {
-                let dot_token: Token![.] = input.parse()?;
+                let mut dot_token: Token![.] = input.parse()?;
 
                 let await_token: Option<token::Await> = input.parse()?;
                 if let Some(await_token) = await_token {
@@ -1677,8 +1677,9 @@
 
                 let float_token: Option<LitFloat> = input.parse()?;
                 if let Some(float_token) = float_token {
-                    e = multi_index(e, dot_token, float_token)?;
-                    continue;
+                    if multi_index(&mut e, &mut dot_token, float_token)? {
+                        continue;
+                    }
                 }
 
                 let member: Member = input.parse()?;
@@ -1766,18 +1767,19 @@
                 });
             } else if input.peek(Token![.]) && !input.peek(Token![..]) && !input.peek2(token::Await)
             {
-                let dot_token: Token![.] = input.parse()?;
+                let mut dot_token: Token![.] = input.parse()?;
                 let float_token: Option<LitFloat> = input.parse()?;
                 if let Some(float_token) = float_token {
-                    e = multi_index(e, dot_token, float_token)?;
-                } else {
-                    e = Expr::Field(ExprField {
-                        attrs: Vec::new(),
-                        base: Box::new(e),
-                        dot_token,
-                        member: input.parse()?,
-                    });
+                    if multi_index(&mut e, &mut dot_token, float_token)? {
+                        continue;
+                    }
                 }
+                e = Expr::Field(ExprField {
+                    attrs: Vec::new(),
+                    base: Box::new(e),
+                    dot_token,
+                    member: input.parse()?,
+                });
             } else if input.peek(token::Bracket) {
                 let content;
                 e = Expr::Index(ExprIndex {
@@ -2739,18 +2741,24 @@
         }
     }
 
-    fn multi_index(mut e: Expr, mut dot_token: Token![.], float: LitFloat) -> Result<Expr> {
-        for part in float.to_string().split('.') {
+    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
+        let mut float_repr = float.to_string();
+        let trailing_dot = float_repr.ends_with('.');
+        if trailing_dot {
+            float_repr.truncate(float_repr.len() - 1);
+        }
+        for part in float_repr.split('.') {
             let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
-            e = Expr::Field(ExprField {
+            let base = mem::replace(e, Expr::__Nonexhaustive);
+            *e = Expr::Field(ExprField {
                 attrs: Vec::new(),
-                base: Box::new(e),
-                dot_token,
+                base: Box::new(base),
+                dot_token: Token![.](dot_token.span),
                 member: Member::Unnamed(index),
             });
-            dot_token = Token![.](float.span());
+            *dot_token = Token![.](float.span());
         }
-        Ok(e)
+        Ok(!trailing_dot)
     }
 
     #[cfg(feature = "full")]
diff --git a/src/lib.rs b/src/lib.rs
index f95d43d..f33b280 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -250,7 +250,7 @@
 //!   dynamic library libproc_macro from rustc toolchain.
 
 // Syn types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/syn/1.0.36")]
+#![doc(html_root_url = "https://docs.rs/syn/1.0.37")]
 #![deny(clippy::all, clippy::pedantic)]
 // Ignored clippy lints.
 #![allow(
@@ -456,6 +456,9 @@
 #[cfg(all(feature = "parsing", feature = "printing"))]
 pub mod spanned;
 
+#[cfg(all(feature = "parsing", feature = "full"))]
+mod whitespace;
+
 mod gen {
     /// Syntax tree traversal to walk a shared borrow of a syntax tree.
     ///
@@ -943,13 +946,16 @@
     }
 
     let mut shebang = None;
-    if content.starts_with("#!") && !content.starts_with("#![") {
-        if let Some(idx) = content.find('\n') {
-            shebang = Some(content[..idx].to_string());
-            content = &content[idx..];
-        } else {
-            shebang = Some(content.to_string());
-            content = "";
+    if content.starts_with("#!") {
+        let rest = whitespace::skip(&content[2..]);
+        if !rest.starts_with('[') {
+            if let Some(idx) = content.find('\n') {
+                shebang = Some(content[..idx].to_string());
+                content = &content[idx..];
+            } else {
+                shebang = Some(content.to_string());
+                content = "";
+            }
         }
     }
 
diff --git a/src/whitespace.rs b/src/whitespace.rs
new file mode 100644
index 0000000..7be082e
--- /dev/null
+++ b/src/whitespace.rs
@@ -0,0 +1,65 @@
+pub fn skip(mut s: &str) -> &str {
+    'skip: while !s.is_empty() {
+        let byte = s.as_bytes()[0];
+        if byte == b'/' {
+            if s.starts_with("//")
+                && (!s.starts_with("///") || s.starts_with("////"))
+                && !s.starts_with("//!")
+            {
+                if let Some(i) = s.find('\n') {
+                    s = &s[i + 1..];
+                    continue;
+                } else {
+                    return "";
+                }
+            } else if s.starts_with("/**/") {
+                s = &s[4..];
+                continue;
+            } else if s.starts_with("/*")
+                && (!s.starts_with("/**") || s.starts_with("/***"))
+                && !s.starts_with("/*!")
+            {
+                let mut depth = 0;
+                let bytes = s.as_bytes();
+                let mut i = 0;
+                let upper = bytes.len() - 1;
+                while i < upper {
+                    if bytes[i] == b'/' && bytes[i + 1] == b'*' {
+                        depth += 1;
+                        i += 1; // eat '*'
+                    } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
+                        depth -= 1;
+                        if depth == 0 {
+                            s = &s[i + 2..];
+                            continue 'skip;
+                        }
+                        i += 1; // eat '/'
+                    }
+                    i += 1;
+                }
+                return s;
+            }
+        }
+        match byte {
+            b' ' | 0x09..=0x0d => {
+                s = &s[1..];
+                continue;
+            }
+            b if b <= 0x7f => {}
+            _ => {
+                let ch = s.chars().next().unwrap();
+                if is_whitespace(ch) {
+                    s = &s[ch.len_utf8()..];
+                    continue;
+                }
+            }
+        }
+        return s;
+    }
+    s
+}
+
+fn is_whitespace(ch: char) -> bool {
+    // Rust treats left-to-right mark and right-to-left mark as whitespace
+    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
+}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 1b0b23c..a1cc80a 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -16,8 +16,12 @@
 
 /// Configure Rayon threadpool.
 pub fn rayon_init() {
+    let stack_size = match env::var("RUST_MIN_STACK") {
+        Ok(s) => s.parse().expect("failed to parse RUST_MIN_STACK"),
+        Err(_) => 20 * 1024 * 1024,
+    };
     ThreadPoolBuilder::new()
-        .stack_size(10 * 1024 * 1024)
+        .stack_size(stack_size)
         .build_global()
         .unwrap();
 }
diff --git a/tests/repo/mod.rs b/tests/repo/mod.rs
index 02b25c8..20c5fdd 100644
--- a/tests/repo/mod.rs
+++ b/tests/repo/mod.rs
@@ -8,7 +8,7 @@
 use tar::Archive;
 use walkdir::DirEntry;
 
-const REVISION: &str = "46e85b4328fe18492894093c1092dfe509df4370";
+const REVISION: &str = "81e754c359c471f91263813c46c67955071716a7";
 
 #[rustfmt::skip]
 static EXCLUDE: &[&str] = &[
@@ -25,6 +25,7 @@
     "test/ui/include-single-expr-helper-1.rs",
     "test/ui/issues/auxiliary/issue-21146-inc.rs",
     "test/ui/json-bom-plus-crlf-multifile-aux.rs",
+    "test/ui/lint/expansion-time-include.rs",
     "test/ui/macros/auxiliary/macro-comma-support.rs",
     "test/ui/macros/auxiliary/macro-include-items-expr.rs",
 ];
@@ -42,8 +43,13 @@
     if cfg!(windows) {
         path_string = path_string.replace('\\', "/").into();
     }
-    assert!(path_string.starts_with("tests/rust/src/"));
-    let path = &path_string["tests/rust/src/".len()..];
+    let path = if let Some(path) = path_string.strip_prefix("tests/rust/src/") {
+        path
+    } else if let Some(path) = path_string.strip_prefix("tests/rust/library/") {
+        path
+    } else {
+        panic!("unexpected path in Rust dist: {}", path_string);
+    };
 
     // TODO assert that parsing fails on the parse-fail cases
     if path.starts_with("test/parse-fail")
diff --git a/tests/test_expr.rs b/tests/test_expr.rs
index dde72d5..b2b65a2 100644
--- a/tests/test_expr.rs
+++ b/tests/test_expr.rs
@@ -50,55 +50,72 @@
     "###);
 }
 
+#[rustfmt::skip]
 #[test]
 fn test_tuple_multi_index() {
-    let input = "tuple.0.0";
-    snapshot!(input as Expr, @r###"
-    Expr::Field {
-        base: Expr::Field {
-            base: Expr::Path {
-                path: Path {
-                    segments: [
-                        PathSegment {
-                            ident: "tuple",
-                            arguments: None,
-                        },
-                    ],
+    for &input in &[
+        "tuple.0.0",
+        "tuple .0.0",
+        "tuple. 0.0",
+        "tuple.0 .0",
+        "tuple.0. 0",
+        "tuple . 0 . 0",
+    ] {
+        snapshot!(input as Expr, @r###"
+        Expr::Field {
+            base: Expr::Field {
+                base: Expr::Path {
+                    path: Path {
+                        segments: [
+                            PathSegment {
+                                ident: "tuple",
+                                arguments: None,
+                            },
+                        ],
+                    },
                 },
+                member: Unnamed(Index {
+                    index: 0,
+                }),
             },
             member: Unnamed(Index {
                 index: 0,
             }),
-        },
-        member: Unnamed(Index {
-            index: 0,
-        }),
+        }
+        "###);
     }
-    "###);
 
-    let tokens = quote!(tuple.0.0);
-    snapshot!(tokens as Expr, @r###"
-    Expr::Field {
-        base: Expr::Field {
-            base: Expr::Path {
-                path: Path {
-                    segments: [
-                        PathSegment {
-                            ident: "tuple",
-                            arguments: None,
-                        },
-                    ],
+    for tokens in vec![
+        quote!(tuple.0.0),
+        quote!(tuple .0.0),
+        quote!(tuple. 0.0),
+        quote!(tuple.0 .0),
+        quote!(tuple.0. 0),
+        quote!(tuple . 0 . 0),
+    ] {
+        snapshot!(tokens as Expr, @r###"
+        Expr::Field {
+            base: Expr::Field {
+                base: Expr::Path {
+                    path: Path {
+                        segments: [
+                            PathSegment {
+                                ident: "tuple",
+                                arguments: None,
+                            },
+                        ],
+                    },
                 },
+                member: Unnamed(Index {
+                    index: 0,
+                }),
             },
             member: Unnamed(Index {
                 index: 0,
             }),
-        },
-        member: Unnamed(Index {
-            index: 0,
-        }),
+        }
+        "###);
     }
-    "###);
 }
 
 #[test]
diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs
index d74d96d..dfdab3f 100644
--- a/tests/test_precedence.rs
+++ b/tests/test_precedence.rs
@@ -352,6 +352,17 @@
             }
         }
 
+        fn fold_generic_method_argument(
+            &mut self,
+            arg: GenericMethodArgument,
+        ) -> GenericMethodArgument {
+            match arg {
+                // Don't wrap const generic arg as that's invalid syntax.
+                GenericMethodArgument::Const(a) => GenericMethodArgument::Const(fold_expr(self, a)),
+                _ => fold_generic_method_argument(self, arg),
+            }
+        }
+
         fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
             match stmt {
                 // Don't wrap toplevel expressions in statements.
diff --git a/tests/test_shebang.rs b/tests/test_shebang.rs
new file mode 100644
index 0000000..e76e180
--- /dev/null
+++ b/tests/test_shebang.rs
@@ -0,0 +1,59 @@
+#[macro_use]
+mod macros;
+
+#[test]
+fn test_basic() {
+    let content = "#!/usr/bin/env rustx\nfn main() {}";
+    let file = syn::parse_file(content).unwrap();
+    snapshot!(file, @r###"
+    File {
+        shebang: Some("#!/usr/bin/env rustx"),
+        items: [
+            Item::Fn {
+                vis: Inherited,
+                sig: Signature {
+                    ident: "main",
+                    generics: Generics,
+                    output: Default,
+                },
+                block: Block,
+            },
+        ],
+    }
+    "###);
+}
+
+#[test]
+fn test_comment() {
+    let content = "#!//am/i/a/comment\n[allow(dead_code)] fn main() {}";
+    let file = syn::parse_file(content).unwrap();
+    snapshot!(file, @r###"
+    File {
+        attrs: [
+            Attribute {
+                style: Inner,
+                path: Path {
+                    segments: [
+                        PathSegment {
+                            ident: "allow",
+                            arguments: None,
+                        },
+                    ],
+                },
+                tokens: TokenStream(`( dead_code )`),
+            },
+        ],
+        items: [
+            Item::Fn {
+                vis: Inherited,
+                sig: Signature {
+                    ident: "main",
+                    generics: Generics,
+                    output: Default,
+                },
+                block: Block,
+            },
+        ],
+    }
+    "###);
+}