Version 2.14.0-352.0.dev

Merge commit '12d1bc7236f9afa24df29da6c3dc64fc08d241c7' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 80022ea..76697c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -225,7 +225,11 @@
       // Continue to resolve type.
     }
 
-    // TODO(srawlins): If PropertyAccessorElement, report error.
+    if (member is PropertyAccessorElement) {
+      function.accept(_resolver);
+      _resolveDisallowedExpression(node, member.returnType);
+      return;
+    }
 
     _resolve(node: node, rawType: member.type, name: propertyName.name);
   }
@@ -298,9 +302,11 @@
       return;
     }
 
-    // TODO(srawlins): Need to report cases where [methodElement] is not
-    // generic. The 'test_instanceGetter_explicitReceiver' test case needs to
-    // be updated to handle this.
+    if (methodElement is PropertyAccessorElement) {
+      function.accept(_resolver);
+      _resolveDisallowedExpression(node, methodElement.returnType);
+      return;
+    }
 
     function.accept(_resolver);
     node.staticType = DynamicTypeImpl.instance;
@@ -388,8 +394,6 @@
     PrefixedIdentifier prefix,
     Element element,
   ) {
-    // TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
-
     if (element is MultiplyDefinedElement) {
       MultiplyDefinedElement multiply = element;
       element = multiply.conflictingElements[0];
@@ -472,17 +476,25 @@
           // Continue to assign types.
         }
 
+        if (method is PropertyAccessorElement) {
+          _resolveDisallowedExpression(node, method.returnType);
+          return;
+        }
+
         function.staticElement = method;
         function.staticType = method.type;
         _resolve(node: node, rawType: method.type, name: function.name);
         return;
       } else {
-        // TODO(srawlins): Report CompileTimeErrorCode.UNDEFINED_METHOD.
+        _resolver.errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_METHOD,
+          function,
+          [function.name, enclosingClass],
+        );
+        function.staticType = DynamicTypeImpl.instance;
+        node.staticType = DynamicTypeImpl.instance;
         return;
       }
-
-      // TODO(srawlins): if `(target is PropertyAccessorElement)`, report an
-      // error.
     }
 
     // Classes and type aliases are checked first so as to include a
@@ -504,18 +516,34 @@
         _resolveTypeAlias(node: node, element: element, typeAlias: function);
         return;
       }
-    } else if (element is ExecutableElement) {
+    } else if (element is MethodElement) {
       function.staticElement = element;
       function.staticType = element.type;
       _resolve(node: node, rawType: element.type, name: element.name);
       return;
+    } else if (element is FunctionElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolve(node: node, rawType: element.type, name: element.name);
+      return;
+    } else if (element is PropertyAccessorElement) {
+      function.staticElement = element;
+      function.staticType = element.returnType;
+      _resolveDisallowedExpression(node, element.returnType);
+      return;
+    } else if (element is ExecutableElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolveDisallowedExpression(node, element.type);
+      return;
     } else if (element is VariableElement) {
       function.staticElement = element;
       function.staticType = element.type;
       _resolveDisallowedExpression(node, element.type);
       return;
     } else {
-      node.staticType = DynamicTypeImpl.instance;
+      _resolveDisallowedExpression(node, DynamicTypeImpl.instance);
+      return;
     }
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 21ffd13..3675f92 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -41,6 +41,26 @@
     assertType(reference, 'dynamic');
   }
 
