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:
committed by
commit-bot@chromium.org
parent
3f931429c3
commit
63e5b0db57
+128
-3
@@ -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`
|
||||
|
||||
Reference in New Issue
Block a user