Update CHANGELOG.md to include information about function updates

In 2.15, function objects have had their specification and
implementation updated such that several inconsistencies have been
eliminated, and the specification has been clarified and generalized.
In particular, equality is now more consistent and compositional,
canonicalization is applied also for expressions that are constant
but not in a constant context, generic instantiation gives rise to
function objects that are identical/equal in cases where they weren't
previously, and similarly for some tearoffs.

Change-Id: Ic26bbc1f047500c1030f52fe69bb06963b0193f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/216289
Reviewed-by: Michael Thomsen <mit@google.com>
Commit-Queue: Erik Ernst <eernst@google.com>
This commit is contained in:
Erik Ernst 2021-10-14 09:23:52 +00:00 committed by commit-bot@chromium.org
parent 3f931429c3
commit 63e5b0db57

View file

@ -134,8 +134,7 @@
greater (if using a beta preview release, an sdk constraint of
`>=2.15.0-0` must be used).
- **[Explicit generic method instantiations][Explicit instantiation]**: **BETA
PREVIEW**
- **[Explicit generic method instantiations][Explicit instantiation]**: **BETA PREVIEW**
Previous Dart versions allowed generic methods to be implicitly specialized
(or "instantiated") to non-generic versions when assigned to a location with a
@ -197,6 +196,65 @@
[Explicit instantiation]:
https://github.com/dart-lang/language/blob/master/accepted/future-releases/constructor-tearoffs/feature-specification.md#explicitly-instantiated-classes-and-functions
- **[Generic instantiation of function objects][Object instantiation]**: **BETA PREVIEW**
Generic function instantiation was previously restricted to function
declarations. For example, as soon as a function had already been torn
off, it could not be instantiated:
```dart
X id<X>(X x) => x;
void main() {
var fo = id; // Tear off `id`, creating a function object.
var c1 = fo<int>; // Compile-time error: can't instantiate `fo`.
int Function(int) c2 = fo; // Same compile-time error.
// Constants are treated the same.
}
```
New in Dart 2.15, this restriction has been lifted, and it is now possible
to obtain a generic instantiation of an existing function object, both
explicitly and implicitly (again, this works the same for non-constants):
```dart
X id<X>(X x) => x;
X other<X>(X x) => throw x;
void main() {
const fo = id; // Tear off `id`, creating a function object.
// Generic function instantiation on `fo` is no longer an error.
const c1 = fo<int>; // OK.
const int Function(int) c2 = fo; // OK.
// This also generalizes function instantiation because we can,
// e.g., use non-trivial expressions and go via a constructor.
const c3 = A(true); // OK.
}
class A {
final int Function(int) x;
// `(...)<T>` is now allowed, also in a `const` constructor.
const A(bool b): x = (b ? id : other)<int>;
}
```
The new generic instantation of objects feature is currently in **BETA
PREVIEW**. The feature is enabled in beta releases only, and is still subject
to breaking changes. It is not fully supported by all tools and there may be
known issues with the tool support. Feedback on the feature is welcome, but it
is not recommended that production code use the feature until it has been
released in a stable version.
Generic instantiation of objects is only available as part of the 2.15
[language version](https://dart.dev/guides/language/evolution). To use this
feature, you must set the lower bound on the sdk constraint for your package
to 2.15 or greater (if using a beta preview release, an sdk constraint of
`>=2.15.0-0` must be used).
[Object instantiation]: https://github.com/dart-lang/language/pull/1812
- Annotations on type parameters of classes can no longer refer to class members
without a prefix. For example, this used to be permitted:
@ -226,7 +284,7 @@
if (!iIsNull) {
print(i + 1); // OK, because `i` is known to be non-null
}
}<>
}
```
Previously, the above program had a compile-time error because type promotion
@ -266,6 +324,73 @@
instance variable, and it brings the implementation behavior in line with
the specification in all other cases.
- **Function object canonicalization and equality**
Several corner cases in the area of function object canonicalization and
function object equality have been updated, such that all tools behave in
the same way, and the behavior matches the specification.
In particular, function objects are now equal when they are obtained by
generic instantiation from the same function with the same actual type
arguments, even when that type argument is not known at compile time.
When the expressions are constant then said function objects are identical.
Constant expressions are treated as such even when they do not occur in a
constant context (e.g., `var f = top;`). Here are the main cases where the
behavior has been adjusted:
```dart
void top() {}
X? genericTop<X>() => null;
class A {
static void stat() {}
static X? genericStat<X>() => null;
void inst() {}
X? genericInst<X>() => null;
}
const int? Function() cIntTop1 = genericTop;
const int? Function() cIntStat1 = A.genericStat;
int? Function() vIntTop1 = genericTop;
int? Function() vIntStat1 = A.genericStat;
int? Function() vIntTop2 = genericTop;
int? Function() vIntStat2 = A.genericStat;
String? Function() vStringTop = genericTop;
String? Function() vStringStat = A.genericStat;
void main() {
var a = A();
int? Function() vIntInst1 = a.genericInst;
int? Function() vIntInst2 = a.genericInst;
// All true (used to be false).
identical(cIntTop1, vIntTop2);
identical(cIntStat1, vIntStat2);
identical(vIntTop1, vIntTop2);
identical(vIntStat1, vIntStat2);
vIntInst1 == vIntInst2;
<X>() {
X? Function() vXTop1 = genericTop;
X? Function() vXStat1 = A.genericStat;
X? Function() vXTop2 = genericTop;
X? Function() vXStat2 = A.genericStat;
X? Function() vXInst1 = a.genericInst;
X? Function() vXInst2 = a.genericInst;
// All true (used to be false).
vXTop1 == vXTop2;
vXStat1 == vXStat2;
vXInst1 == vXInst2;
vXTop1 == vIntTop1;
vXStat1 == vIntStat1;
vXInst1 == vIntInst2;
}<int>();
}
```
### Core libraries
#### `dart:async`