Don't try to run snapshots in Dart 2 mode (#1893)

Closes #32188
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index bb7cd56..796b326 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -59,7 +59,9 @@
 
   var localSnapshotPath =
       p.join(entrypoint.cachePath, "bin", package, "$executable.snapshot");
-  if (!isGlobal && fileExists(localSnapshotPath)) {
+  // Snapshots are compiled in Dart 1 mode, so in Dart 2 mode we always run
+  // executables from source.
+  if (!isDart2 && !isGlobal && fileExists(localSnapshotPath)) {
     // Since we don't access the package graph, this doesn't happen
     // automatically.
     entrypoint.assertUpToDate();
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 84cb087..82c085e 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -376,7 +376,9 @@
       String package, String executable, Iterable<String> args,
       {bool checked: false}) {
     var binDir = p.join(_directory, package, 'bin');
-    if (!fileExists(p.join(binDir, '$executable.dart.snapshot'))) {
+    // Snapshots are compiled in Dart 1 mode, so in Dart 2 mode we always run
+    // executables from source.
+    if (isDart2 || !fileExists(p.join(binDir, '$executable.dart.snapshot'))) {
       return exe.runExecutable(find(package), package, executable, args,
           isGlobal: true, checked: checked, cache: cache);
     }
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 0689c0a..8bd242d 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -20,6 +20,12 @@
 /// Whether Pub is running its own tests under Travis.CI.
 final isTravis = Platform.environment["TRAVIS_REPO_SLUG"] == "dart-lang/pub";
 
+/// Whether Pub is running with Dart 2 runtime semantics.
+final bool isDart2 = () {
+  Type checkType<T>() => T;
+  return checkType<String>() == String;
+}();
+
 /// A regular expression matching a Dart identifier.
 ///
 /// This also matches a package name, since they must be Dart identifiers.