Remove `rust` as a submodule

This removes the `tests/rust` submodule and instead moves to lazily cloning it
during tests. This helps work around the fact that git dependencies on `syn`
will pull in all submodules, and rust takes forever to clone. In short, the
intention here is to make git dependencies on `syn` bearable to avoid Cargo
auto-cloning submodules.
diff --git a/.gitignore b/.gitignore
index a9d37c5..07d9fa6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 target
 Cargo.lock
+tests/rust
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 0e829e3..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "tests/rust"]
-	path = tests/rust
-	url = https://github.com/rust-lang/rust
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 5ffeb84..da1e0cc 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -3,6 +3,8 @@
 extern crate walkdir;
 
 use std::env;
+use std::path::Path;
+use std::process::Command;
 use std::u32;
 
 use self::walkdir::DirEntry;
@@ -86,3 +88,29 @@
     }
 }
 
+pub fn clone_rust() {
+    if Path::new("tests/rust").is_dir() {
+        return
+    }
+
+    println!("cloning rust-lang/rust");
+    let result = Command::new("git")
+                    .arg("clone")
+                    .arg("https://github.com/rust-lang/rust")
+                    .arg("tests/rust")
+                    .status()
+                    .unwrap();
+    println!("result: {}", result);
+    assert!(result.success());
+
+    println!("reset to known-good rev");
+    let result = Command::new("git")
+                    .arg("reset")
+                    .arg("--hard")
+                    .arg("ddc5d7bd4b9ea3e8a8ccf82cb443e950be311d61")
+                    .current_dir("tests/rust")
+                    .status()
+                    .unwrap();
+    println!("result: {}", result);
+    assert!(result.success());
+}
diff --git a/tests/rust b/tests/rust
deleted file mode 160000
index ddc5d7b..0000000
--- a/tests/rust
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ddc5d7bd4b9ea3e8a8ccf82cb443e950be311d61
diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs
index a5128fc..c4220d4 100644
--- a/tests/test_precedence.rs
+++ b/tests/test_precedence.rs
@@ -74,6 +74,7 @@
     use std::io::Read;
 
     common::check_min_stack();
+    common::clone_rust();
     let abort_after = common::abort_after();
     if abort_after == 0 {
         panic!("Skipping all precedence tests");
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
index 6bab10f..e3a66d3 100644
--- a/tests/test_round_trip.rs
+++ b/tests/test_round_trip.rs
@@ -25,6 +25,7 @@
 #[test]
 fn test_round_trip() {
     common::check_min_stack();
+    common::clone_rust();
     let abort_after = common::abort_after();
     if abort_after == 0 {
         panic!("Skipping all round_trip tests");