Version 2.15.0-220.0.dev
Merge commit '14bcf0f3d4bc02ab3b4ea421476e78aadaccefae' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d4be95..2680c55 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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`
diff --git a/build/gn_run_binary.py b/build/gn_run_binary.py
index 9b3c32d..99cd20c 100755
--- a/build/gn_run_binary.py
+++ b/build/gn_run_binary.py
@@ -45,12 +45,9 @@
return 1
# Unless the path is absolute, this script is designed to run binaries
- # produced by the current build. We always prefix it with "./" to avoid
- # picking up system versions that might also be on the path.
- if os.path.isabs(argv[2]):
- path = argv[2]
- else:
- path = './' + argv[2]
+ # produced by the current build, which is the current working directory when
+ # this script is run.
+ path = os.path.abspath(argv[2])
if not os.path.isfile(path):
print("Binary not found: " + path)
diff --git a/pkg/dartdev/lib/src/templates/web_simple.dart b/pkg/dartdev/lib/src/templates/web_simple.dart
index 2dde7de..6ea2eb1 100644
--- a/pkg/dartdev/lib/src/templates/web_simple.dart
+++ b/pkg/dartdev/lib/src/templates/web_simple.dart
@@ -48,8 +48,8 @@
# path: ^1.7.0
dev_dependencies:
- build_runner: ^1.10.0
- build_web_compilers: ^2.11.0
+ build_runner: ^2.1.4
+ build_web_compilers: ^3.2.1
lints: ^1.0.0
''';
diff --git a/tools/VERSION b/tools/VERSION
index a3831ae..cfac96c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 219
+PRERELEASE 220
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 6a2efbb..9c4cd3f 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -148,7 +148,7 @@
# Explicitly set DFE so Dart doesn't implicitly depend on the kernel service
# snapshot (creating a circular dep. for kernel-service_snapshot).
- dfe = "NEVER LOADED"
+ dfe = "NEVER_LOADED"
abs_depfile = rebase_path(depfile)
abs_output = rebase_path(output)