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:
committed by
commit-bot@chromium.org
parent
48c0eadb86
commit
39a2e69ea4
@@ -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,
|
||||
|
||||
@@ -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)];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user