[flip-patterns] Enable "records" and "patterns" experiment flags.

This turns on the flags for these two language features and makes
them generally accessible.

Doing so causes a number of tests to fail, but the failures are
approved and there are filed issues for them. Most of the
failures are minor or only affect code using the new language
features.

This CL:

- Enables the features in experimental_features.yaml.
- Re-generates all of the various files generated from that.
- Makes some analyzer and front end changes that this CL
  inherited from Paul's original CL flipping all of the 3.0
  feature flags. I don't know what these changes are about, but
  I assume they are necessary.
- Pins a couple of tests to 2.19 since they deliberately test
  behavior that is specific to 2.19. (For most test changes, I've
  landed them separately, but there are a couple of stragglers
  in this CL.)

This doesn't enable "class-modifiers" or "sealed-types" and doesn't
include the core lib changes related to those.

TEST=On bots

Change-Id: Id387753772286a958e20a3589a6e983995f2e4a6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286344
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Robert Nystrom 2023-03-10 20:02:23 +00:00 committed by Commit Queue
parent af52197dd6
commit 56eaffb392
25 changed files with 97 additions and 89 deletions

View file

@ -123,14 +123,14 @@ enum ExperimentalFlag {
patterns(
name: 'patterns',
isEnabledByDefault: false,
isEnabledByDefault: true,
isExpired: false,
experimentEnabledVersion: const Version(3, 0),
experimentReleasedVersion: const Version(3, 0)),
records(
name: 'records',
isEnabledByDefault: false,
isEnabledByDefault: true,
isExpired: false,
experimentEnabledVersion: const Version(3, 0),
experimentReleasedVersion: const Version(3, 0)),

View file

@ -23,6 +23,7 @@ class RemoveDuplicateCaseBulkTest extends BulkFixProcessorTest {
Future<void> test_singleFile() async {
await resolveTestCode('''
// @dart = 2.19
void switchInt() {
switch (2) {
case 1:
@ -38,6 +39,7 @@ void switchInt() {
}
''');
await assertHasFix('''
// @dart = 2.19
void switchInt() {
switch (2) {
case 1:

View file

@ -305,7 +305,7 @@ class ExperimentalFeatures {
isExpired: IsExpired.patterns,
documentation: 'Patterns',
experimentalReleaseVersion: null,
releaseVersion: null,
releaseVersion: Version.parse('3.0.0'),
);
static final records = ExperimentalFeature(
@ -315,7 +315,7 @@ class ExperimentalFeatures {
isExpired: IsExpired.records,
documentation: 'Records',
experimentalReleaseVersion: null,
releaseVersion: null,
releaseVersion: Version.parse('3.0.0'),
);
static final sealed_class = ExperimentalFeature(
@ -462,10 +462,10 @@ class IsEnabledByDefault {
static const bool nonfunction_type_aliases = true;
/// Default state of the experiment "patterns"
static const bool patterns = false;
static const bool patterns = true;
/// Default state of the experiment "records"
static const bool records = false;
static const bool records = true;
/// Default state of the experiment "sealed-class"
static const bool sealed_class = true;

View file

@ -503,6 +503,11 @@ class ExitDetector extends GeneralizingAstVisitor<bool> {
bool visitSwitchDefault(SwitchDefault node) =>
_visitStatements(node.statements);
@override
bool visitSwitchPatternCase(SwitchPatternCase node) {
return _visitStatements(node.statements);
}
@override
bool visitSwitchStatement(SwitchStatement node) {
bool outerBreakValue = _enclosingBlockContainsBreak;

View file

@ -1540,7 +1540,6 @@ void Function<A>(core.List<core.int> x) m() => null;
// https://github.com/dart-lang/sdk/issues/37693
parseCompilationUnit('class C{ C() : super() * (); }', errors: [
expectedError(ParserErrorCode.INVALID_INITIALIZER, 15, 12),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 25, 1),
]);
}

View file

@ -1440,7 +1440,6 @@ class Wrong<T> {
expectNotNullIfNoErrors(statement);
listener.assertErrors([
expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
]);
}

View file

@ -490,7 +490,6 @@ class B = Object with A {}''', codes:
CompilationUnit unit =
parseCompilationUnit("class A { A() : a = (){}; var v; }", codes: [
ParserErrorCode.EXPECTED_CLASS_MEMBER,
ParserErrorCode.EXPERIMENT_NOT_ENABLED,
]);
// Make sure we recovered and parsed "var v" correctly
ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;

View file

@ -126,7 +126,6 @@ class C {
expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 18, 5),
expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 24, 5),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 5),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 29, 1),
]);
}

