Version 2.10.0-31.0.dev

Merge commit 'ba5aa496f16ef4402d303376c454f877946bcb38' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 5033a79..64c12b9 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -8893,6 +8893,65 @@
   @override
   Precedence get precedence => Precedence.primary;
 
+  /// If this identifier is used as an expression to read a value, this
+  /// is the element that provides the value.
+  ///
+  /// In valid code this can be almost any element, usually a
+  /// [LocalVariableElement], a [ParameterElement], or a
+  /// [PropertyAccessorElement] getter.
+  ///
+  /// In invalid code, for recovery, we might use a [PropertyAccessorElement]
+  /// setter `print(mySetter)` even though the setter cannot be used to read a
+  /// value. We do this to help the user to navigate to the setter, and maybe
+  /// add the corresponding getter.
+  ///
+  /// Return `null` if this identifier is not used to read a value, or the
+  /// AST structure has not been resolved, or if this identifier could not be
+  /// resolved.
+  ///
+  /// If this identifier is used as the target for a compound assignment
+  /// `x += 2`, both [readElement] and [writeElement] could be not `null`.
+  ///
+  /// If [referenceElement] is not `null`, then both [readElement] and
+  /// [writeElement] are `null`, because the identifier is not being used to
+  /// read or write a value.
+  ///
+  /// If either [readElement] or [writeElement] are not `null`, the
+  /// [referenceElement] is `null`, because the identifier is being used to
+  /// read or write a value.
+  ///
+  /// All three [readElement], [writeElement], and [referenceElement] can be
+  /// `null` when the AST structure has not been resolved, or this identifier
+  /// could not be resolved.
+  Element get readElement => null;
+
+  /// This element is set when this identifier is used not as an expression,
+  /// but just to reference some element.
+  ///
+  /// Examples are the name of the type in a [TypeName], the name of the method
+  /// in a [MethodInvocation], the name of the constructor in a
+  /// [ConstructorName], the name of the property in a [PropertyAccess], the
+  /// prefix and the identifier in a [PrefixedIdentifier] (which then can be
+  /// used to read or write a value).
+  ///
+  /// In invalid code, for recovery, any element could be used, e.g. a
+  /// setter as a type name `set mySetter(_) {} mySetter topVar;`. We do this
+  /// to help the user to navigate to this element, and maybe change its name,
+  /// add a new declaration, etc.
+  ///
+  /// Return `null` if this identifier is used to either read or write a value,
+  /// or the AST structure has not been resolved, or if this identifier could
+  /// not be resolved.
+  ///
+  /// If either [readElement] or [writeElement] are not `null`, the
+  /// [referenceElement] is `null`, because the identifier is being used to
+  /// read or write a value.
+  ///
+  /// All three [readElement], [writeElement], and [referenceElement] can be
+  /// `null` when the AST structure has not been resolved, or this identifier
+  /// could not be resolved.
+  Element get referenceElement => null;
+
   @override
   Element get staticElement => _staticElement;
 
@@ -8901,6 +8960,39 @@
     _staticElement = element;
   }
 
+  /// If this identifier is used as a target to assign a value, explicitly
+  /// using an [AssignmentExpression], or implicitly using a [PrefixExpression]
+  /// or [PostfixExpression], this is the element that is used to write the
+  /// value.
+  ///
+  /// In valid code this is a [LocalVariableElement], [ParameterElement], or a
+  /// [PropertyAccessorElement] setter.
+  ///
+  /// In invalid code, for recovery, we might use other elements, for example a
+  /// [PropertyAccessorElement] getter `myGetter = 0` even though the getter
+  /// cannot be used to write a value. We do this to help the user to navigate
+  /// to the getter, and maybe add the corresponding setter.
+  ///
+  /// Return `null` if this identifier is not used to write a value, or the
+  /// AST structure has not been resolved, or if this identifier could not be
+  /// resolved.
+  ///
+  /// If this identifier is used as the target for a compound assignment
+  /// `x += 2`, both [readElement] and [writeElement] could be not `null`.
+  ///
+  /// If [referenceElement] is not `null`, then both [readElement] and
+  /// [writeElement] are `null`, because the identifier is not being used to
+  /// read or write a value.
+  ///
+  /// If either [readElement] or [writeElement] are not `null`, the
+  /// [referenceElement] is `null`, because the identifier is being used to
+  /// read or write a value.
+  ///
+  /// All three [readElement], [writeElement], and [referenceElement] can be
+  /// `null` when the AST structure has not been resolved, or this identifier
+  /// could not be resolved.
+  Element get writeElement => null;
+
   @override
   E accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleIdentifier(this);
 
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index f974f35..33ce9bf 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -15,7 +15,10 @@
 }
 
 @reflectiveTest
