From 6a464c9dee693f92c8d752680da65aea15b88132 Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Fri, 27 Oct 2023 16:50:09 +0000 Subject: [PATCH] Revert "Expire 3.0.0 experiment flags." This reverts commit 6f29e7fce4b4ef8ed4951b04018c151e15f674d5. Reason for revert: broke g3 bot Original change's description: > Expire 3.0.0 experiment flags. > > TEST=Existing tests covers. > Change-Id: I161eefdc28c74f63ba1ee926800a01eea03d9930 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/331960 > Commit-Queue: Lasse Nielsen > Reviewed-by: Alexander Thomas Change-Id: Ied6f612dc922824ffdadc4660898f3b859922ff5 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/332582 Reviewed-by: Lasse Nielsen Reviewed-by: Alexander Thomas Commit-Queue: Alexander Thomas Auto-Submit: Alexander Aprelev Bot-Commit: Rubber Stamper --- .../lib/src/experiments/flags.dart | 8 +- .../correction/fix/remove_break_test.dart | 4 +- .../lib/src/dart/analysis/experiments.g.dart | 8 +- .../test/inference/record_type_test.dart | 2 +- pkg/dartdev/test/commands/analyze_test.dart | 2 +- .../dap/integration/debug_variables_test.dart | 2 + .../experimental_flags_generated.dart | 8 +- pkg/front_end/messages.yaml | 79 +++++++ .../testcases/class_modifiers/folder.options | 1 + .../testcases/patterns/folder.options | 1 + .../testcases/patterns/records/folder.options | 2 + .../testcases/records/folder.options | 1 + .../testcases/sealed_class/folder.options | 1 + pkg/test_runner/lib/src/test_suite.dart | 3 +- pkg/vm/test/transformations/ffi_test.dart | 4 +- .../test/patterns_local_vars_test.dart | 1 + .../records_allocation_sinking_il_test.dart | 2 + .../records_field_operations_il_test.dart | 2 + ...records_return_value_unboxing_il_test.dart | 2 + runtime/tests/vm/dart/regress_51091_test.dart | 1 + ...vmspecific_static_checks_varargs_test.dart | 1 + .../record_literal_problems_test.dart | 20 ++ tests/language_2/record_literal_test.dart | 61 +++++ .../language_2/record_type_problems_test.dart | 38 +++ tests/language_2/record_type_test.dart | 222 ++++++++++++++++++ tools/experimental_features.yaml | 8 +- 26 files changed, 459 insertions(+), 25 deletions(-) create mode 100644 tests/language_2/record_literal_problems_test.dart create mode 100644 tests/language_2/record_literal_test.dart create mode 100644 tests/language_2/record_type_problems_test.dart create mode 100644 tests/language_2/record_type_test.dart diff --git a/pkg/_fe_analyzer_shared/lib/src/experiments/flags.dart b/pkg/_fe_analyzer_shared/lib/src/experiments/flags.dart index 96752aa489d..d3f97b8e77d 100644 --- a/pkg/_fe_analyzer_shared/lib/src/experiments/flags.dart +++ b/pkg/_fe_analyzer_shared/lib/src/experiments/flags.dart @@ -13,7 +13,7 @@ enum ExperimentalFlag { classModifiers( name: 'class-modifiers', isEnabledByDefault: true, - isExpired: true, + isExpired: false, experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)), @@ -125,21 +125,21 @@ enum ExperimentalFlag { patterns( name: 'patterns', isEnabledByDefault: true, - isExpired: true, + isExpired: false, experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)), records( name: 'records', isEnabledByDefault: true, - isExpired: true, + isExpired: false, experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)), sealedClass( name: 'sealed-class', isEnabledByDefault: true, - isExpired: true, + isExpired: false, experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)), diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart index 50ff1a0d82b..8141c9ff680 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart @@ -19,7 +19,7 @@ void main() { @reflectiveTest class RemoveBreakBulkTest extends BulkFixProcessorTest { @override - List get experiments => []; + List get experiments => ['patterns', 'records']; @override String get lintCode => LintNames.unnecessary_breaks; @@ -76,7 +76,7 @@ void f() { @reflectiveTest class RemoveBreakTest extends FixProcessorLintTest { @override - List get experiments => []; + List get experiments => ['patterns', 'records']; @override FixKind get kind => DartFixKind.REMOVE_BREAK; diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart index 4e48d5b3b13..b8297a226c8 100644 --- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart +++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart @@ -483,7 +483,7 @@ class IsEnabledByDefault { /// value in [IsEnabledByDefault]). class IsExpired { /// Expiration status of the experiment "class-modifiers" - static const bool class_modifiers = true; + static const bool class_modifiers = false; /// Expiration status of the experiment "const-functions" static const bool const_functions = false; @@ -531,13 +531,13 @@ class IsExpired { static const bool nonfunction_type_aliases = true; /// Expiration status of the experiment "patterns" - static const bool patterns = true; + static const bool patterns = false; /// Expiration status of the experiment "records" - static const bool records = true; + static const bool records = false; /// Expiration status of the experiment "sealed-class" - static const bool sealed_class = true; + static const bool sealed_class = false; /// Expiration status of the experiment "set-literals" static const bool set_literals = true; diff --git a/pkg/compiler/test/inference/record_type_test.dart b/pkg/compiler/test/inference/record_type_test.dart index 3b6c47b2c70..b2e7d7b0678 100644 --- a/pkg/compiler/test/inference/record_type_test.dart +++ b/pkg/compiler/test/inference/record_type_test.dart @@ -32,7 +32,7 @@ main() { } """, testBackendWorld: true, - options: [Flags.soundNullSafety]); + options: ['--enable-experiment=records', Flags.soundNullSafety]); JClosedWorld world = env.jClosedWorld; final domain = world.abstractValueDomain as CommonMasks; diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart index db5ff4902e3..50653d73456 100644 --- a/pkg/dartdev/test/commands/analyze_test.dart +++ b/pkg/dartdev/test/commands/analyze_test.dart @@ -448,7 +448,7 @@ analyzer: expect(result.exitCode, 0); expect(result.stdout, contains('No issues found!')); expect(result.stderr, contains("'records' is now enabled by default")); - }, skip: 'records are enabled by default in 3.0'); + }); test('--verbose', () async { p = project(mainSrc: ''' diff --git a/pkg/dds/test/dap/integration/debug_variables_test.dart b/pkg/dds/test/dap/integration/debug_variables_test.dart index 917752941f3..063dd3cdc93 100644 --- a/pkg/dds/test/dap/integration/debug_variables_test.dart +++ b/pkg/dds/test/dap/integration/debug_variables_test.dart @@ -252,6 +252,8 @@ void main(List args) { final stop = await client.hitBreakpoint( testFile, breakpointLine, + // TODO(dantup): Remove toolArgs when this is no longer required. + toolArgs: ['--enable-experiment=records'], ); // Check the fields directly on the record. diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart index 18744d36af5..4fafdd8fbd0 100644 --- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart +++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart @@ -62,7 +62,7 @@ class ExperimentalFlag { static const ExperimentalFlag classModifiers = const ExperimentalFlag( name: 'class-modifiers', isEnabledByDefault: true, - isExpired: true, + isExpired: false, enabledVersion: const Version(3, 0), experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)); @@ -190,7 +190,7 @@ class ExperimentalFlag { static const ExperimentalFlag patterns = const ExperimentalFlag( name: 'patterns', isEnabledByDefault: true, - isExpired: true, + isExpired: false, enabledVersion: const Version(3, 0), experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)); @@ -198,7 +198,7 @@ class ExperimentalFlag { static const ExperimentalFlag records = const ExperimentalFlag( name: 'records', isEnabledByDefault: true, - isExpired: true, + isExpired: false, enabledVersion: const Version(3, 0), experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)); @@ -206,7 +206,7 @@ class ExperimentalFlag { static const ExperimentalFlag sealedClass = const ExperimentalFlag( name: 'sealed-class', isEnabledByDefault: true, - isExpired: true, + isExpired: false, enabledVersion: const Version(3, 0), experimentEnabledVersion: const Version(3, 0), experimentReleasedVersion: const Version(3, 0)); diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml index 808f9b76f24..0ed1a52d195 100644 --- a/pkg/front_end/messages.yaml +++ b/pkg/front_end/messages.yaml @@ -381,6 +381,7 @@ RecordLiteralOnePositionalFieldNoTrailingComma: ```dart var r = const (1,); ``` + experiments: records script: > main() { var record = const (1); @@ -421,6 +422,7 @@ RecordLiteralZeroFieldsWithTrailingComma: ```dart var r = (3, 4); ``` + experiments: records script: > main() { var record = (,); @@ -462,6 +464,7 @@ EmptyRecordTypeNamedFieldsList: ```dart void f((int, int) r) {} ``` + experiments: records script: > main() { (int, int, {/*missing*/}) record = (1, 2,); @@ -502,6 +505,7 @@ RecordTypeZeroFieldsButTrailingComma: ```dart void f((int, int) r) {} ``` + experiments: records script: > main() { (,) record = (); @@ -539,6 +543,7 @@ RecordTypeOnePositionalFieldNoTrailingComma: ```dart void f((int,) r) {} ``` + experiments: records script: > main() { (int /* missing trailing comma */) record = const (1, ); @@ -547,6 +552,7 @@ RecordTypeOnePositionalFieldNoTrailingComma: DuplicatedRecordTypeFieldName: problemMessage: "Duplicated record type field name '#name'." correctionMessage: "Try renaming or removing one of the named record type fields." + experiments: records script: | ({int a, String a}) record = throw ''; @@ -557,6 +563,7 @@ DuplicatedRecordTypeFieldNameContext: DuplicatedRecordLiteralFieldName: problemMessage: "Duplicated record literal field name '#name'." correctionMessage: "Try renaming or removing one of the named record literal fields." + experiments: records script: | dynamic field = (a: 0, a: 1); @@ -743,6 +750,7 @@ MultipleImplements: MultipleClauses: problemMessage: "Each '#string' definition can have at most one '#string2' clause." correctionMessage: "Try combining all of the '#string2' clauses into a single clause." + experiments: enhanced-enums analyzerCode: ParserErrorCode.MULTIPLE_CLAUSES index: 121 script: @@ -752,6 +760,7 @@ MultipleClauses: OutOfOrderClauses: problemMessage: "The '#string' clause must come before the '#string2' clause." correctionMessage: "Try moving the '#string' clause before the '#string2' clause." + experiments: enhanced-enums analyzerCode: ParserErrorCode.OUT_OF_ORDER_CLAUSES index: 122 script: "class B {} class D {} enum A implements B with D { v; }" @@ -1077,6 +1086,7 @@ AbstractSealedClass: ```dart sealed class C {} ``` + experiments: sealed-class script: - "sealed abstract class C {}" - "abstract sealed class C {}" @@ -3602,6 +3612,7 @@ SupertypeIsIllegalAliased: SupertypeIsNullableAliased: problemMessage: "The type '#name' which is an alias of '#type' can't be used as supertype because it is nullable." analyzerCode: EXTENDS_NON_CLASS + experiments: nonfunction-type-aliases script: | class A {} typedef B = A?; @@ -4886,6 +4897,7 @@ IncorrectTypeArgumentInstantiation: problemMessage: "Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3'." correctionMessage: "Try changing type arguments so that they conform to the bounds." analyzerCode: TYPE_ARGUMENT_NOT_MATCHING_BOUNDS + experiments: constructor-tearoffs script: | X bounded(X x) => x; main() { @@ -6122,6 +6134,7 @@ UnsupportedDartExt: InstantiationNonGenericFunctionType: problemMessage: "The static type of the explicit instantiation operand must be a generic function type but is '#type'." correctionMessage: "Try changing the operand or remove the type arguments." + experiments: constructor-tearoffs script: | f() {} main() => f; @@ -6130,12 +6143,14 @@ InstantiationNullableGenericFunctionType: problemMessage: "The static type of the explicit instantiation operand must be a non-null generic function type but is '#type'." correctionMessage: "Try changing the operand or remove the type arguments." analyzerCode: DISALLOWED_TYPE_INSTANTIATION_EXPRESSION + experiments: constructor-tearoffs script: | test(void Function()? f) => f; InstantiationTooFewArguments: problemMessage: "Too few type arguments: #count required, #count2 given." correctionMessage: "Try adding the missing type arguments." + experiments: constructor-tearoffs script: | f() {} main() => f; @@ -6143,12 +6158,14 @@ InstantiationTooFewArguments: InstantiationTooManyArguments: problemMessage: "Too many type arguments: #count allowed, but #count2 found." correctionMessage: "Try removing the extra type arguments." + experiments: constructor-tearoffs script: | f() {} main() => f; AbstractClassConstructorTearOff: problemMessage: "Constructors on abstract classes can't be torn off." + experiments: constructor-tearoffs script: | abstract class Class {} main() => Class.new; @@ -6156,6 +6173,7 @@ AbstractClassConstructorTearOff: StaticTearOffFromInstantiatedClass: problemMessage: "Cannot access static member on an instantiated generic class." correctionMessage: "Try removing the type arguments or placing them after the member name." + experiments: constructor-tearoffs script: | class A { static f() {} } main() => A.f; @@ -6164,11 +6182,13 @@ StaticTearOffFromInstantiatedClass: ConstructorTearOffWithTypeArguments: problemMessage: "A constructor tear-off can't have type arguments after the constructor name." correctionMessage: "Try removing the type arguments or placing them after the class name." + experiments: constructor-tearoffs script: - "class C { C.foo(); } bar() { C.foo; }" NewAsSelector: problemMessage: "'new' can only be used as a constructor reference." + experiments: constructor-tearoffs script: | method(dynamic d) => d.new; @@ -6505,12 +6525,14 @@ ObjectMemberNameUsedForRecordField: RecordFieldsCantBePrivate: problemMessage: "Record field names can't be private." analyzerCode: INVALID_FIELD_NAME + experiments: records script: | foo() => (_bar: 1); NamedFieldClashesWithPositionalFieldInRecord: problemMessage: "Record field names can't be a dollar sign followed by an integer when integer is the index of a positional field." analyzerCode: INVALID_FIELD_NAME + experiments: records script: | foo() => (0, $1: 0); @@ -6528,6 +6550,7 @@ InheritedRestrictedMemberOfEnumImplementer: SealedClassSubtypeOutsideOfLibrary: problemMessage: "The class '#name' can't be extended, implemented, or mixed in outside of its library because it's a sealed class." analyzerCode: SEALED_CLASS_SUBTYPE_OUTSIDE_OF_LIBRARY + experiments: sealed-class script: main.dart: import 'lib.dart'; @@ -6538,6 +6561,7 @@ SealedClassSubtypeOutsideOfLibrary: CantUseClassAsMixin: problemMessage: "The class '#name' can't be used as a mixin because it isn't a mixin class nor a mixin." analyzerCode: CLASS_USED_AS_MIXIN + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6550,6 +6574,7 @@ BaseEnum: problemMessage: "Enums can't be declared to be 'base'." correctionMessage: "Try removing the keyword 'base'." analyzerCode: ParserErrorCode.BASE_ENUM + experiments: class-modifiers script: - "base enum E { v }" @@ -6558,6 +6583,7 @@ FinalEnum: problemMessage: "Enums can't be declared to be 'final'." correctionMessage: "Try removing the keyword 'final'." analyzerCode: ParserErrorCode.FINAL_ENUM + experiments: class-modifiers script: - "final enum E { v }" @@ -6566,6 +6592,7 @@ InterfaceEnum: problemMessage: "Enums can't be declared to be 'interface'." correctionMessage: "Try removing the keyword 'interface'." analyzerCode: ParserErrorCode.INTERFACE_ENUM + experiments: class-modifiers script: - "interface enum E { v }" @@ -6574,6 +6601,7 @@ SealedEnum: problemMessage: "Enums can't be declared to be 'sealed'." correctionMessage: "Try removing the keyword 'sealed'." analyzerCode: ParserErrorCode.SEALED_ENUM + experiments: class-modifiers,sealed-class script: - "sealed enum E { v }" @@ -6582,6 +6610,7 @@ FinalMixin: problemMessage: "A mixin can't be declared 'final'." correctionMessage: "Try removing the 'final' keyword." analyzerCode: ParserErrorCode.FINAL_MIXIN + experiments: class-modifiers script: - "final mixin M {}" @@ -6590,6 +6619,7 @@ InterfaceMixin: problemMessage: "A mixin can't be declared 'interface'." correctionMessage: "Try removing the 'interface' keyword." analyzerCode: ParserErrorCode.INTERFACE_MIXIN + experiments: class-modifiers script: - "interface mixin M {}" @@ -6598,6 +6628,7 @@ SealedMixin: problemMessage: "A mixin can't be declared 'sealed'." correctionMessage: "Try removing the 'sealed' keyword." analyzerCode: ParserErrorCode.SEALED_MIXIN + experiments: class-modifiers,sealed-class script: - "sealed mixin M {}" @@ -6606,6 +6637,7 @@ FinalMixinClass: problemMessage: "A mixin class can't be declared 'final'." correctionMessage: "Try removing the 'final' keyword." analyzerCode: ParserErrorCode.FINAL_MIXIN_CLASS + experiments: class-modifiers script: - "final mixin class C {}" @@ -6614,6 +6646,7 @@ InterfaceMixinClass: problemMessage: "A mixin class can't be declared 'interface'." correctionMessage: "Try removing the 'interface' keyword." analyzerCode: ParserErrorCode.INTERFACE_MIXIN_CLASS + experiments: class-modifiers script: - "interface mixin class C {}" @@ -6622,12 +6655,14 @@ SealedMixinClass: problemMessage: "A mixin class can't be declared 'sealed'." correctionMessage: "Try removing the 'sealed' keyword." analyzerCode: ParserErrorCode.SEALED_MIXIN_CLASS + experiments: class-modifiers,sealed-class script: - "sealed mixin class C {}" BaseClassImplementedOutsideOfLibrary: problemMessage: "The class '#name' can't be implemented outside of its library because it's a base class." analyzerCode: BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6642,6 +6677,7 @@ BaseOrFinalClassImplementedOutsideOfLibraryCause: BaseMixinImplementedOutsideOfLibrary: problemMessage: "The mixin '#name' can't be implemented outside of its library because it's a base mixin." analyzerCode: BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6652,6 +6688,7 @@ BaseMixinImplementedOutsideOfLibrary: InterfaceClassExtendedOutsideOfLibrary: problemMessage: "The class '#name' can't be extended outside of its library because it's an interface class." analyzerCode: INTERFACE_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6662,6 +6699,7 @@ InterfaceClassExtendedOutsideOfLibrary: FinalClassExtendedOutsideOfLibrary: problemMessage: "The class '#name' can't be extended outside of its library because it's a final class." analyzerCode: FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6672,6 +6710,7 @@ FinalClassExtendedOutsideOfLibrary: FinalClassImplementedOutsideOfLibrary: problemMessage: "The class '#name' can't be implemented outside of its library because it's a final class." analyzerCode: FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6682,6 +6721,7 @@ FinalClassImplementedOutsideOfLibrary: FinalClassUsedAsMixinConstraintOutsideOfLibrary: problemMessage: "The class '#name' can't be used as a mixin superclass constraint outside of its library because it's a final class." analyzerCode: FINAL_CLASS_USED_AS_MIXIN_CONSTRAINT_OUTSIDE_OF_LIBRARY + experiments: class-modifiers script: main.dart: import 'lib.dart'; @@ -6693,6 +6733,7 @@ SubtypeOfBaseIsNotBaseFinalOrSealed: problemMessage: "The type '#name' must be 'base', 'final' or 'sealed' because the supertype '#name2' is 'base'." correctionMessage: "Try adding 'base', 'final', or 'sealed' to the type." analyzerCode: SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED + experiments: class-modifiers,sealed-class script: | base class A {} class B extends A {} @@ -6701,6 +6742,7 @@ SubtypeOfFinalIsNotBaseFinalOrSealed: problemMessage: "The type '#name' must be 'base', 'final' or 'sealed' because the supertype '#name2' is 'final'." correctionMessage: "Try adding 'base', 'final', or 'sealed' to the type." analyzerCode: SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED + experiments: class-modifiers,sealed-class script: | final class A {} class B extends A {} @@ -6709,6 +6751,7 @@ MixinSubtypeOfBaseIsNotBase: problemMessage: "The mixin '#name' must be 'base' because the supertype '#name2' is 'base'." correctionMessage: "Try adding 'base' to the mixin." analyzerCode: MIXIN_SUBTYPE_OF_BASE_IS_NOT_BASE + experiments: class-modifiers,sealed-class script: | base class A {} mixin B implements A {} @@ -6717,12 +6760,14 @@ MixinSubtypeOfFinalIsNotBase: problemMessage: "The mixin '#name' must be 'base' because the supertype '#name2' is 'final'." correctionMessage: "Try adding 'base' to the mixin." analyzerCode: MIXIN_SUBTYPE_OF_FINAL_IS_NOT_BASE + experiments: class-modifiers,sealed-class script: | final class A {} mixin B implements A {} UnspecifiedGetterNameInObjectPattern: problemMessage: "The getter name is not specified explicitly, and the pattern is not a variable. Try specifying the getter name explicitly, or using a variable pattern." + experiments: patterns analyzerCode: MISSING_OBJECT_PATTERN_GETTER_NAME script: | abstract class A { int get foo;} @@ -6730,6 +6775,7 @@ UnspecifiedGetterNameInObjectPattern: JointPatternVariablesMismatch: problemMessage: "Variable pattern '#name' doesn't have the same type or finality in all cases." + experiments: patterns script: | test(dynamic x) { switch (x) { case [int a]: case [double a] : return a; default: return null; } } @@ -6737,6 +6783,7 @@ NonExhaustiveSwitchExpression: problemMessage: "The type '#type' is not exhaustively matched by the switch cases since it doesn't match '#string'." correctionMessage: "Try adding a wildcard pattern or cases that match '#string2'." analyzerCode: NON_EXHAUSTIVE_SWITCH_EXPRESSION + experiments: patterns script: | enum Enum { a, b } String method(Enum e) => switch (e) { @@ -6747,6 +6794,7 @@ NonExhaustiveSwitchStatement: problemMessage: "The type '#type' is not exhaustively matched by the switch cases since it doesn't match '#string'." correctionMessage: "Try adding a default case or cases that match '#string2'." analyzerCode: NON_EXHAUSTIVE_SWITCH_STATEMENT + experiments: patterns script: | enum Enum { a, b } method(Enum e) { @@ -6760,6 +6808,7 @@ UnreachableSwitchCase: problemMessage: "This case is covered by the previous cases." analyzerCode: UNREACHABLE_SWITCH_CASE severity: WARNING # TODO(johnniwinther): Should this be an error, warning or not emitted at all? + experiments: patterns script: | enum Enum { a, b } method(Enum e) { @@ -6777,6 +6826,7 @@ PatternTypeMismatchInIrrefutableContext: problemMessage: "The matched value of type '#type' isn't assignable to the required type '#type2'." correctionMessage: "Try changing the required type of the pattern, or the matched value type." analyzerCode: PATTERN_TYPE_MISMATCH_IN_IRREFUTABLE_CONTEXT + experiments: patterns script: | method(List list) { var [a] = list; @@ -6786,6 +6836,7 @@ DuplicatePatternAssignmentVariable: problemMessage: The variable '#name' is already assigned in this pattern. correctionMessage: Try renaming the variable. analyzerCode: DUPLICATE_PATTERN_ASSIGNMENT_VARIABLE + experiments: patterns script: | method(List list) { String a = ''; @@ -6800,6 +6851,7 @@ DuplicateRecordPatternField: problemMessage: The field '#name' is already matched in this pattern. correctionMessage: Try removing the duplicate field. analyzerCode: DUPLICATE_RECORD_PATTERN_FIELD + experiments: patterns script: | method(o) { switch (o) { @@ -6815,6 +6867,7 @@ DuplicateRestElementInPattern: problemMessage: At most one rest element is allowed in a list or map pattern. correctionMessage: Try removing the duplicate rest element. analyzerCode: DUPLICATE_REST_ELEMENT_IN_PATTERN + experiments: patterns script: | method(o) { switch (o) { @@ -6828,6 +6881,7 @@ DuplicateRestElementInPatternContext: RestPatternInMapPattern: problemMessage: "The '...' pattern can't appear in map patterns." + experiments: patterns script: | test(dynamic x) { if (x case {1: 1, ...}) {} } @@ -6836,6 +6890,7 @@ UnnecessaryNullAssertPattern: correctionMessage: Try replacing the null-assert pattern with its nested pattern. analyzerCode: UNNECESSARY_NULL_ASSERT_PATTERN severity: WARNING + experiments: patterns script: | method(List list) { if (list case [var a!]) {} @@ -6847,6 +6902,7 @@ UnnecessaryNullCheckPattern: analyzerCode: UNNECESSARY_NULL_CHECK_PATTERN comment: No parameters. severity: WARNING + experiments: patterns script: | method(List list) { if (list case [var a?]) {} @@ -6856,6 +6912,7 @@ NonBoolCondition: problemMessage: "Conditions must have a static type of 'bool'." correctionMessage: Try changing the condition. analyzerCode: NON_BOOL_CONDITION + experiments: patterns script: | method(int i) { if (i case 5 when i) {} @@ -6865,6 +6922,7 @@ RefutablePatternInIrrefutableContext: problemMessage: Refutable patterns can't be used in an irrefutable context. correctionMessage: Try using an if-case, a 'switch' statement, or a 'switch' expression instead. analyzerCode: REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT + experiments: patterns script: | method(int? x) { var (a?) = x; @@ -6874,6 +6932,7 @@ MissingVariablePattern: problemMessage: "Variable pattern '#name' is missing in this branch of the logical-or pattern." correctionMessage: "Try declaring this variable pattern in the branch." analyzerCode: MISSING_VARIABLE_PATTERN + experiments: patterns script: | method(x) { if (x case [var a] || _) {} @@ -6882,6 +6941,7 @@ MissingVariablePattern: MapPatternTypeArgumentMismatch: problemMessage: "A map pattern requires exactly two type arguments." analyzerCode: EXPECTED_TWO_MAP_PATTERN_TYPE_ARGUMENTS + experiments: patterns script: | method(x) { if (x case {0: 0}) {} @@ -6890,6 +6950,7 @@ MapPatternTypeArgumentMismatch: ListPatternTooManyTypeArguments: problemMessage: "A list pattern requires exactly one type argument." analyzerCode: EXPECTED_ONE_LIST_PATTERN_TYPE_ARGUMENTS + experiments: patterns script: | method(x) { if (x case []) {} @@ -6898,6 +6959,7 @@ ListPatternTooManyTypeArguments: UnnamedObjectPatternField: problemMessage: "A pattern field in an object pattern must be named." correctionMessage: "Try adding a pattern name or ':' before the pattern." + experiments: patterns script: | method(x) { if (x case int(5)) {} @@ -6906,6 +6968,7 @@ UnnamedObjectPatternField: InvalidConstantPatternNegation: problemMessage: "Only negation of a numeric literal is supported as a constant pattern." correctionMessage: "Try wrapping the expression in 'const ( ... )'." + experiments: patterns analyzerCode: ParserErrorCode.INVALID_CONSTANT_PATTERN_NEGATION index: 135 script: | @@ -6917,6 +6980,7 @@ InvalidConstantPatternNegation: InvalidConstantPatternUnary: problemMessage: "The unary operator #name is not supported as a constant pattern." correctionMessage: "Try wrapping the expression in 'const ( ... )'." + experiments: patterns analyzerCode: ParserErrorCode.INVALID_CONSTANT_PATTERN_UNARY index: 136 script: | @@ -6930,6 +6994,7 @@ InvalidConstantPatternDuplicateConst: correctionMessage: "Try removing one of the 'const' keywords." analyzerCode: ParserErrorCode.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST index: 137 + experiments: patterns script: | method(x) { if (x case const const []) {} @@ -6939,6 +7004,7 @@ InvalidConstantPatternEmptyRecordLiteral: problemMessage: "The empty record literal is not supported as a constant pattern." analyzerCode: ParserErrorCode.INVALID_CONSTANT_PATTERN_EMPTY_RECORD_LITERAL index: 138 + experiments: patterns,records script: | method(x) { if (x case const ()) {} @@ -6949,6 +7015,7 @@ InvalidConstantPatternGeneric: correctionMessage: "Try wrapping the expression in 'const ( ... )'." analyzerCode: ParserErrorCode.INVALID_CONSTANT_PATTERN_GENERIC index: 139 + experiments: patterns script: | method(x) { if (x case List) {} @@ -6959,6 +7026,7 @@ InvalidConstantPatternConstPrefix: correctionMessage: "Try wrapping the expression in 'const ( ... )' instead." analyzerCode: ParserErrorCode.INVALID_CONSTANT_CONST_PREFIX index: 140 + experiments: patterns script: | method(x) { if (x case const 1) {} @@ -6969,6 +7037,7 @@ InvalidConstantPatternBinary: correctionMessage: "Try wrapping the expression in 'const ( ... )'." analyzerCode: ParserErrorCode.INVALID_CONSTANT_PATTERN_BINARY index: 141 + experiments: patterns script: | method(x) { if (x case 1 + 2) {} @@ -6979,6 +7048,7 @@ PatternAssignmentDeclaresVariable: correctionMessage: "Try using a preexisting variable or changing the assignment to a pattern variable declaration." analyzerCode: ParserErrorCode.PATTERN_ASSIGNMENT_DECLARES_VARIABLE index: 145 + experiments: patterns script: | method(x) { var y; @@ -6989,6 +7059,7 @@ PatternAssignmentNotLocalVariable: problemMessage: Only local variables or formal parameters can be used in pattern assignments. correctionMessage: Try assigning to a local variable. analyzerCode: PATTERN_ASSIGNMENT_NOT_LOCAL_VARIABLE + experiments: patterns script: | var global; method(x) { @@ -7000,6 +7071,7 @@ VariablePatternKeywordInDeclarationContext: correctionMessage: Try removing the keyword. analyzerCode: ParserErrorCode.VARIABLE_PATTERN_KEYWORD_IN_DECLARATION_CONTEXT index: 149 + experiments: patterns comment: No parameters. hasPublishedDocs: true script: | @@ -7041,6 +7113,7 @@ IllegalPatternVariableName: correctionMessage: Choose a different name. analyzerCode: ParserErrorCode.ILLEGAL_PATTERN_VARIABLE_NAME index: 159 + experiments: patterns comment: |- Parameters: 0: the illegal name @@ -7056,6 +7129,7 @@ IllegalPatternAssignmentVariableName: correctionMessage: Choose a different name. analyzerCode: ParserErrorCode.ILLEGAL_PATTERN_ASSIGNMENT_VARIABLE_NAME index: 160 + experiments: patterns comment: |- Parameters: 0: the illegal name @@ -7070,6 +7144,7 @@ IllegalPatternIdentifierName: correctionMessage: Match the identifier using '== #lexeme'. analyzerCode: ParserErrorCode.ILLEGAL_PATTERN_IDENTIFIER_NAME index: 161 + experiments: patterns comment: |- Parameters: 0: the illegal name @@ -7086,6 +7161,7 @@ InvalidInsideUnaryPattern: correctionMessage: Try combining into a single pattern if possible, or enclose the inner pattern in parentheses. analyzerCode: ParserErrorCode.INVALID_INSIDE_UNARY_PATTERN index: 150 + experiments: patterns comment: No parameters. script: | void f(x) { @@ -7097,6 +7173,7 @@ LatePatternVariableDeclaration: correctionMessage: Try removing the keyword `late`. analyzerCode: ParserErrorCode.LATE_PATTERN_VARIABLE_DECLARATION index: 151 + experiments: patterns comment: No parameters. script: | void f(x) { @@ -7108,6 +7185,7 @@ PatternVariableDeclarationOutsideFunctionOrMethod: correctionMessage: Try declaring ordinary variables and assigning from within a function or method. analyzerCode: ParserErrorCode.PATTERN_VARIABLE_DECLARATION_OUTSIDE_FUNCTION_OR_METHOD index: 152 + experiments: patterns comment: No parameters. script: | class C { @@ -7119,6 +7197,7 @@ DefaultInSwitchExpression: correctionMessage: Try replacing `default` with `_`. analyzerCode: ParserErrorCode.DEFAULT_IN_SWITCH_EXPRESSION index: 153 + experiments: patterns comment: No parameters. script: | void f(x) => switch (x) { diff --git a/pkg/front_end/testcases/class_modifiers/folder.options b/pkg/front_end/testcases/class_modifiers/folder.options index e69de29bb2d..4e33e756e1a 100644 --- a/pkg/front_end/testcases/class_modifiers/folder.options +++ b/pkg/front_end/testcases/class_modifiers/folder.options @@ -0,0 +1 @@ +--enable-experiment=class-modifiers,sealed-class diff --git a/pkg/front_end/testcases/patterns/folder.options b/pkg/front_end/testcases/patterns/folder.options index e69de29bb2d..3a75a8339e7 100644 --- a/pkg/front_end/testcases/patterns/folder.options +++ b/pkg/front_end/testcases/patterns/folder.options @@ -0,0 +1 @@ +--enable-experiment=patterns diff --git a/pkg/front_end/testcases/patterns/records/folder.options b/pkg/front_end/testcases/patterns/records/folder.options index e69de29bb2d..73400e0fb41 100644 --- a/pkg/front_end/testcases/patterns/records/folder.options +++ b/pkg/front_end/testcases/patterns/records/folder.options @@ -0,0 +1,2 @@ +--enable-experiment=patterns +--enable-experiment=records diff --git a/pkg/front_end/testcases/records/folder.options b/pkg/front_end/testcases/records/folder.options index e69de29bb2d..cc13ec14b25 100644 --- a/pkg/front_end/testcases/records/folder.options +++ b/pkg/front_end/testcases/records/folder.options @@ -0,0 +1 @@ +--enable-experiment=records diff --git a/pkg/front_end/testcases/sealed_class/folder.options b/pkg/front_end/testcases/sealed_class/folder.options index e69de29bb2d..ffdc790bace 100644 --- a/pkg/front_end/testcases/sealed_class/folder.options +++ b/pkg/front_end/testcases/sealed_class/folder.options @@ -0,0 +1 @@ +--enable-experiment=sealed-class,class-modifiers \ No newline at end of file diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart index d12ddaa7e52..9e8d8181e4f 100644 --- a/pkg/test_runner/lib/src/test_suite.dart +++ b/pkg/test_runner/lib/src/test_suite.dart @@ -333,7 +333,8 @@ class VMTestSuite extends TestSuite { ? '$buildDir/gen/kernel-service.dart.snapshot' : '$buildDir/gen/kernel_service.dill'; var dfePath = Path(filename).absolute.toNativePath(); - final experiments = [...configuration.experiments]; + // Enable 'records' experiment as it is used by certain vm/cc unit tests. + final experiments = [...configuration.experiments, 'records']; var args = [ ...initialTargetArguments, // '--dfe' must be the first VM argument for run_vm_test to pick it up. diff --git a/pkg/vm/test/transformations/ffi_test.dart b/pkg/vm/test/transformations/ffi_test.dart index 78af86b5931..d6b0c3e1951 100644 --- a/pkg/vm/test/transformations/ffi_test.dart +++ b/pkg/vm/test/transformations/ffi_test.dart @@ -30,7 +30,7 @@ runTestCaseJit(Uri source) async { final target = VmTarget(TargetFlags()); Component component = await compileTestCaseToKernelProgram(source, - target: target, experimentalFlags: []); + target: target, experimentalFlags: ['class-modifiers']); final coreTypes = CoreTypes(component); @@ -54,7 +54,7 @@ runTestCaseAot(Uri source) async { final target = VmTarget(TargetFlags(supportMirrors: false)); Component component = await compileTestCaseToKernelProgram(source, - target: target, experimentalFlags: []); + target: target, experimentalFlags: ['class-modifiers']); const bool useGlobalTypeFlowAnalysis = true; const bool enableAsserts = false; diff --git a/pkg/vm_service/test/patterns_local_vars_test.dart b/pkg/vm_service/test/patterns_local_vars_test.dart index 6d9e8910ac4..63c0b8814cf 100644 --- a/pkg/vm_service/test/patterns_local_vars_test.dart +++ b/pkg/vm_service/test/patterns_local_vars_test.dart @@ -2,6 +2,7 @@ // 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. +// VMOptions=--enable-experiment=patterns // @dart=3.0 // ignore_for_file: experiment_not_enabled diff --git a/runtime/tests/vm/dart/records_allocation_sinking_il_test.dart b/runtime/tests/vm/dart/records_allocation_sinking_il_test.dart index 45a37d1b4e3..0ff310adc89 100644 --- a/runtime/tests/vm/dart/records_allocation_sinking_il_test.dart +++ b/runtime/tests/vm/dart/records_allocation_sinking_il_test.dart @@ -4,6 +4,8 @@ // Verifies that compiler can eliminate record allocation. +// SharedOptions=--enable-experiment=records + import 'package:vm/testing/il_matchers.dart'; @pragma('vm:prefer-inline') diff --git a/runtime/tests/vm/dart/records_field_operations_il_test.dart b/runtime/tests/vm/dart/records_field_operations_il_test.dart index 44e2db35819..dd4369b0b2b 100644 --- a/runtime/tests/vm/dart/records_field_operations_il_test.dart +++ b/runtime/tests/vm/dart/records_field_operations_il_test.dart @@ -5,6 +5,8 @@ // Verifies that compiler can propagate static types through record fields // and recognize int/double operations on record fields. +// SharedOptions=--enable-experiment=records,patterns + import 'package:vm/testing/il_matchers.dart'; double d(int x) => x + double.parse('1.0'); diff --git a/runtime/tests/vm/dart/records_return_value_unboxing_il_test.dart b/runtime/tests/vm/dart/records_return_value_unboxing_il_test.dart index 3457fd372dd..56d1216b360 100644 --- a/runtime/tests/vm/dart/records_return_value_unboxing_il_test.dart +++ b/runtime/tests/vm/dart/records_return_value_unboxing_il_test.dart @@ -4,6 +4,8 @@ // Verifies that compiler can unbox records in return values. +// SharedOptions=--enable-experiment=records + import 'package:vm/testing/il_matchers.dart'; @pragma('vm:never-inline') diff --git a/runtime/tests/vm/dart/regress_51091_test.dart b/runtime/tests/vm/dart/regress_51091_test.dart index 18ca2140210..92bfb86ac30 100644 --- a/runtime/tests/vm/dart/regress_51091_test.dart +++ b/runtime/tests/vm/dart/regress_51091_test.dart @@ -6,6 +6,7 @@ // Verifies that compiler doesn't crash if there are two local // variables with the same name in the same local scope. +// SharedOptions=--enable-experiment=patterns import 'package:expect/expect.dart'; diff --git a/tests/ffi/vmspecific_static_checks_varargs_test.dart b/tests/ffi/vmspecific_static_checks_varargs_test.dart index e093698e43c..967f1e2d74a 100644 --- a/tests/ffi/vmspecific_static_checks_varargs_test.dart +++ b/tests/ffi/vmspecific_static_checks_varargs_test.dart @@ -4,6 +4,7 @@ // SharedObjects=ffi_test_functions +// VMOptions=--enable-experiment=records import 'dylib_utils.dart'; diff --git a/tests/language_2/record_literal_problems_test.dart b/tests/language_2/record_literal_problems_test.dart new file mode 100644 index 00000000000..5c4b825bb20 --- /dev/null +++ b/tests/language_2/record_literal_problems_test.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2022, 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 = 2.9 + +main() { + var r1 = const (42); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + // ^ + // [analyzer] SYNTACTIC_ERROR.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA + // [cfe] A record literal with exactly one positional field requires a trailing comma. + + var r2 = const (); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. +} diff --git a/tests/language_2/record_literal_test.dart b/tests/language_2/record_literal_test.dart new file mode 100644 index 00000000000..0d6410c44d2 --- /dev/null +++ b/tests/language_2/record_literal_test.dart @@ -0,0 +1,61 @@ +// Copyright (c) 2022, 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 = 2.9 + +main() { + var record1 = (1, 2, a: 3, b: 4); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record1); + + // With ending comma. + var record2 = (42, 42, 42, ); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record2); + var record3 = (foo: 42, bar: 42, 42, baz: 42, ); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record3); + + // Nested. + var record4 = ((42, 42), 42); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record4); + + // With function inside. + var record5 = ((foo, bar) => 42, 42); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record5); + + // 1 record entry with trailing comma. + var record6 = (42, ); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record6); + + // Const records. + var record7 = const (42, ); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record7); + var record8 = const (42, foo: "bar"); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + print(record8); +} diff --git a/tests/language_2/record_type_problems_test.dart b/tests/language_2/record_type_problems_test.dart new file mode 100644 index 00000000000..f21a2446d0e --- /dev/null +++ b/tests/language_2/record_type_problems_test.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2022, 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 = 2.9 + +main() { + (int, int, {/*missing*/}) r1 = (1, 2); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EMPTY_RECORD_TYPE_NAMED_FIELDS_LIST +// [cfe] The list of named fields in a record type can't be empty. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + + (int /* missing trailing comma */ ) r2 = (1, ); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA +// [cfe] A record type with exactly one positional field requires a trailing comma. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + + () emptyRecord = (); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(emptyRecord); +} diff --git a/tests/language_2/record_type_test.dart b/tests/language_2/record_type_test.dart new file mode 100644 index 00000000000..e0a3c3fdd64 --- /dev/null +++ b/tests/language_2/record_type_test.dart @@ -0,0 +1,222 @@ +// Copyright (c) 2022, 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 = 2.9 + +main() { + (int, int) record1 = (1, 2); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record1); + (int x, int y) record1Named = (1, 2); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record1Named); + + (int, int, ) record2 = (1, 2); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record2); + + (int x, int y, ) record2Named = (1, 2); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record2Named); + + (int, int, {int a, int b}) record3 = (1, 2, a: 3, b: 4); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record3); + + (int x, int y, {int a, int b}) record3Named = (1, 2, a: 3, b: 4); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record3Named); + + (int, int, {int a, int b, }) record4 = (1, 2, a: 3, b: 4); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record4); + + (int x, int y, {int a, int b, }) record4Named = (1, 2, a: 3, b: 4); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(record4Named); + + print(foo((42, b: true), 42)); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + + Bar b = new Bar(); + print(b.foo(42)); + (int, int) Function ((int, int) a) z1 = ((int, int) a) { return (42, 42); }; +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + + final (int x, int y) finalRecordType = (42, 42); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] This requires the experimental 'records' language feature to be enabled. + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + + List<(int, int)> listOfRecords = []; + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] This requires the experimental 'records' language feature to be enabled. + + var listOfRecords2 = <(int, int)>[]; + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] This requires the experimental 'records' language feature to be enabled. + + (int, ) oneElementRecord = (1, ); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(oneElementRecord); + + ({int ok}) oneElementNamedRecord = (ok: 1); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + print(oneElementNamedRecord); +} + +(int, T) f1(T t) { +// [error column 1, length 1] +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. + return (42, t); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. +} + +(int, T) f2(T t) => (42, t); +// [error column 1, length 1] +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + +(int a, String b) get topLevelGetterType => throw ''; +// [error column 1, length 1] +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. + +(int, int) foo((int, {bool b}) inputRecord, int x) { +// [error column 1, length 1] +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. + if (inputRecord.b) return (42, 42); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + return (1, 1, ); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. +} + +class Bar { + (int, int) foo(int x) => (42, 42); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. + + static (int x, int y) staticRecordType = (42, 42); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] This requires the experimental 'records' language feature to be enabled. + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + + (int a, String b) get instanceGetterType => throw ''; +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. + + static (int a, String b) get staticGetterType => throw ''; +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. + + (int, T) f1(T t) { +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. + return (42, t); + // ^ + // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED + // [cfe] The 'records' language feature is disabled for this library. + } + + (int, T) f2(T t) => (42, t); +//^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] This requires the experimental 'records' language feature to be enabled. +// ^ +// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED +// [cfe] The 'records' language feature is disabled for this library. +} + diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml index a9e7b248e47..3d46206fd9e 100644 --- a/tools/experimental_features.yaml +++ b/tools/experimental_features.yaml @@ -161,7 +161,6 @@ features: void main() { print('feature enabled'); } - expired: true class-modifiers: help: "Class modifiers" @@ -171,7 +170,6 @@ features: void main() { print('feature enabled'); } - expired: true records: help: "Records" @@ -181,7 +179,6 @@ features: void main() { print('${x.$1} ${x.a}'); } - expired: true patterns: help: "Patterns" @@ -191,15 +188,14 @@ features: final [a, b] = ['feature', 'enabled']; print('$a $b'); } - expired: true unnamed-libraries: help: "Unnamed libraries" enabledIn: '2.19.0' + expired: true validation: | library; void main() => print('feature enabled'); - expired: true alternative-invalidation-strategy: help: "Alternative invalidation strategy for incremental compilation." @@ -210,6 +206,7 @@ features: inference-update-1: help: "Horizontal type inference for function expressions passed to generic invocations." enabledIn: '2.18.0' + expired: true validation: | void test(List list) { var a = list.fold(0, (x, y) => x + y); @@ -223,7 +220,6 @@ features: void main() { test([1, 2, 3]); } - expired: true enhanced-enums: help: "Enhanced Enums"