View file

@ -929,43 +929,7 @@ void f() { // ref
@reflectiveTest
class ExitDetectorResolvedStatementTest extends PubPackageResolutionTest
with ExitDetectorResolvedStatementTestCases {
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/50502')
@override
test_switch_withEnum_false_noDefault() {
return super.test_switch_withEnum_false_noDefault();
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/50502')
@override
test_switch_withEnum_false_withDefault() {
return super.test_switch_withEnum_false_withDefault();
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/50502')
@override
test_switch_withEnum_true_noDefault() {
return super.test_switch_withEnum_true_noDefault();
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/50502')
@override
test_switch_withEnum_true_withExitingDefault() {
return super.test_switch_withEnum_true_withExitingDefault();
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/50502')
@override
test_switch_withEnum_true_withNonExitingDefault() {
return super.test_switch_withEnum_true_withNonExitingDefault();
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/50502')
@override
test_whileStatement_switchWithBreakWithLabel() {
return super.test_whileStatement_switchWithBreakWithLabel();
}
}
with ExitDetectorResolvedStatementTestCases {}
@reflectiveTest
class ExitDetectorResolvedStatementTest_Language218

View file

@ -37,7 +37,8 @@ class AssertStatementTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
]),
TestDescriptor(
'condition',

View file

@ -78,7 +78,8 @@ class DoStatementTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
]),
TestDescriptor(
'condition',

View file

@ -32,7 +32,8 @@ class IfStatementTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
],
),
TestDescriptor(

View file

@ -70,7 +70,8 @@ class IndexStatementTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
],
),
TestDescriptor(

View file

@ -128,7 +128,8 @@ class LocalVariableTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
]),
TestDescriptor('varNameEqualsExpression', 'var a = b',
[ParserErrorCode.EXPECTED_TOKEN], "var a = b;"),

View file

@ -42,7 +42,8 @@ class SwitchStatementTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
]),
TestDescriptor(
'expression',

View file

@ -87,7 +87,8 @@ class WhileStatementTest extends PartialCodeTest {
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'return'
'return',
'switch',
],
),
TestDescriptor(

View file

@ -30,6 +30,7 @@ class YieldStatementTest extends PartialCodeTest {
'localFunctionNonVoid',
'localFunctionVoid',
'return',
'switch',
]),
TestDescriptor('expression', 'yield a',
[ParserErrorCode.EXPECTED_TOKEN], "yield a;"),
@ -48,6 +49,7 @@ class YieldStatementTest extends PartialCodeTest {
'localFunctionNonVoid',
'localFunctionVoid',
'return',
'switch',
]),
TestDescriptor('star_expression', 'yield * a',
[ParserErrorCode.EXPECTED_TOKEN], "yield * a;"),

View file

