[vm] Fix equality of closures instantiated from the same closure
TEST=co19/LanguageFeatures/Constructor-tear-offs/equality_A03_t01
TEST=co19/LanguageFeatures/Constructor-tear-offs/equality_A03_t02
TEST=co19/LanguageFeatures/Constructor-tear-offs/equality_A03_t04
Fixes https://github.com/dart-lang/sdk/issues/47317
Change-Id: I380cbabe5406f1a8cd5ccf180eb392f36f77f164
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215620
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index 77800d4..908fc31 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -40,22 +40,22 @@
return false;
}
const auto& other_closure = Closure::Cast(other);
- // Closures that are not implicit closures (tear-offs) are unique.
const auto& func_a = Function::Handle(zone, receiver.function());
- if (!func_a.IsImplicitClosureFunction()) {
- return false;
- }
const auto& func_b = Function::Handle(zone, other_closure.function());
- if (!func_b.IsImplicitClosureFunction()) {
- return false;
- }
- // If the closure functions are not the same, check the function's name and
- // owner, as multiple function objects could exist for the same function due
- // to hot reload.
- if (func_a.ptr() != func_b.ptr() &&
- (func_a.name() != func_b.name() || func_a.Owner() != func_b.Owner() ||
- func_a.is_static() != func_b.is_static())) {
- return false;
+ // Check that functions match.
+ if (func_a.ptr() != func_b.ptr()) {
+ // Closure functions that are not implicit closures (tear-offs) are unique.
+ if (!func_a.IsImplicitClosureFunction() ||
+ !func_b.IsImplicitClosureFunction()) {
+ return false;
+ }
+ // If the closure functions are not the same, check the function's name and
+ // owner, as multiple function objects could exist for the same function due
+ // to hot reload.
+ if ((func_a.name() != func_b.name() || func_a.Owner() != func_b.Owner() ||
+ func_a.is_static() != func_b.is_static())) {
+ return false;
+ }
}
// Check that the delayed type argument vectors match.
if (receiver.delayed_type_arguments() !=
@@ -72,11 +72,25 @@
return false;
}
}
- if (!func_a.is_static()) {
- // Check that the both receiver instances are the same.
- const Context& context_a = Context::Handle(zone, receiver.context());
- const Context& context_b = Context::Handle(zone, other_closure.context());
- return context_a.At(0) == context_b.At(0);
+ if (func_a.IsImplicitClosureFunction() &&
+ func_b.IsImplicitClosureFunction()) {
+ if (!func_a.is_static()) {
+ // Check that the both receiver instances are the same.
+ const Context& context_a = Context::Handle(zone, receiver.context());
+ const Context& context_b = Context::Handle(zone, other_closure.context());
+ return context_a.At(0) == context_b.At(0);
+ }
+ } else {
+ // Non-identical closures which are not tear-offs can be equal only if
+ // they are different instantiations of the same generic closure.
+ if (!func_a.IsGeneric() || receiver.IsGeneric() ||
+ (receiver.context() != other_closure.context()) ||
+ (receiver.instantiator_type_arguments() !=
+ other_closure.instantiator_type_arguments()) ||
+ (receiver.function_type_arguments() !=
+ other_closure.function_type_arguments())) {
+ return false;
+ }
}
return true;
}