From a2adab7dfdc069175abfc667c9f75a43811c69d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Tue, 15 Nov 2022 15:41:49 +0000 Subject: [PATCH] Update Function class documentation: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Language spec does not require that evaluations of the same function literal should create distinct objects. Remove the parts in `Function` documentation to reflect that. Also fixes formatting of markdown. Invalid test file (with Dart 2 and 3 versions) removed: the tests assume function literals won't be lifted to top-level. Change-Id: Ib7a9464ad992cf461e77ef2d8ef336c7b0f4875a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/269721 Reviewed-by: Lasse Nielsen Reviewed-by: Aske Simon Christensen Commit-Queue: Ömer Ağacan Reviewed-by: Erik Ernst --- .../tests/concurrency/stress_test_list.json | 2 - sdk/lib/core/function.dart | 65 +++++++++++++------ .../function/local_non_equal_test.dart | 33 ---------- .../function/local_non_equal_test.dart | 35 ---------- 4 files changed, 46 insertions(+), 89 deletions(-) delete mode 100644 tests/language/function/local_non_equal_test.dart delete mode 100644 tests/language_2/function/local_non_equal_test.dart diff --git a/runtime/tests/concurrency/stress_test_list.json b/runtime/tests/concurrency/stress_test_list.json index e901d31f95215..84518822baacf 100644 --- a/runtime/tests/concurrency/stress_test_list.json +++ b/runtime/tests/concurrency/stress_test_list.json @@ -1112,7 +1112,6 @@ "../../../tests/language/function/local2_test.dart", "../../../tests/language/function/local3_test.dart", "../../../tests/language/function/local_function_test.dart", - "../../../tests/language/function/local_non_equal_test.dart", "../../../tests/language/function/malformed_result_type_runtime_test.dart", "../../../tests/language/function/propagation_test.dart", "../../../tests/language/function/regress_45601_test.dart", @@ -4516,7 +4515,6 @@ "../../../tests/language_2/function/local2_test.dart", "../../../tests/language_2/function/local3_test.dart", "../../../tests/language_2/function/local_function_test.dart", - "../../../tests/language_2/function/local_non_equal_test.dart", "../../../tests/language_2/function/malformed_result_type_runtime_test.dart", "../../../tests/language_2/function/propagation_test.dart", "../../../tests/language_2/function/regress_45601_test.dart", diff --git a/sdk/lib/core/function.dart b/sdk/lib/core/function.dart index 608b542ff35b8..7ec53f370482b 100644 --- a/sdk/lib/core/function.dart +++ b/sdk/lib/core/function.dart @@ -148,17 +148,17 @@ abstract class Function { /// Test whether another object is equal to this function. /// - /// Function objects are only equal to other function objects - /// (an object satisfying `object is Function`), - /// and never to non-function objects. + /// Function objects are only equal to other function objects (an object + /// satisfying `object is Function`), and never to non-function objects. /// - /// Some function objects are considered equal by `==` - /// because they are recognized as representing the "same function": + /// Some function objects are considered equal by `==` because they are + /// recognized as representing the "same function": /// /// - It is the same object. Static and top-level functions are compile time /// constants when used as values, so referring to the same function twice /// always yields the same object, as does referring to a local function /// declaration twice in the same scope where it was declared. + /// /// ```dart /// void main() { /// assert(identical(print, print)); @@ -166,34 +166,61 @@ abstract class Function { /// assert(identical(add, add)); /// } /// ``` + /// /// - The functions are same member method extracted from the same object. - /// Repeatedly extracting ("tearing off") the same instance method of - /// the same object to a function value - /// gives equal, but not necessarily identical, function values. + /// Repeatedly extracting ("tearing off") the same instance method of the + /// same object to a function value gives equal, but not necessarily + /// identical, function values. + /// /// ```dart /// var o = Object(); /// assert(o.toString == o.toString); /// ``` + /// /// - Instantiations of equal generic functions with the *same* types /// yields equal results. + /// /// ```dart - /// T id(T value) => value; - /// assert(id == id); + /// T id(T value) => value; + /// assert(id == id); /// ``` - /// (If the function is a constant and the type arguments are known at - /// compile-time, the results may also be identical.) - /// - /// Different evaluations of function literals - /// never give rise to equal function objects. - /// Each time a function literal is evaluated, - /// it creates a new function value that is not equal to any other function - /// value, not even ones created by the same expression. + /// + /// (If the function is a constant and the type arguments are known at + /// compile-time, the results may also be identical.) + /// + /// Different evaluations of function literals are not guaranteed or required + /// to give rise to identical or equal function objects. For example: + /// /// ```dart /// var functions = []; /// for (var i = 0; i < 2; i++) { /// functions.add((x) => x); /// } - /// assert(functions[0] != functions[1]); + /// print(identical(functions[0], functions[1])); // 'true' or 'false' + /// print(functions[0] == functions[1]); // 'true' or 'false' /// ``` + /// + /// If the distinct values are identical, they are always equal. + /// + /// If the function values are equal, they are guaranteed to behave + /// indistinguishably for all arguments. + /// + /// If two functions values behave differently, they are never equal or + /// identical. + /// + /// The reason to not require a specific equality or identity of the values + /// of a function expression is to allow compiler optimizations. If a + /// function expression does not depend on surrounding variables, an + /// implementation can safely be shared between multiple evaluations. For + /// example: + /// + /// ```dart + /// List ints = [6, 2, 5, 1, 4, 3]; + /// ints.sort((x, y) => x - y); + /// print(ints); + /// ``` + /// + /// A compiler can convert the closure `(x, y) => x - y` into a top-level + /// function. bool operator ==(Object other); } diff --git a/tests/language/function/local_non_equal_test.dart b/tests/language/function/local_non_equal_test.dart deleted file mode 100644 index 5fbaf57dc435b..0000000000000 --- a/tests/language/function/local_non_equal_test.dart +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import "package:expect/expect.dart"; - -foo() => () => 42; -bar() { - var c = () => 54; - return c; -} - -baz() { - c() => 68; - return c; -} - -main() { - var first = foo(); - var second = foo(); - Expect.isFalse(identical(first, second)); - Expect.notEquals(first, second); - - first = bar(); - second = bar(); - Expect.isFalse(identical(first, second)); - Expect.notEquals(first, second); - - first = baz(); - second = baz(); - Expect.isFalse(identical(first, second)); - Expect.notEquals(first, second); -} diff --git a/tests/language_2/function/local_non_equal_test.dart b/tests/language_2/function/local_non_equal_test.dart deleted file mode 100644 index 8111821169ec2..0000000000000 --- a/tests/language_2/function/local_non_equal_test.dart +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// @dart = 2.9 - -import "package:expect/expect.dart"; - -foo() => () => 42; -bar() { - var c = () => 54; - return c; -} - -baz() { - c() => 68; - return c; -} - -main() { - var first = foo(); - var second = foo(); - Expect.isFalse(identical(first, second)); - Expect.notEquals(first, second); - - first = bar(); - second = bar(); - Expect.isFalse(identical(first, second)); - Expect.notEquals(first, second); - - first = baz(); - second = baz(); - Expect.isFalse(identical(first, second)); - Expect.notEquals(first, second); -}