-class BinaryExpressionResolutionTest extends PubPackageResolutionTest {
+class BinaryExpressionResolutionTest extends PubPackageResolutionTest
+    with BinaryExpressionResolutionTestCases {}
+
+mixin BinaryExpressionResolutionTestCases on PubPackageResolutionTest {
   test_bangEq() async {
     await assertNoErrorsInCode(r'''
 f(int a, int b) {
@@ -70,8 +73,9 @@
   }
 
   test_ifNull() async {
-    await assertNoErrorsInCode(r'''
-f(int a, double b) {
+    var question = typeToStringWithNullability ? '?' : '';
+    await assertNoErrorsInCode('''
+f(int$question a, double b) {
   a ?? b;
 }
 ''');
@@ -230,7 +234,8 @@
 
 @reflectiveTest
 class BinaryExpressionResolutionWithNullSafetyTest
-    extends PubPackageResolutionTest with WithNullSafetyMixin {
+    extends PubPackageResolutionTest
+    with WithNullSafetyMixin, BinaryExpressionResolutionTestCases {
   test_ifNull_left_nullableContext() async {
     await assertNoErrorsInCode(r'''
 T f<T>(T t) => t;
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index 462c895..57b16e8 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -53,6 +53,9 @@
     'CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT',
     // The code has been replaced but is not yet removed.
     'HintCode.DEPRECATED_MEMBER_USE',
+    // Produces two diagnostics when it should only produce one (see
+    // https://github.com/dart-lang/sdk/issues/43051)
+    'HintCode.UNNECESSARY_NULL_COMPARISON_FALSE',
   ];
 
   /// The prefix used on directive lines to specify the experiments that should
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 3056ea5..f5b9ef8 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -47,10 +47,14 @@
   analytics =
       createAnalyticsInstance(args.contains('--disable-dartdev-analytics'));
 
-  // On the first run, print the message to alert users that anonymous data will
-  // be collected by default.
-  if (analytics.firstRun) {
+  // If we have not printed the analyticsNoticeOnFirstRunMessage to stdout,
+  // and the user is on a terminal, then print the disclosure and set
+  // analytics.disclosureShownOnTerminal.
+  if (analytics is DartdevAnalytics &&
+      !analytics.disclosureShownOnTerminal &&
+      io.stdout.hasTerminal) {
     print(analyticsNoticeOnFirstRunMessage);
+    analytics.disclosureShownOnTerminal = true;
   }
 
   // When `--disable-analytics` or `--enable-analytics` are called we perform
@@ -152,8 +156,9 @@
           timeout: const Duration(milliseconds: 200));
     }
 
-    // As the notification to the user read on the first run, analytics are
-    // enabled by default, on the first run only.
+    // Set the enabled flag in the analytics object to true. Note: this will not
+    // enable the analytics unless the disclosure was shown (terminal
+    // detected), and the machine is not detected to be a bot.
     if (analytics.firstRun) {
       analytics.enabled = true;
     }
diff --git a/pkg/dartdev/lib/src/analytics.dart b/pkg/dartdev/lib/src/analytics.dart
index b00dca4..18369cf 100644
--- a/pkg/dartdev/lib/src/analytics.dart
+++ b/pkg/dartdev/lib/src/analytics.dart
@@ -46,7 +46,9 @@
   }
 
   // Dartdev tests pass a hidden 'disable-dartdev-analytics' flag which is
-  // handled here
+  // handled here.
+  // Also, stdout.hasTerminal is checked, if there is no terminal we infer that
+  // a machine is running dartdev so we return analytics shouldn't be set.
   if (disableAnalytics) {
     instance = DisabledAnalytics(_trackingId, _appName);
     return instance;
@@ -136,13 +138,22 @@
 
   @override
   bool get enabled {
-    if (telemetry.isRunningOnBot()) {
+    // Don't enable if the user hasn't been shown the disclosure or if this
+    // machine is bot.
+    if (!disclosureShownOnTerminal || telemetry.isRunningOnBot()) {
       return false;
     }
 
     // If there's no explicit setting (enabled or disabled) then we don't send.
     return (properties['enabled'] as bool) ?? false;
   }
+
+  bool get disclosureShownOnTerminal =>
+      (properties['disclosureShown'] as bool) ?? false;
+
+  void set disclosureShownOnTerminal(bool value) {
+    properties['disclosureShown'] = value;
+  }
 }
 
 class DisabledAnalytics extends AnalyticsMock {
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index f535c91..34cc58e 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -213,12 +213,6 @@
       }
     }
 
-    if (FLAG_print_classes) {
-      for (intptr_t i = 0; i < class_array.Length(); i++) {
-        cls ^= class_array.At(i);
-        PrintClassInformation(cls);
-      }
-    }
     // Clear pending classes array.
     class_array = GrowableObjectArray::New();
     object_store->set_pending_classes(class_array);
@@ -1161,6 +1155,9 @@
   }
   // Mark as loaded and finalized.
   cls.Finalize();
+  if (FLAG_print_classes) {
+    PrintClassInformation(cls);
+  }
   FinalizeMemberTypes(cls);
 
   if (cls.is_enum_class()) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 8b3cc81..92bc408 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5528,6 +5528,7 @@
 
   DECLARE_INSTRUCTION(LoadIndexed)
   virtual CompileType ComputeType() const;
+  virtual bool RecomputeType();
 
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT(idx == 0 || idx == 1);
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index f3fcd25..ba9529b 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1701,6 +1701,61 @@
   return CompileType::FromCid(definition_cid_);
 }
 
+static AbstractTypePtr ExtractElementTypeFromArrayType(
+    const AbstractType& array_type) {
+  if (array_type.IsTypeParameter()) {
+    return ExtractElementTypeFromArrayType(
+        AbstractType::Handle(TypeParameter::Cast(array_type).bound()));
+  }
+  if (!array_type.IsType()) {
+    return Object::dynamic_type().raw();
+  }
+  const intptr_t cid = array_type.type_class_id();
+  if (cid == kGrowableObjectArrayCid || cid == kArrayCid ||
+      cid == kImmutableArrayCid ||
+      array_type.type_class() ==
+          Isolate::Current()->object_store()->list_class()) {
+    const auto& type_args = TypeArguments::Handle(array_type.arguments());
+    return type_args.TypeAtNullSafe(Array::kElementTypeTypeArgPos);
+  }
+  return Object::dynamic_type().raw();
+}
+
+static AbstractTypePtr GetElementTypeFromArray(Value* array) {
+  return ExtractElementTypeFromArrayType(*(array->Type()->ToAbstractType()));
+}
+
+static CompileType ComputeArrayElementType(Value* array) {
+  // 1. Try to extract element type from array value.
+  auto& elem_type = AbstractType::Handle(GetElementTypeFromArray(array));
+  if (!elem_type.IsDynamicType()) {
+    return CompileType::FromAbstractType(elem_type);
+  }
+
+  // 2. Array value may be loaded from GrowableObjectArray.data.
+  // Unwrap and try again.
+  if (auto* load_field = array->definition()->AsLoadField()) {
+    if (load_field->slot().IsIdentical(Slot::GrowableObjectArray_data())) {
+      array = load_field->instance();
+      elem_type = GetElementTypeFromArray(array);
+      if (!elem_type.IsDynamicType()) {
+        return CompileType::FromAbstractType(elem_type);
+      }
+    }
+  }
+
+  // 3. If array was loaded from a Dart field, use field's static type.
+  // Unlike propagated type (which could be cid), static type may contain
+  // type arguments which can be used to figure out element type.
+  if (auto* load_field = array->definition()->AsLoadField()) {
+    if (load_field->slot().IsDartField()) {
+      elem_type =
+          ExtractElementTypeFromArrayType(load_field->slot().static_type());
+    }
+  }
+  return CompileType::FromAbstractType(elem_type);
+}
+
 CompileType LoadIndexedInstr::ComputeType() const {
   switch (class_id_) {
     case kArrayCid:
@@ -1709,7 +1764,7 @@
         // The original call knew something.
         return *result_type_;
       }
-      return CompileType::Dynamic();
+      return ComputeArrayElementType(array());
 
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
@@ -1751,4 +1806,13 @@
   }
 }
 
+bool LoadIndexedInstr::RecomputeType() {
+  if ((class_id_ == kArrayCid) || (class_id_ == kImmutableArrayCid)) {
+    // Array element type computation depends on computed
+    // types of other instructions and may change over time.
+    return UpdateType(ComputeType());
+  }
+  return false;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 718c6df..1785105 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2002,8 +2002,11 @@
 
 NameIndex KernelReaderHelper::ReadInterfaceMemberNameReference() {
   NameIndex name_index = reader_.ReadCanonicalNameReference();
-  reader_
-      .ReadCanonicalNameReference();  // read interface target origin reference
+  NameIndex origin_name_index = reader_.ReadCanonicalNameReference();
+  if (!FLAG_precompiled_mode && origin_name_index != NameIndex::kInvalidName) {
+    // Reference to a skipped member signature target, return the origin target.
+    return origin_name_index;
+  }
   return name_index;
 }
 
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index f22bcc1..eac771f 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -4710,6 +4710,58 @@
                "with matching arguments declared in class 'A'.");
 }
 
+TEST_CASE(IsolateReload_SuperGetterReboundToMethod) {
+  const char* kScript = R"(
+    import 'file:///test:isolate_reload_helper';
+
+    class A {
+      get x => "123";
+    }
+
+    class B extends A {
+      f() {
+        var old_x = super.x;
+        reloadTest();
+        var new_x = super.x;
+        return "$old_x:$new_x";
+      }
+    }
+
+    main() {
+      return B().f().toString();
+    }
+  )";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript = R"(
+    import 'file:///test:isolate_reload_helper';
+
+    class A {
+      x() => "123";
+    }
+
+    class B extends A {
+      f() {
+        var old_x = super.x;
+        reloadTest();
+        var new_x = super.x;
+        return "$old_x:$new_x";
+      }
+    }
+
+    main() {
+      return B().f();
+    }
+  )";
+
+  EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
+
+  EXPECT_STREQ("123:Closure: () => dynamic from Function 'x':.",
+               SimpleInvokeStr(lib, "main"));
+}
+
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 092af49..a992ff3 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1947,7 +1947,16 @@
   ProcedureHelper procedure_helper(&helper_);
 
   procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
-  if (procedure_helper.IsRedirectingFactoryConstructor()) {
+  // CFE adds 'member signature' abstract functions to a legacy class deriving
+  // or implementing an opted-in interface. The signature of these functions is
+  // legacy erased and used as the target of interface calls. They are used for
+  // static reasoning about the program by CFE, but not really needed by the VM.
+  // In certain situations (e.g. issue 162073826), a large number of these
+  // additional functions can cause strain on the VM. They are therefore skipped
+  // in jit mode and their associated origin function is used instead as
+  // interface call target.
+  if (procedure_helper.IsRedirectingFactoryConstructor() ||
+      (!FLAG_precompiled_mode && procedure_helper.IsMemberSignature())) {
     helper_.SetOffset(procedure_end);
     return;
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 533eb68..28b6ca2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -9572,6 +9572,9 @@
 
   bool IsImmutable() const { return raw()->GetClassId() == kImmutableArrayCid; }
 
+  // Position of element type in type arguments.
+  static const intptr_t kElementTypeTypeArgPos = 0;
+
   virtual TypeArgumentsPtr GetTypeArguments() const {
     return raw_ptr()->type_arguments_;
   }
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index cc6f720..847d1a4 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -992,17 +992,8 @@
       ASSERT(!caller_.is_static());
       new_cls_ = caller_.Owner();
       new_cls_ = new_cls_.SuperClass();
-      new_target_ = Function::null();
-      while (!new_cls_.IsNull()) {
-        // TODO(rmacnak): Should use Resolver::ResolveDynamicAnyArgs to handle
-        // method-extractors and call-through-getters, but we're in a no
-        // safepoint scope here.
-        new_target_ = new_cls_.LookupDynamicFunction(name_);
-        if (!new_target_.IsNull()) {
-          break;
-        }
-        new_cls_ = new_cls_.SuperClass();
-      }
+      new_target_ = Resolver::ResolveDynamicAnyArgs(zone_, new_cls_, name_,
+                                                    /*allow_add=*/true);
     }
     args_desc_array_ = ic.arguments_descriptor();
     ArgumentsDescriptor args_desc(args_desc_array_);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 9683d81..26a5c3a 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -335,13 +335,15 @@
 }
 
 void ObjectStore::LazyInitCoreTypes() {
-  if (non_nullable_list_rare_type_ == Type::null()) {
+  if (list_class_ == Type::null()) {
+    ASSERT(non_nullable_list_rare_type_ == Type::null());
     ASSERT(non_nullable_map_rare_type_ == Type::null());
     Thread* thread = Thread::Current();
     Zone* zone = thread->zone();
     const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
     Class& cls = Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
     ASSERT(!cls.IsNull());
+    set_list_class(cls);
     Type& type = Type::Handle(zone);
     type ^= cls.RareType();
     set_non_nullable_list_rare_type(type);
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 52c75ed..07ee7d6 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -82,6 +82,7 @@
   RW(Type, string_type)                                                        \
   RW(Type, legacy_string_type)                                                 \
   RW(Type, non_nullable_string_type)                                           \
+  CW(Class, list_class)                    /* maybe be null, lazily built */   \
   CW(Type, non_nullable_list_rare_type)    /* maybe be null, lazily built */   \
   CW(Type, non_nullable_map_rare_type)     /* maybe be null, lazily built */   \
   FW(Type, non_nullable_future_rare_type)  /* maybe be null, lazily built */   \
diff --git a/sdk/bin/dart2js_sdk.bat b/sdk/bin/dart2js_sdk.bat
index 8485cdc..0a9293c 100755
--- a/sdk/bin/dart2js_sdk.bat
+++ b/sdk/bin/dart2js_sdk.bat
@@ -47,7 +47,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 [" 2^>nul`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartanalyzer_sdk.bat b/sdk/bin/dartanalyzer_sdk.bat
index ab66885..57dd538 100644
--- a/sdk/bin/dartanalyzer_sdk.bat
+++ b/sdk/bin/dartanalyzer_sdk.bat
@@ -42,7 +42,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 [" 2^>nul`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartdevc.bat b/sdk/bin/dartdevc.bat
index fec39e4..6091a3a 100644
--- a/sdk/bin/dartdevc.bat
+++ b/sdk/bin/dartdevc.bat
@@ -56,7 +56,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 [" 2^>nul`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartdevc_sdk.bat b/sdk/bin/dartdevc_sdk.bat
index ce027a9..74b4c18 100644
--- a/sdk/bin/dartdevc_sdk.bat
+++ b/sdk/bin/dartdevc_sdk.bat
@@ -49,7 +49,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartfix.bat b/sdk/bin/dartfix.bat
index 4241694..b58475c 100644
--- a/sdk/bin/dartfix.bat
+++ b/sdk/bin/dartfix.bat
@@ -34,7 +34,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 [" 2^>nul`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartfmt_sdk.bat b/sdk/bin/dartfmt_sdk.bat
index 295b977..b4228d3 100644
--- a/sdk/bin/dartfmt_sdk.bat
+++ b/sdk/bin/dartfmt_sdk.bat
@@ -34,7 +34,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/pub_sdk.bat b/sdk/bin/pub_sdk.bat
index bde0e4a..2fe828b 100644
--- a/sdk/bin/pub_sdk.bat
+++ b/sdk/bin/pub_sdk.bat
@@ -43,7 +43,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 [" 2^>nul`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/tools/VERSION b/tools/VERSION
index c3bec70..ecc7570 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 30
+PRERELEASE 31
 PRERELEASE_PATCH 0
\ No newline at end of file