@ -918,7 +918,7 @@ void g() {}
addTestSource(r'''
class C {
final int foo;
C() : ^
}
''');
@ -930,7 +930,7 @@ class C {
addTestSource(r'''
class C {
final int foo;
C() : foo = ^
}
''');
@ -2555,23 +2555,49 @@ main() {
}
Future<void> test_switchCase_expression1() async {
// SimpleIdentifier SwitchCase SwitchStatement
// SimpleIdentifier SwitchPatternCase SwitchStatement
addTestSource('''m() {switch (x) {case ^D: return;}}''');
await assertOpType(
completionLocation: 'SwitchCase_expression',
constructors: true,
returnValue: true,
typeNames: true);
completionLocation: 'SwitchPatternCase_pattern',
typeNames: true,
);
}
Future<void> test_switchCase_expression1_language219() async {
// SimpleIdentifier SwitchCase SwitchStatement
addTestSource('''
// @dart = 2.19
m() {switch (x) {case ^D: return;}}
''');
await assertOpType(
completionLocation: 'SwitchCase_expression',
constructors: true,
returnValue: true,
typeNames: true,
);
}
Future<void> test_switchCase_expression2() async {
// SimpleIdentifier SwitchCase SwitchStatement
// SimpleIdentifier SwitchPatternCase SwitchStatement
addTestSource('''m() {switch (x) {case ^}}''');
await assertOpType(
completionLocation: 'SwitchCase_expression',
constructors: true,
returnValue: true,
typeNames: true);
completionLocation: 'SwitchPatternCase_pattern',
typeNames: true,
);
}
Future<void> test_switchCase_expression2_language219() async {
// SimpleIdentifier SwitchCase SwitchStatement
addTestSource('''
// @dart = 2.19
m() {switch (x) {case ^}}
''');
await assertOpType(
completionLocation: 'SwitchCase_expression',
constructors: true,
returnValue: true,
typeNames: true,
);
}
Future<void> test_switchDefault_before() async {

View file

@ -189,7 +189,7 @@ class ExperimentalFlag {
static const ExperimentalFlag patterns = const ExperimentalFlag(
name: 'patterns',
isEnabledByDefault: false,
isEnabledByDefault: true,
isExpired: false,
enabledVersion: const Version(3, 0),
experimentEnabledVersion: const Version(3, 0),
@ -197,7 +197,7 @@ class ExperimentalFlag {
static const ExperimentalFlag records = const ExperimentalFlag(
name: 'records',
isEnabledByDefault: false,
isEnabledByDefault: true,
isExpired: false,
enabledVersion: const Version(3, 0),
experimentEnabledVersion: const Version(3, 0),

View file

@ -3440,6 +3440,7 @@ SwitchExpressionNotSubtype:
problemMessage: "Type '#type' of the case expression is not a subtype of type '#type2' of this switch expression."
script:
- |
// @dart=2.19
void f() {
switch (42) {
case "foo": break;

View file

@ -2,6 +2,10 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.md file.
# TODO(rnystrom): Temporarily renamed to disable because this test is causing
# the unit tests to hang and is blocking enabling the "records" and "patterns"
# experiments.
main.dart.patch: |
// Regression for crash when attempting to reuse method with compile-time
// error.

View file

@ -44,6 +44,8 @@ const char* GetExperimentalFeatureName(ExperimentalFeature feature) {
"super-parameters",
"inference-update-1",
"unnamed-libraries",
"records",
"patterns",
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
return kFeatureNames[static_cast<int>(feature)];

View file

@ -31,6 +31,8 @@ enum class ExperimentalFeature {
super_parameters,
inference_update_1,
unnamed_libraries,
records,
patterns,
};
bool GetExperimentalFeatureDefault(ExperimentalFeature feature);

View file

@ -2,12 +2,8 @@
// 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.
// In Dart 3.0, any type can be used in a switch case, even if it doesn't have
// primitive equality.
// @dart=2.19
// SharedOptions=--enable-experiment=patterns,records
class SuperClass {
const SuperClass();

View file

@ -130,23 +130,6 @@ features:
inference-update-2:
help: "Type promotion for fields"
records:
help: "Records"
validation: |
final x = (1, 2);
void main() {
final x = ('feature', 'enabled');
print('${x.$1} ${x.$2}');
}
patterns:
help: "Patterns"
validation: |
void main() {
final [x, y] = ['feature', 'enabled'];
print('$x $y');
}
inline-class:
help: "Inline class"
@ -335,3 +318,21 @@ features:
validation: |
library;
void main() => print('feature enabled');
records:
help: "Records"
enabledIn: '3.0.0'
validation: |
final x = ('feature', a: 'enabled');
void main() {
print('${x.$1} ${x.a}');
}
patterns:
help: "Patterns"
enabledIn: '3.0.0'
validation: |
void main() {
final [a, b] = ['feature', 'enabled'];
print('$a $b');
}