Enable non-function type aliases by default in 2.13.

TEST=language/nonfunction-type-aliases

Change-Id: Ifff4e838fbfc4f71e2d990e1f1f8a67b987adf91
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192948
Commit-Queue: Leaf Petersen <leafp@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
This commit is contained in:
Leaf Petersen
2021-04-03 01:31:42 +00:00
committed by commit-bot@chromium.org
parent 48c0eadb86
commit 39a2e69ea4
8 changed files with 112 additions and 10 deletions
+42
View File
@@ -2,6 +2,48 @@
### Language
* **Type aliases** [Non-function type aliases][]: Type aliases (names for
types introduced via the `typedef` keyword) were previously restricted
to only introduce names for function types. In this release, we
remove this restriction and allow type aliases to name any kind of type.
```dart
import 'dart:convert';
typedef JsonMap = Map<String, dynamic>;
JsonMap parseJsonMap(String input) => json.decode(input) as JsonMap;
```
In addition to being usable as type annotations, type aliases that name
class types can now also be used anywhere that the underlying class could be
used, allowing type aliases to be used to safely rename existing classes.
```dart
class NewClassName<T> {
NewClassName.create(T x);
static NewClassName<T> mkOne<T>(T x) => NewClassName<T>.create(x);
}
@Deprecated("Use NewClassName instead")
typedef OldClassName<T> = NewClassName<T>;
class LegacyClass extends OldClassName<int> {
LegacyClass() : super.create(3);
}
OldClassName<int> legacyCode() {
var one = OldClassName.create(1);
var two = OldClassName.mkOne(2);
return LegacyClass();
}
```
The new type alias feature is only available as part of the 2.13 [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.13
or greater.
[Non-function type aliases]: https://github.com/dart-lang/language/blob/master/accepted/2.13/nonfunction-type-aliases/feature-specification.md
### Core libraries
#### `dart:collection`
@@ -152,7 +152,7 @@ class ExperimentalFeatures {
isExpired: IsExpired.nonfunction_type_aliases,
documentation: 'Type aliases define a <type>, not just a <functionType>',
experimentalReleaseVersion: null,
releaseVersion: null,
releaseVersion: Version.parse('2.13.0'),
);
static final set_literals = ExperimentalFeature(
@@ -231,7 +231,7 @@ class IsEnabledByDefault {
static const bool non_nullable = true;
/// Default state of the experiment "nonfunction-type-aliases"
static const bool nonfunction_type_aliases = false;
static const bool nonfunction_type_aliases = true;
/// Default state of the experiment "set-literals"
static const bool set_literals = true;
@@ -87,7 +87,7 @@ const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
ExperimentalFlag.extensionTypes: false,
ExperimentalFlag.genericMetadata: false,
ExperimentalFlag.nonNullable: true,
ExperimentalFlag.nonfunctionTypeAliases: false,
ExperimentalFlag.nonfunctionTypeAliases: true,
ExperimentalFlag.setLiterals: true,
ExperimentalFlag.spreadCollections: true,
ExperimentalFlag.tripleShift: false,
+5 -4
View File
@@ -18,7 +18,7 @@ namespace dart {
bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
constexpr bool kFeatureValues[] = {
true, true, true, true, true, true,
true, true, true, true, true, true, true,
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureValues));
return kFeatureValues[static_cast<int>(feature)];
@@ -26,9 +26,10 @@ bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
const char* GetExperimentalFeatureName(ExperimentalFeature feature) {
constexpr const char* kFeatureNames[] = {
"non-nullable", "extension-methods",
"constant-update-2018", "control-flow-collections",
"set-literals", "spread-collections",
"nonfunction-type-aliases", "non-nullable",
"extension-methods", "constant-update-2018",
"control-flow-collections", "set-literals",
"spread-collections",
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
return kFeatureNames[static_cast<int>(feature)];
+1
View File
@@ -14,6 +14,7 @@
namespace dart {
enum class ExperimentalFeature {
nonfunction_type_aliases,
non_nullable,
extension_methods,
constant_update_2018,
@@ -3,6 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
// Dart test for a function type test that cannot be eliminated at compile time.
// This test validates the static errors for typedefs in language versions
// prior to the release of nonfunction type aliases (Dart 2.13).
// @dart=2.12
import "package:expect/expect.dart";
class A {}
@@ -0,0 +1,47 @@
// Copyright (c) 2017, 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 test for a function type test that cannot be eliminated at compile time.
// This test validates the static errors for typedefs as per the code in
// function_typedef2_test.dart in language versions after the release of
// nonfunction type aliases (Dart 2.13).
import "package:expect/expect.dart";
class A {}
typedef int F();
typedef G = F;
typedef H = int;
typedef I = A;
typedef J = List<int>;
typedef K = Function(Function<A>(A<int>));
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_TYPE_ARGUMENTS
// [cfe] Can't use type arguments with type variable 'A'.
typedef L = Function({x});
// ^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
// [cfe] Type 'x' not found.
// ^
// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
// [cfe] Expected an identifier, but got '}'.
typedef M = Function({int});
// ^
// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
// [cfe] Expected an identifier, but got '}'.
foo({bool int = false}) {}
main() {
bool b = true;
Expect.isFalse(b is L);
Expect.isFalse(b is M);
Expect.isTrue(foo is M);
}
+10 -3
View File
@@ -119,9 +119,6 @@ features:
variance:
help: "Sound variance"
nonfunction-type-aliases:
help: "Type aliases define a <type>, not just a <functionType>"
alternative-invalidation-strategy:
help: "Alternative invalidation strategy for incremental compilation"
category: "CFE"
@@ -143,6 +140,16 @@ features:
# on the command line, and will eventually be removed.
#
nonfunction-type-aliases:
help: "Type aliases define a <type>, not just a <functionType>"
enabledIn: '2.13.0'
validation: |
typedef S = String;
void main() {
S s = 'feature enabled';
print(s);
}
non-nullable:
help: "Non Nullable by default"
experimentalReleaseVersion: '2.10.0'