+  test_extensionGetter_extensionOverride() async {
+    await assertErrorsInCode('''
+class A {}
+
+extension E on A {
+  int get foo => 0;
+}
+
+bar(A a) {
+  E(a).foo<int>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 67, 8),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
   test_extensionMethod() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -175,21 +195,41 @@
         reference, findElement.method('foo'), 'void Function(int)');
   }
 
+  test_instanceGetter() async {
+    await assertErrorsInCode('''
+abstract class A {
+  late void Function<T>(T) foo;
+
+  bar() {
+    foo<int>;
+  }
+}
+
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 66, 3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'void Function(int)');
+  }
+
   test_instanceGetter_explicitReceiver() async {
-    // This test is here to assert that the resolver does not throw, but in the
-    // future, an error should be reported here as well.
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 class A {
-  int foo = 0;
+  late void Function<T>(T) foo;
 }
 
 bar(A a) {
   a.foo<int>;
 }
-''');
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 58, 5),
+    ]);
 
     var reference = findNode.functionReference('foo<int>;');
-    assertType(reference, 'dynamic');
+    assertType(reference, 'void Function(int)');
   }
 
   test_instanceMethod() async {
@@ -430,6 +470,21 @@
         reference, findElement.method('foo'), 'void Function(int)');
   }
 
+  test_instanceMethod_unknown() async {
+    await assertErrorsInCode('''
+class A {
+  bar() {
+    foo<int>;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_METHOD, 24, 3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
   test_localFunction() async {
     await assertNoErrorsInCode('''
 void bar() {
@@ -722,7 +777,20 @@
     );
   }
 
-  test_topLevelVariable_prefix_unknown() async {
+  test_topLevelFunction_prefix_unknownPrefix() async {
+    await assertErrorsInCode('''
+bar() {
+  prefix.foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 6),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
+  test_topLevelVariable_prefix_unknownIdentifier() async {
     newFile('$testPackageLibPath/a.dart', content: '');
     await assertErrorsInCode('''
 import 'a.dart' as prefix;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7ebeb28..1903854 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -18902,6 +18902,49 @@
   return true;
 }
 
+static ClassPtr EnsureSymbolClass(Thread* thread) {
+  ObjectStore* const store = thread->isolate_group()->object_store();
+
+  if (store->symbol_class() != Class::null()) {
+    return store->symbol_class();
+  }
+  Zone* const zone = thread->zone();
+  const auto& library = Library::Handle(zone, Library::InternalLibrary());
+  const auto& symbol_class =
+      Class::Handle(zone, library.LookupClass(Symbols::Symbol()));
+  ASSERT(!symbol_class.IsNull());
+  store->set_symbol_class(symbol_class);
+  return symbol_class.ptr();
+}
+
+bool Symbol::IsSymbolCid(classid_t class_id) {
+  Thread* const thread = Thread::Current();
+  Zone* const zone = thread->zone();
+
+  Class& symbol_class = Class::Handle(zone, EnsureSymbolClass(thread));
+
+  return class_id == symbol_class.id();
+}
+
+// Must be kept in sync with Symbol.hashCode in symbol_patch.dart
+uint32_t Symbol::CanonicalizeHash(const Instance& instance) {
+  ASSERT(IsSymbolCid(instance.GetClassId()));
+
+  Thread* const thread = Thread::Current();
+  Zone* const zone = thread->zone();
+
+  Class& symbol_class = Class::Handle(zone, EnsureSymbolClass(thread));
+  const auto& symbol_name_field = Field::Handle(
+      zone, symbol_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
+  ASSERT(!symbol_name_field.IsNull());
+
+  // Keep in sync with sdk/lib/_internal/vm/lib/symbol_patch.dart.
+  const auto& name =
+      String::Cast(Object::Handle(zone, instance.GetField(symbol_name_field)));
+  const uint32_t arbitrary_prime = 664597;
+  return 0x1fffffff & (arbitrary_prime * name.CanonicalizeHash());
+}
+
 uint32_t Instance::CanonicalizeHash() const {
   if (GetClassId() == kNullCid) {
     return 2011;  // Matches null_patch.dart.
@@ -18914,41 +18957,46 @@
   Zone* zone = thread->zone();
   const Class& cls = Class::Handle(zone, clazz());
   NoSafepointScope no_safepoint(thread);
-  const intptr_t instance_size = SizeFromClass();
-  ASSERT(instance_size != 0);
-  hash = instance_size / kCompressedWordSize;
-  uword this_addr = reinterpret_cast<uword>(this->untag());
-  Object& obj = Object::Handle(zone);
-  Instance& instance = Instance::Handle(zone);
 
-  const auto unboxed_fields_bitmap =
-      thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
-          GetClassId());
+  if (Symbol::IsSymbolCid(GetClassId())) {
+    hash = Symbol::CanonicalizeHash(*this);
+  } else {
+    const intptr_t instance_size = SizeFromClass();
+    ASSERT(instance_size != 0);
+    hash = instance_size / kCompressedWordSize;
+    uword this_addr = reinterpret_cast<uword>(this->untag());
+    Object& obj = Object::Handle(zone);
+    Instance& instance = Instance::Handle(zone);
 
-  for (intptr_t offset = Instance::NextFieldOffset();
-       offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
-    if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
-      if (kCompressedWordSize == 8) {
-        hash = CombineHashes(hash,
-                             *reinterpret_cast<uint32_t*>(this_addr + offset));
-        hash = CombineHashes(
-            hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
+    const auto unboxed_fields_bitmap =
+        thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
+            GetClassId());
+
+    for (intptr_t offset = Instance::NextFieldOffset();
+         offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
+      if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+        if (kCompressedWordSize == 8) {
+          hash = CombineHashes(
+              hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
+          hash = CombineHashes(
+              hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
+        } else {
+          hash = CombineHashes(
+              hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
+        }
       } else {
-        hash = CombineHashes(hash,
-                             *reinterpret_cast<uint32_t*>(this_addr + offset));
-      }
-    } else {
-      obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
-                ->Decompress(untag()->heap_base());
-      if (obj.IsSentinel()) {
-        hash = CombineHashes(hash, 11);
-      } else {
-        instance ^= obj.ptr();
-        hash = CombineHashes(hash, instance.CanonicalizeHash());
+        obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
+                  ->Decompress(untag()->heap_base());
+        if (obj.IsSentinel()) {
+          hash = CombineHashes(hash, 11);
+        } else {
+          instance ^= obj.ptr();
+          hash = CombineHashes(hash, instance.CanonicalizeHash());
+        }
       }
     }
+    hash = FinalizeHash(hash, String::kHashBits);
   }
-  hash = FinalizeHash(hash, String::kHashBits);
   thread->heap()->SetCanonicalHash(ptr(), hash);
   return hash;
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 3b80f79..718d4ca 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -9120,6 +9120,14 @@
   friend class Number;
 };
 
+// TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
+class Symbol : public AllStatic {
+ public:
+  static bool IsSymbolCid(classid_t class_id);
+
+  static uint32_t CanonicalizeHash(const Instance& instance);
+};
+
 // String may not be '\0' terminated.
 class String : public Instance {
  public:
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 0bce1aa..dae798f 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -4874,8 +4874,7 @@
     const char* value_script,
     uint32_t hashcode_canonicalize_vm = kCalculateCanonizalizeHash,
     bool check_identity = true,
-    bool check_hashcode = true,
-    bool print_failure = true) {
+    bool check_hashcode = true) {
   auto kScriptChars = Utils::CStringUniquePtr(
       OS::SCreate(nullptr,
                   "%s"
@@ -4929,7 +4928,7 @@
     success &= identity_hashcode_dart == hashcode_canonicalize_vm;
   }
 
-  if (!success && print_failure) {
+  if (!success) {
     LogBlock lb;
     THR_Print(
         "Dart hashCode or Dart identityHashCode does not equal VM "
@@ -4991,6 +4990,15 @@
   EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
 }
 
+TEST_CASE(HashCode_Symbol) {
+  const char* kScript =
+      "value() {\n"
+      "  return #A;\n"
+      "}\n";
+  EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kCalculateCanonizalizeHash,
+                                        /*check_identity=*/false));
+}
+
 TEST_CASE(HashCode_True) {
   const char* kScript =
       "value() {\n"
diff --git a/sdk/lib/_internal/vm/lib/symbol_patch.dart b/sdk/lib/_internal/vm/lib/symbol_patch.dart
index 06eb588..eeb9e0b 100644
--- a/sdk/lib/_internal/vm/lib/symbol_patch.dart
+++ b/sdk/lib/_internal/vm/lib/symbol_patch.dart
@@ -6,6 +6,7 @@
 
 @patch
 class Symbol {
+  // TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
   @patch
   const Symbol(String name) : this._name = name;
 
@@ -52,6 +53,7 @@
     return result.toString();
   }
 
+  // Must be kept in sync with Symbol::CanonicalizeHash in object.cc.
   @patch
   int get hashCode {
     const arbitraryPrime = 664597;
diff --git a/sdk/lib/internal/symbol.dart b/sdk/lib/internal/symbol.dart
index 718ac68..2ccb071 100644
--- a/sdk/lib/internal/symbol.dart
+++ b/sdk/lib/internal/symbol.dart
@@ -12,7 +12,9 @@
  * make it accessible to Dart platform code via the static method
  * [getName].
  */
+@pragma('vm:entry-point')
 class Symbol implements core.Symbol {
+  @pragma('vm:entry-point')
   final String _name;
 
   /**
diff --git a/tools/VERSION b/tools/VERSION
index d5ad021..e6e0d78 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 351
+PRERELEASE 352
 PRERELEASE_PATCH 0
\ No newline at end of file