Repository: rust-lang/rust-analyzer
Pull request #12871 (2022-07-25 12:09:39)

Sync from `rust-lang/rust`
This is the first subtree sync PR from `rust-lang/rust` to `rust-lang/rust-analyzer`, made by following the instructions at: https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html#performing-the-sync-from-rust-langrust-to-clippy

It includes all the commits that were made in:

  * https://github.com/rust-lang/rust/pull/99603

(And that were reviewed ahead of time by @Veykril + @lnicola)


Patch:
diff --git a/.gitattributes b/.gitattributes
index 3b3d2d0d65..cb87b5d013 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,7 +1,8 @@
 * text=auto eol=lf
+
 # git grep shouldn't match entries in this benchmark data
 bench_data/** binary
-crates/syntax/test_data/** -text eof=LF
+
 # Older git versions try to fix line endings on images, this prevents it.
 *.png binary
 *.jpg binary
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 000fe5ac7b..05e0ceb05a 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -516,6 +516,9 @@ mod tests {
                     mark
                 ))
             })
+            // HashSet iteration order isn't defined - it's different on
+            // x86_64 and i686 at the very least
+            .sorted()
             .collect::<String>();
         expect.assert_eq(&actual)
     }
@@ -588,6 +591,7 @@ mod tests {
 
                 Some(format!("{}:\n{:?}\n", name, map))
             })
+            .sorted()
             .collect::<String>();
 
         expect.assert_eq(&actual)
@@ -621,15 +625,15 @@ mod tests {
             struct Priv;
         ",
             expect![[r#"
+                lib:
+                - Pub (t)
+                - Pub2 (t)
+                - Pub2 (v)
                 main:
                 - publ1 (t)
                 - real_pu2 (t)
                 - real_pub (t)
                 - real_pub::Pub (t)
-                lib:
-                - Pub (t)
-                - Pub2 (t)
-                - Pub2 (v)
             "#]],
         );
     }
@@ -671,13 +675,13 @@ mod tests {
             pub struct S;
         ",
             expect![[r#"
+                lib:
+                - S (t)
+                - S (v)
                 main:
                 - m (t)
                 - m::S (t)
                 - m::S (v)
-                lib:
-                - S (t)
-                - S (v)
             "#]],
         );
     }
@@ -697,11 +701,11 @@ mod tests {
             }
         ",
             expect![[r#"
+                lib:
+                - pub_macro (m)
                 main:
                 - m (t)
                 - m::pub_macro (m)
-                lib:
-                - pub_macro (m)
             "#]],
         );
     }
@@ -719,14 +723,14 @@ mod tests {
             }
         ",
             expect![[r#"
-                main:
-                - reexported_module (t)
-                - reexported_module::S (t)
-                - reexported_module::S (v)
                 lib:
                 - module (t)
                 - module::S (t)
                 - module::S (v)
+                main:
+                - reexported_module (t)
+                - reexported_module::S (t)
+                - reexported_module::S (v)
             "#]],
         );
     }
@@ -831,10 +835,10 @@ mod tests {
             Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy),
             expect![[r#"
                 dep::fmt (t)
-                dep::fmt::Display::format_method (a)
                 dep::fmt::Display (t)
                 dep::fmt::Display::FMT_CONST (a)
                 dep::fmt::Display::format_function (a)
+                dep::fmt::Display::format_method (a)
             "#]],
         );
     }
@@ -860,10 +864,10 @@ mod tests {
             "main",
             Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy).assoc_items_only(),
             expect![[r#"
-            dep::fmt::Display::format_method (a)
-            dep::fmt::Display::FMT_CONST (a)
-            dep::fmt::Display::format_function (a)
-        "#]],
+                dep::fmt::Display::FMT_CONST (a)
+                dep::fmt::Display::format_function (a)
+                dep::fmt::Display::format_method (a)
+            "#]],
         );
 
         check_search(
@@ -920,13 +924,13 @@ mod tests {
             "main",
             Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy),
             expect![[r#"
-                dep::fmt (t)
-                dep::format (f)
-                dep::Fmt (v)
                 dep::Fmt (m)
                 dep::Fmt (t)
-                dep::fmt::Display::fmt (a)
+                dep::Fmt (v)
+                dep::fmt (t)
                 dep::fmt::Display (t)
+                dep::fmt::Display::fmt (a)
+                dep::format (f)
             "#]],
         );
 
@@ -935,10 +939,10 @@ mod tests {
             "main",
             Query::new("fmt".to_string()).search_mode(SearchMode::Equals),
             expect![[r#"
-                dep::fmt (t)
-                dep::Fmt (v)
                 dep::Fmt (m)
                 dep::Fmt (t)
+                dep::Fmt (v)
+                dep::fmt (t)
                 dep::fmt::Display::fmt (a)
             "#]],
         );
@@ -948,12 +952,12 @@ mod tests {
             "main",
             Query::new("fmt".to_string()).search_mode(SearchMode::Contains),
             expect![[r#"
-                dep::fmt (t)
-                dep::Fmt (v)
                 dep::Fmt (m)
                 dep::Fmt (t)
-                dep::fmt::Display::fmt (a)
+                dep::Fmt (v)
+                dep::fmt (t)
                 dep::fmt::Display (t)
+                dep::fmt::Display::fmt (a)
             "#]],
         );
     }
@@ -989,12 +993,12 @@ mod tests {
             "main",
             Query::new("fmt".to_string()),
             expect![[r#"
-                dep::fmt (t)
-                dep::Fmt (v)
                 dep::Fmt (m)
                 dep::Fmt (t)
-                dep::fmt::Display::fmt (a)
+                dep::Fmt (v)
+                dep::fmt (t)
                 dep::fmt::Display (t)
+                dep::fmt::Display::fmt (a)
             "#]],
         );
 
@@ -1003,10 +1007,10 @@ mod tests {
             "main",
             Query::new("fmt".to_string()).name_only(),
             expect![[r#"
-                dep::fmt (t)
-                dep::Fmt (v)
                 dep::Fmt (m)
                 dep::Fmt (t)
+                dep::Fmt (v)
+                dep::fmt (t)
                 dep::fmt::Display::fmt (a)
             "#]],
         );
@@ -1027,10 +1031,10 @@ mod tests {
             "main",
             Query::new("FMT".to_string()),
             expect![[r#"
-                dep::fmt (t)
+                dep::FMT (t)
                 dep::FMT (v)
+                dep::fmt (t)
                 dep::fmt (v)
-                dep::FMT (t)
             "#]],
         );
 
@@ -1068,10 +1072,10 @@ mod tests {
             "main",
             Query::new("".to_string()).limit(2),
             expect![[r#"
-                dep::fmt (t)
+                dep::Fmt (m)
                 dep::Fmt (t)
                 dep::Fmt (v)
-                dep::Fmt (m)
+                dep::fmt (t)
             "#]],
         );
     }
@@ -1091,10 +1095,10 @@ mod tests {
             "main",
             Query::new("FMT".to_string()),
             expect![[r#"
-                dep::fmt (t)
+                dep::FMT (t)
                 dep::FMT (v)
+                dep::fmt (t)
                 dep::fmt (v)
-                dep::FMT (t)
             "#]],
         );
 
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index c67046dfda..3949fbb6e7 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -48,8 +48,8 @@
 //! the result
 
 pub mod attr_resolution;
-pub mod diagnostics;
 mod collector;
+pub mod diagnostics;
 mod mod_resolution;
 mod path_resolution;
 mod proc_macro;
@@ -57,10 +57,11 @@ mod proc_macro;
 #[cfg(test)]
 mod tests;
 
-use std::sync::Arc;
+use std::{cmp::Ord, sync::Arc};
 
 use base_db::{CrateId, Edition, FileId};
 use hir_expand::{name::Name, InFile, MacroDefId};
+use itertools::Itertools;
 use la_arena::Arena;
 use profile::Count;
 use rustc_hash::FxHashMap;
@@ -431,7 +432,9 @@ impl DefMap {
 
             map.modules[module].scope.dump(buf);
 
-            for (name, child) in map.modules[module].children.iter() {
+            for (name, child) in
+                map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
+            {
                 let path = format!("{}::{}", path, name);
                 buf.push('\n');
                 go(buf, map, &path, *child);
diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml
index 51e43d21cb..fca09d384c 100644
--- a/crates/ide-assists/Cargo.toml
+++ b/crates/ide-assists/Cargo.toml
@@ -26,3 +26,6 @@ hir = { path = "../hir", version = "0.0.0" }
 test-utils = { path = "../test-utils" }
 sourcegen = { path = "../sourcegen" }
 expect-test = "1.4.0"
+
+[features]
+in-rust-tree = []
diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml
index a79adca4cd..e221425edd 100644
--- a/crates/ide-diagnostics/Cargo.toml
+++ b/crates/ide-diagnostics/Cargo.toml
@@ -29,3 +29,6 @@ expect-test = "1.4.0"
 
 test-utils = { path = "../test-utils" }
 sourcegen = { path = "../sourcegen" }
+
+[features]
+in-rust-tree = []
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml
index 95a54b75e2..0e9771cd2e 100644
--- a/crates/ide/Cargo.toml
+++ b/crates/ide/Cargo.toml
@@ -42,3 +42,6 @@ toolchain = { path = "../toolchain", version = "0.0.0" }
 [dev-dependencies]
 test-utils = { path = "../test-utils" }
 expect-test = "1.4.0"
+
+[features]
+in-rust-tree = ["ide-assists/in-rust-tree", "ide-diagnostics/in-rust-tree"]
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 41205f2584..07771d1b39 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -84,4 +84,9 @@ mbe = { path = "../mbe" }
 [features]
 jemalloc = ["jemallocator", "profile/jemalloc"]
 force-always-assert = ["always-assert/force"]
-in-rust-tree = ["proc-macro-srv/sysroot-abi"]
+in-rust-tree = [
+    "proc-macro-srv/sysroot-abi",
+    "sourcegen/in-rust-tree",
+    "ide/in-rust-tree",
+    "syntax/in-rust-tree"
+]
diff --git a/crates/sourcegen/Cargo.toml b/crates/sourcegen/Cargo.toml
index e75867e2d8..a84110d940 100644
--- a/crates/sourcegen/Cargo.toml
+++ b/crates/sourcegen/Cargo.toml
@@ -11,3 +11,6 @@ doctest = false
 
 [dependencies]
 xshell = "0.2.2"
+
+[features]
+in-rust-tree = []
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index a56c9dec40..0e2dec386f 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -34,3 +34,6 @@ ungrammar = "1.16.1"
 
 test-utils = { path = "../test-utils" }
 sourcegen = { path = "../sourcegen" }
+
+[features]
+in-rust-tree = []


Test patch:
diff --git a/crates/hir-def/src/nameres/tests.rs b/crates/hir-def/src/nameres/tests.rs
index 80e5476071..70dd2eb3ad 100644
--- a/crates/hir-def/src/nameres/tests.rs
+++ b/crates/hir-def/src/nameres/tests.rs
@@ -648,11 +648,11 @@ mod b {
             a: t
             b: t
 
-            crate::b
-            T: v
-
             crate::a
             T: t v
+
+            crate::b
+            T: v
         "#]],
     );
 }
@@ -704,13 +704,13 @@ use crate::reex::*;
             reex: t
             tr: t
 
-            crate::tr
-            PrivTr: t
-            PubTr: t
-
             crate::reex
             _: t
             _: t
+
+            crate::tr
+            PrivTr: t
+            PubTr: t
         "#]],
     );
 }
@@ -920,14 +920,14 @@ use some_module::unknown_func;
             some_module: t
             unknown_func: v
 
-            crate::some_module
-            unknown_func: v
-
             crate::other_module
             some_submodule: t
 
             crate::other_module::some_submodule
             unknown_func: v
+
+            crate::some_module
+            unknown_func: v
         "#]],
     )
 }
diff --git a/crates/hir-def/src/nameres/tests/globs.rs b/crates/hir-def/src/nameres/tests/globs.rs
index 17426d54d4..b2a6a592cf 100644
--- a/crates/hir-def/src/nameres/tests/globs.rs
+++ b/crates/hir-def/src/nameres/tests/globs.rs
@@ -315,8 +315,13 @@ mod d {
             c: t
             d: t
 
-            crate::d
-            Y: t v
+            crate::a
+            foo: t
+
+            crate::a::foo
+            X: t v
+
+            crate::b
             foo: t
 
             crate::c
@@ -325,14 +330,9 @@ mod d {
             crate::c::foo
             Y: t v
 
-            crate::b
-            foo: t
-
-            crate::a
+            crate::d
+            Y: t v
             foo: t
-
-            crate::a::foo
-            X: t v
         "#]],
     );
 }
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index 520a6ae1cb..3ece1379ad 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -1,4 +1,5 @@
 use super::*;
+use itertools::Itertools;
 
 #[test]
 fn macro_rules_are_globally_visible() {
@@ -439,15 +440,8 @@ macro_rules! baz {
             m7: t
             ok_double_macro_use_shadow: v
 
-            crate::m7
-
             crate::m1
 
-            crate::m5
-            m6: t
-
-            crate::m5::m6
-
             crate::m2
 
             crate::m3
@@ -462,6 +456,13 @@ macro_rules! baz {
             ok_shadow_deep: v
 
             crate::m3::m5
+
+            crate::m5
+            m6: t
+
+            crate::m5::m6
+
+            crate::m7
         "#]],
     );
     // FIXME: should not see `NotFoundBefore`
@@ -1171,11 +1172,15 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
     );
 
     let root = &def_map[def_map.root()].scope;
-    let actual = root.legacy_macros().map(|(name, _)| format!("{name}\n")).collect::<String>();
+    let actual = root
+        .legacy_macros()
+        .sorted_by(|a, b| std::cmp::Ord::cmp(&a.0, &b.0))
+        .map(|(name, _)| format!("{name}\n"))
+        .collect::<String>();
 
     expect![[r#"
-        macro20
         legacy
+        macro20
         proc_attr
     "#]]
     .assert_eq(&actual);
diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs
index 249a56b4ae..9cd66c6b3b 100644
--- a/crates/ide-assists/src/tests.rs
+++ b/crates/ide-assists/src/tests.rs
@@ -1,5 +1,6 @@
-mod sourcegen;
 mod generated;
+#[cfg(not(feature = "in-rust-tree"))]
+mod sourcegen;
 
 use expect_test::expect;
 use hir::{db::DefDatabase, Semantics};
diff --git a/crates/ide-assists/src/tests/sourcegen.rs b/crates/ide-assists/src/tests/sourcegen.rs
index d45e54186b..070b83d3c1 100644
--- a/crates/ide-assists/src/tests/sourcegen.rs
+++ b/crates/ide-assists/src/tests/sourcegen.rs
@@ -59,6 +59,7 @@ r#####"
         fs::write(dst, contents).unwrap();
     }
 }
+
 #[derive(Debug)]
 struct Section {
     doc: String,
@@ -104,9 +105,11 @@ impl Assist {
                 while lines.peek().is_some() {
                     let doc = take_until(lines.by_ref(), "```").trim().to_string();
                     assert!(
-                        (doc.chars().next().unwrap().is_ascii_uppercase() && doc.ends_with('.')) || assist.sections.len() > 0,
+                        (doc.chars().next().unwrap().is_ascii_uppercase() && doc.ends_with('.'))
+                            || assist.sections.len() > 0,
                         "\n\n{}: assist docs should be proper sentences, with capitalization and a full stop at the end.\n\n{}\n\n",
-                        &assist.id, doc,
+                        &assist.id,
+                        doc,
                     );
 
                     let before = take_until(lines.by_ref(), "```");
diff --git a/crates/ide-diagnostics/src/tests.rs b/crates/ide-diagnostics/src/tests.rs
index 7cd79c7cee..7312bca32f 100644
--- a/crates/ide-diagnostics/src/tests.rs
+++ b/crates/ide-diagnostics/src/tests.rs
@@ -1,3 +1,4 @@
+#[cfg(not(feature = "in-rust-tree"))]
 mod sourcegen;
 
 use expect_test::Expect;
diff --git a/crates/proc-macro-test/build.rs b/crates/proc-macro-test/build.rs
index cd99eea5ae..a80c962617 100644
--- a/crates/proc-macro-test/build.rs
+++ b/crates/proc-macro-test/build.rs
@@ -62,17 +62,18 @@ fn main() {
         Command::new(toolchain::cargo())
     };
 
-    let output = cmd
-        .current_dir(&staging_dir)
+    cmd.current_dir(&staging_dir)
         .args(&["build", "-p", "proc-macro-test-impl", "--message-format", "json"])
         // Explicit override the target directory to avoid using the same one which the parent
         // cargo is using, or we'll deadlock.
         // This can happen when `CARGO_TARGET_DIR` is set or global config forces all cargo
         // instance to use the same target directory.
         .arg("--target-dir")
-        .arg(&target_dir)
-        .output()
-        .unwrap();
+        .arg(&target_dir);
+
+    println!("Running {:?}", cmd);
+
+    let output = cmd.output().unwrap();
     if !output.status.success() {
         println!("proc-macro-test-impl failed to build");
         println!("============ stdout ============");
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index eef76343dc..4cc46af1b1 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -10,10 +10,11 @@
 
 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
 
+#[cfg(not(feature = "in-rust-tree"))]
 mod sourcegen;
-mod tidy;
-mod testdir;
 mod support;
+mod testdir;
+mod tidy;
 
 use std::{collections::HashMap, path::PathBuf, time::Instant};
 
diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs
index dc3c5539c2..18f95925d9 100644
--- a/crates/rust-analyzer/tests/slow-tests/tidy.rs
+++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs
@@ -3,8 +3,12 @@ use std::{
     path::{Path, PathBuf},
 };
 
-use xshell::{cmd, Shell};
+use xshell::Shell;
 
+#[cfg(not(feature = "in-rust-tree"))]
+use xshell::cmd;
+
+#[cfg(not(feature = "in-rust-tree"))]
 #[test]
 fn check_code_formatting() {
     let sh = &Shell::new().unwrap();
@@ -168,6 +172,7 @@ See https://github.com/rust-lang/rust-clippy/issues/5537 for discussion.
     }
 }
 
+#[cfg(not(feature = "in-rust-tree"))]
 #[test]
 fn check_licenses() {
     let sh = &Shell::new().unwrap();
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
index 0611143e2a..58fba8cfa8 100644
--- a/crates/syntax/src/tests.rs
+++ b/crates/syntax/src/tests.rs
@@ -1,5 +1,7 @@
-mod sourcegen_ast;
+#[cfg(not(feature = "in-rust-tree"))]
 mod ast_src;
+#[cfg(not(feature = "in-rust-tree"))]
+mod sourcegen_ast;
 
 use std::{
     fs,
diff --git a/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs b/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs
index 3a73d81bb5..0a5958f25f 100644
--- a/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs
+++ b/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs
@@ -1,6 +1,6 @@
-type Foo<'a> = &'a dyn Send + Sync;
-type Foo = *const dyn Send + Sync;
-type Foo = fn() -> dyn Send + 'static;
-fn main() {
-    let b = (&a) as &dyn Add<Other, Output = Addable> + Other;
-}
+type Foo<'a> = &'a dyn Send + Sync;
+type Foo = *const dyn Send + Sync;
+type Foo = fn() -> dyn Send + 'static;
+fn main() {
+    let b = (&a) as &dyn Add<Other, Output = Addable> + Other;
+}
diff --git a/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs b/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs
index b34336f3f1..ccab6bccfa 100644
--- a/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs
+++ b/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs
@@ -1,1 +1,1 @@
-const mut FOO: () = ();
+const mut FOO: () = ();
diff --git a/crates/syntax/test_data/parser/validation/invalid_let_expr.rast b/crates/syntax/test_data/parser/validation/invalid_let_expr.rast
index 5b37b59783..9e1e488640 100644
--- a/crates/syntax/test_data/parser/validation/invalid_let_expr.rast
+++ b/crates/syntax/test_data/parser/validation/invalid_let_expr.rast
@@ -1,216 +1,216 @@
-SOURCE_FILE@0..282
-  FN@0..281
-    FN_KW@0..2 "fn"
-    WHITESPACE@2..3 " "
-    NAME@3..6
-      IDENT@3..6 "foo"
-    PARAM_LIST@6..8
-      L_PAREN@6..7 "("
-      R_PAREN@7..8 ")"
-    WHITESPACE@8..9 " "
-    BLOCK_EXPR@9..281
-      STMT_LIST@9..281
-        L_CURLY@9..10 "{"
-        WHITESPACE@10..15 "\n    "
-        CONST@15..42
-          CONST_KW@15..20 "const"
-          WHITESPACE@20..21 " "
-          UNDERSCORE@21..22 "_"
-          COLON@22..23 ":"
-          WHITESPACE@23..24 " "
-          TUPLE_TYPE@24..26
-            L_PAREN@24..25 "("
-            R_PAREN@25..26 ")"
-          WHITESPACE@26..27 " "
-          EQ@27..28 "="
-          WHITESPACE@28..29 " "
-          LET_EXPR@29..41
-            LET_KW@29..32 "let"
-            WHITESPACE@32..33 " "
-            WILDCARD_PAT@33..34
-              UNDERSCORE@33..34 "_"
-            WHITESPACE@34..35 " "
-            EQ@35..36 "="
-            WHITESPACE@36..37 " "
-            PATH_EXPR@37..41
-              PATH@37..41
-                PATH_SEGMENT@37..41
-                  NAME_REF@37..41
-                    IDENT@37..41 "None"
-          SEMICOLON@41..42 ";"
-        WHITESPACE@42..48 "\n\n    "
-        LET_STMT@48..83
-          LET_KW@48..51 "let"
-          WHITESPACE@51..52 " "
-          WILDCARD_PAT@52..53
-            UNDERSCORE@52..53 "_"
-          WHITESPACE@53..54 " "
-          EQ@54..55 "="
-          WHITESPACE@55..56 " "
-          IF_EXPR@56..82
-            IF_KW@56..58 "if"
-            WHITESPACE@58..59 " "
-            LITERAL@59..63
-              TRUE_KW@59..63 "true"
-            WHITESPACE@63..64 " "
-            BLOCK_EXPR@64..82
-              STMT_LIST@64..82
-                L_CURLY@64..65 "{"
-                WHITESPACE@65..66 " "
-                PAREN_EXPR@66..80
-                  L_PAREN@66..67 "("
-                  LET_EXPR@67..79
-                    LET_KW@67..70 "let"
-                    WHITESPACE@70..71 " "
-                    WILDCARD_PAT@71..72
-                      UNDERSCORE@71..72 "_"
-                    WHITESPACE@72..73 " "
-                    EQ@73..74 "="
-                    WHITESPACE@74..75 " "
-                    PATH_EXPR@75..79
-                      PATH@75..79
-                        PATH_SEGMENT@75..79
-                          NAME_REF@75..79
-                            IDENT@75..79 "None"
-                  R_PAREN@79..80 ")"
-                WHITESPACE@80..81 " "
-                R_CURLY@81..82 "}"
-          SEMICOLON@82..83 ";"
-        WHITESPACE@83..89 "\n\n    "
-        IF_EXPR@89..279
-          IF_KW@89..91 "if"
-          WHITESPACE@91..92 " "
-          BIN_EXPR@92..114
-            LITERAL@92..96
-              TRUE_KW@92..96 "true"
-            WHITESPACE@96..97 " "
-            AMP2@97..99 "&&"
-            WHITESPACE@99..100 " "
-            PAREN_EXPR@100..114
-              L_PAREN@100..101 "("
-              LET_EXPR@101..113
-                LET_KW@101..104 "let"
-                WHITESPACE@104..105 " "
-                WILDCARD_PAT@105..106
-                  UNDERSCORE@105..106 "_"
-                WHITESPACE@106..107 " "
-                EQ@107..108 "="
-                WHITESPACE@108..109 " "
-                PATH_EXPR@109..113
-                  PATH@109..113
-                    PATH_SEGMENT@109..113
-                      NAME_REF@109..113
-                        IDENT@109..113 "None"
-              R_PAREN@113..114 ")"
-          WHITESPACE@114..115 " "
-          BLOCK_EXPR@115..279
-            STMT_LIST@115..279
-              L_CURLY@115..116 "{"
-              WHITESPACE@116..125 "\n        "
-              EXPR_STMT@125..140
-                PAREN_EXPR@125..139
-                  L_PAREN@125..126 "("
-                  LET_EXPR@126..138
-                    LET_KW@126..129 "let"
-                    WHITESPACE@129..130 " "
-                    WILDCARD_PAT@130..131
-                      UNDERSCORE@130..131 "_"
-                    WHITESPACE@131..132 " "
-                    EQ@132..133 "="
-                    WHITESPACE@133..134 " "
-                    PATH_EXPR@134..138
-                      PATH@134..138
-                        PATH_SEGMENT@134..138
-                          NAME_REF@134..138
-                            IDENT@134..138 "None"
-                  R_PAREN@138..139 ")"
-                SEMICOLON@139..140 ";"
-              WHITESPACE@140..149 "\n        "
-              WHILE_EXPR@149..273
-                WHILE_KW@149..154 "while"
-                WHITESPACE@154..155 " "
-                LET_EXPR@155..167
-                  LET_KW@155..158 "let"
-                  WHITESPACE@158..159 " "
-                  WILDCARD_PAT@159..160
-                    UNDERSCORE@159..160 "_"
-                  WHITESPACE@160..161 " "
-                  EQ@161..162 "="
-                  WHITESPACE@162..163 " "
-                  PATH_EXPR@163..167
-                    PATH@163..167
-                      PATH_SEGMENT@163..167
-                        NAME_REF@163..167
-                          IDENT@163..167 "None"
-                WHITESPACE@167..168 " "
-                BLOCK_EXPR@168..273
-                  STMT_LIST@168..273
-                    L_CURLY@168..169 "{"
-                    WHITESPACE@169..182 "\n            "
-                    MATCH_EXPR@182..263
-                      MATCH_KW@182..187 "match"
-                      WHITESPACE@187..188 " "
-                      PATH_EXPR@188..192
-                        PATH@188..192
-                          PATH_SEGMENT@188..192
-                            NAME_REF@188..192
-                              IDENT@188..192 "None"
-                      WHITESPACE@192..193 " "
-                      MATCH_ARM_LIST@193..263
-                        L_CURLY@193..194 "{"
-                        WHITESPACE@194..211 "\n                "
-                        MATCH_ARM@211..249
-                          WILDCARD_PAT@211..212
-                            UNDERSCORE@211..212 "_"
-                          WHITESPACE@212..213 " "
-                          MATCH_GUARD@213..228
-                            IF_KW@213..215 "if"
-                            WHITESPACE@215..216 " "
-                            LET_EXPR@216..228
-                              LET_KW@216..219 "let"
-                              WHITESPACE@219..220 " "
-                              WILDCARD_PAT@220..221
-                                UNDERSCORE@220..221 "_"
-                              WHITESPACE@221..222 " "
-                              EQ@222..223 "="
-                              WHITESPACE@223..224 " "
-                              PATH_EXPR@224..228
-                                PATH@224..228
-                                  PATH_SEGMENT@224..228
-                                    NAME_REF@224..228
-                                      IDENT@224..228 "None"
-                          WHITESPACE@228..229 " "
-                          FAT_ARROW@229..231 "=>"
-                          WHITESPACE@231..232 " "
-                          BLOCK_EXPR@232..249
-                            STMT_LIST@232..249
-                              L_CURLY@232..233 "{"
-                              WHITESPACE@233..234 " "
-                              LET_STMT@234..247
-                                LET_KW@234..237 "let"
-                                WHITESPACE@237..238 " "
-                                WILDCARD_PAT@238..239
-                                  UNDERSCORE@238..239 "_"
-                                WHITESPACE@239..240 " "
-                                EQ@240..241 "="
-                                WHITESPACE@241..242 " "
-                                PATH_EXPR@242..246
-                                  PATH@242..246
-                                    PATH_SEGMENT@242..246
-                                      NAME_REF@242..246
-                                        IDENT@242..246 "None"
-                                SEMICOLON@246..247 ";"
-                              WHITESPACE@247..248 " "
-                              R_CURLY@248..249 "}"
-                        WHITESPACE@249..262 "\n            "
-                        R_CURLY@262..263 "}"
-                    WHITESPACE@263..272 "\n        "
-                    R_CURLY@272..273 "}"
-              WHITESPACE@273..278 "\n    "
-              R_CURLY@278..279 "}"
-        WHITESPACE@279..280 "\n"
-        R_CURLY@280..281 "}"
-  WHITESPACE@281..282 "\n"
-error 29..41: `let` expressions are not supported here
-error 67..79: `let` expressions are not supported here
-error 126..138: `let` expressions are not supported here
+SOURCE_FILE@0..282
+  FN@0..281
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..281
+      STMT_LIST@9..281
+        L_CURLY@9..10 "{"
+        WHITESPACE@10..15 "\n    "
+        CONST@15..42
+          CONST_KW@15..20 "const"
+          WHITESPACE@20..21 " "
+          UNDERSCORE@21..22 "_"
+          COLON@22..23 ":"
+          WHITESPACE@23..24 " "
+          TUPLE_TYPE@24..26
+            L_PAREN@24..25 "("
+            R_PAREN@25..26 ")"
+          WHITESPACE@26..27 " "
+          EQ@27..28 "="
+          WHITESPACE@28..29 " "
+          LET_EXPR@29..41
+            LET_KW@29..32 "let"
+            WHITESPACE@32..33 " "
+            WILDCARD_PAT@33..34
+              UNDERSCORE@33..34 "_"
+            WHITESPACE@34..35 " "
+            EQ@35..36 "="
+            WHITESPACE@36..37 " "
+            PATH_EXPR@37..41
+              PATH@37..41
+                PATH_SEGMENT@37..41
+                  NAME_REF@37..41
+                    IDENT@37..41 "None"
+          SEMICOLON@41..42 ";"
+        WHITESPACE@42..48 "\n\n    "
+        LET_STMT@48..83
+          LET_KW@48..51 "let"
+          WHITESPACE@51..52 " "
+          WILDCARD_PAT@52..53
+            UNDERSCORE@52..53 "_"
+          WHITESPACE@53..54 " "
+          EQ@54..55 "="
+          WHITESPACE@55..56 " "
+          IF_EXPR@56..82
+            IF_KW@56..58 "if"
+            WHITESPACE@58..59 " "
+            LITERAL@59..63
+              TRUE_KW@59..63 "true"
+            WHITESPACE@63..64 " "
+            BLOCK_EXPR@64..82
+              STMT_LIST@64..82
+                L_CURLY@64..65 "{"
+                WHITESPACE@65..66 " "
+                PAREN_EXPR@66..80
+                  L_PAREN@66..67 "("
+                  LET_EXPR@67..79
+                    LET_KW@67..70 "let"
+                    WHITESPACE@70..71 " "
+                    WILDCARD_PAT@71..72
+                      UNDERSCORE@71..72 "_"
+                    WHITESPACE@72..73 " "
+                    EQ@73..74 "="
+                    WHITESPACE@74..75 " "
+                    PATH_EXPR@75..79
+                      PATH@75..79
+                        PATH_SEGMENT@75..79
+                          NAME_REF@75..79
+                            IDENT@75..79 "None"
+                  R_PAREN@79..80 ")"
+                WHITESPACE@80..81 " "
+                R_CURLY@81..82 "}"
+          SEMICOLON@82..83 ";"
+        WHITESPACE@83..89 "\n\n    "
+        IF_EXPR@89..279
+          IF_KW@89..91 "if"
+          WHITESPACE@91..92 " "
+          BIN_EXPR@92..114
+            LITERAL@92..96
+              TRUE_KW@92..96 "true"
+            WHITESPACE@96..97 " "
+            AMP2@97..99 "&&"
+            WHITESPACE@99..100 " "
+            PAREN_EXPR@100..114
+              L_PAREN@100..101 "("
+              LET_EXPR@101..113
+                LET_KW@101..104 "let"
+                WHITESPACE@104..105 " "
+                WILDCARD_PAT@105..106
+                  UNDERSCORE@105..106 "_"
+                WHITESPACE@106..107 " "
+                EQ@107..108 "="
+                WHITESPACE@108..109 " "
+                PATH_EXPR@109..113
+                  PATH@109..113
+                    PATH_SEGMENT@109..113
+                      NAME_REF@109..113
+                        IDENT@109..113 "None"
+              R_PAREN@113..114 ")"
+          WHITESPACE@114..115 " "
+          BLOCK_EXPR@115..279
+            STMT_LIST@115..279
+              L_CURLY@115..116 "{"
+              WHITESPACE@116..125 "\n        "
+              EXPR_STMT@125..140
+                PAREN_EXPR@125..139
+                  L_PAREN@125..126 "("
+                  LET_EXPR@126..138
+                    LET_KW@126..129 "let"
+                    WHITESPACE@129..130 " "
+                    WILDCARD_PAT@130..131
+                      UNDERSCORE@130..131 "_"
+                    WHITESPACE@131..132 " "
+                    EQ@132..133 "="
+                    WHITESPACE@133..134 " "
+                    PATH_EXPR@134..138
+                      PATH@134..138
+                        PATH_SEGMENT@134..138
+                          NAME_REF@134..138
+                            IDENT@134..138 "None"
+                  R_PAREN@138..139 ")"
+                SEMICOLON@139..140 ";"
+              WHITESPACE@140..149 "\n        "
+              WHILE_EXPR@149..273
+                WHILE_KW@149..154 "while"
+                WHITESPACE@154..155 " "
+                LET_EXPR@155..167
+                  LET_KW@155..158 "let"
+                  WHITESPACE@158..159 " "
+                  WILDCARD_PAT@159..160
+                    UNDERSCORE@159..160 "_"
+                  WHITESPACE@160..161 " "
+                  EQ@161..162 "="
+                  WHITESPACE@162..163 " "
+                  PATH_EXPR@163..167
+                    PATH@163..167
+                      PATH_SEGMENT@163..167
+                        NAME_REF@163..167
+                          IDENT@163..167 "None"
+                WHITESPACE@167..168 " "
+                BLOCK_EXPR@168..273
+                  STMT_LIST@168..273
+                    L_CURLY@168..169 "{"
+                    WHITESPACE@169..182 "\n            "
+                    MATCH_EXPR@182..263
+                      MATCH_KW@182..187 "match"
+                      WHITESPACE@187..188 " "
+                      PATH_EXPR@188..192
+                        PATH@188..192
+                          PATH_SEGMENT@188..192
+                            NAME_REF@188..192
+                              IDENT@188..192 "None"
+                      WHITESPACE@192..193 " "
+                      MATCH_ARM_LIST@193..263
+                        L_CURLY@193..194 "{"
+                        WHITESPACE@194..211 "\n                "
+                        MATCH_ARM@211..249
+                          WILDCARD_PAT@211..212
+                            UNDERSCORE@211..212 "_"
+                          WHITESPACE@212..213 " "
+                          MATCH_GUARD@213..228
+                            IF_KW@213..215 "if"
+                            WHITESPACE@215..216 " "
+                            LET_EXPR@216..228
+                              LET_KW@216..219 "let"
+                              WHITESPACE@219..220 " "
+                              WILDCARD_PAT@220..221
+                                UNDERSCORE@220..221 "_"
+                              WHITESPACE@221..222 " "
+                              EQ@222..223 "="
+                              WHITESPACE@223..224 " "
+                              PATH_EXPR@224..228
+                                PATH@224..228
+                                  PATH_SEGMENT@224..228
+                                    NAME_REF@224..228
+                                      IDENT@224..228 "None"
+                          WHITESPACE@228..229 " "
+                          FAT_ARROW@229..231 "=>"
+                          WHITESPACE@231..232 " "
+                          BLOCK_EXPR@232..249
+                            STMT_LIST@232..249
+                              L_CURLY@232..233 "{"
+                              WHITESPACE@233..234 " "
+                              LET_STMT@234..247
+                                LET_KW@234..237 "let"
+                                WHITESPACE@237..238 " "
+                                WILDCARD_PAT@238..239
+                                  UNDERSCORE@238..239 "_"
+                                WHITESPACE@239..240 " "
+                                EQ@240..241 "="
+                                WHITESPACE@241..242 " "
+                                PATH_EXPR@242..246
+                                  PATH@242..246
+                                    PATH_SEGMENT@242..246
+                                      NAME_REF@242..246
+                                        IDENT@242..246 "None"
+                                SEMICOLON@246..247 ";"
+                              WHITESPACE@247..248 " "
+                              R_CURLY@248..249 "}"
+                        WHITESPACE@249..262 "\n            "
+                        R_CURLY@262..263 "}"
+                    WHITESPACE@263..272 "\n        "
+                    R_CURLY@272..273 "}"
+              WHITESPACE@273..278 "\n    "
+              R_CURLY@278..279 "}"
+        WHITESPACE@279..280 "\n"
+        R_CURLY@280..281 "}"
+  WHITESPACE@281..282 "\n"
+error 29..41: `let` expressions are not supported here
+error 67..79: `let` expressions are not supported here
+error 126..138: `let` expressions are not supported here
diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs
index dedfbd7afe..8a9cfb6c22 100644
--- a/crates/test-utils/src/lib.rs
+++ b/crates/test-utils/src/lib.rs
@@ -8,9 +8,9 @@
 
 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
 
+mod assert_linear;
 pub mod bench_fixture;
 mod fixture;
-mod assert_linear;
 
 use std::{
     collections::BTreeMap,
@@ -391,7 +391,8 @@ fn main() {
 /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag
 /// that slow tests did run.
 pub fn skip_slow_tests() -> bool {
-    let should_skip = std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err();
+    let should_skip = (std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err())
+        || std::env::var("SKIP_SLOW_TESTS").is_ok();
     if should_skip {
         eprintln!("ignoring slow test");
     } else {
@@ -475,7 +476,7 @@ pub fn ensure_file_contents(file: &Path, contents: &str) {
 pub fn try_ensure_file_contents(file: &Path, contents: &str) -> Result<(), ()> {
     match std::fs::read_to_string(file) {
         Ok(old_contents) if normalize_newlines(&old_contents) == normalize_newlines(contents) => {
-            return Ok(())
+            return Ok(());
         }
         _ => (),
     }