From 386825ee8c24ef262dfbaff4481a77136bc9c3bd Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Fri, 24 Mar 2023 21:59:23 +0000 Subject: [PATCH] Add tests for the transitivity of the base modifier when applied to base mixins and base mixin classes. Change-Id: Idfe7576f38382c5e9a0ff968aae00f48990e1d38 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/290351 Commit-Queue: Leaf Petersen Reviewed-by: Erik Ernst --- .../base_class_different_library_test.dart | 10 +- .../base_class_same_library_test.dart | 8 +- ...in_class_different_library_error_test.dart | 426 ++++++++++++++++++ ...se_mixin_class_different_library_test.dart | 97 ++++ ...e_mixin_class_same_library_error_test.dart | 304 +++++++++++++ .../base_mixin_class_same_library_test.dart | 201 +++++++++ ...se_mixin_different_library_error_test.dart | 317 +++++++++++++ .../base_mixin_different_library_test.dart | 62 +++ .../base_mixin_same_library_error_test.dart | 223 +++++++++ .../base_mixin_same_library_test.dart | 156 +++++++ ...al_class_different_library_error_test.dart | 12 +- .../final_class_same_library_test.dart | 8 +- ...nterface_class_different_library_test.dart | 8 +- .../interface_class_same_library_test.dart | 8 +- .../sealed_class_same_library_test.dart | 8 +- 15 files changed, 1841 insertions(+), 7 deletions(-) create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_error_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_error_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_different_library_error_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_different_library_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_same_library_error_test.dart create mode 100644 tests/language/class_modifiers/base_transitivity/base_mixin_same_library_test.dart diff --git a/tests/language/class_modifiers/base_transitivity/base_class_different_library_test.dart b/tests/language/class_modifiers/base_transitivity/base_class_different_library_test.dart index 53b1d4ae336..bd39d97e7b4 100644 --- a/tests/language/class_modifiers/base_transitivity/base_class_different_library_test.dart +++ b/tests/language/class_modifiers/base_transitivity/base_class_different_library_test.dart @@ -41,11 +41,19 @@ sealed class SealedExtendWith extends BaseClass with _MixinOnObject {} // Extending via an anonymous mixin application class. final class FinalExtendApplication = BaseClass with _MixinOnObject; + base class BaseExtendApplication = BaseClass with _MixinOnObject; + sealed class SealedExtendApplication = BaseClass with _MixinOnObject; /// BaseClass can be an `on` type, so long as the subtype is base. base mixin BaseMixinOn on BaseClass {} -main() {} +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/base_class_same_library_test.dart b/tests/language/class_modifiers/base_transitivity/base_class_same_library_test.dart index ec6b23ec9c6..6381a671f51 100644 --- a/tests/language/class_modifiers/base_transitivity/base_class_same_library_test.dart +++ b/tests/language/class_modifiers/base_transitivity/base_class_same_library_test.dart @@ -119,4 +119,10 @@ sealed class SealedMixinImplementApplied extends Object base mixin BaseMixinOn on BaseClass {} -main() {} +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_error_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_error_test.dart new file mode 100644 index 00000000000..e55dd39290e --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_error_test.dart @@ -0,0 +1,426 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the invalid uses of a base mixin class defined in a different library. + +import "shared_library_definitions.dart" show SimpleClass, BaseMixinClass; + +mixin _MixinOnObject {} + +/// It is an error if BaseMixinClass is extended by something which is not base, +/// final or sealed. + +// Simple extension. +class SimpleExtend extends BaseMixinClass {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceExtend extends BaseMixinClass {} +// ^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Extending with a sealed class (valid, used to check the errors below). +sealed class SealedExtend extends BaseMixinClass {} + +// Extending through a sealed class. +class SimpleSealedExtendExtend extends SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedExtendExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceSealedExtendExtend extends SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedExtendExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing through a sealed class. +class SimpleSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base class BaseSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +interface class InterfaceSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +final class FinalSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +sealed class SealedSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +mixin class MixinClassSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin class BaseMixinClassSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +mixin MixinSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin BaseMixinSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +// Using a sealed class as an `on` type + +mixin MixinSealedExtendOn on SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'MixinSealedExtendOn' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Extending via an anonymous mixin class. +class SimpleExtendWith extends BaseMixinClass with _MixinOnObject {} +// ^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleExtendWith' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceExtendWith extends BaseMixinClass +// ^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceExtendWith' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject {} + +// Extending via an anonymous mixin application class. +class SimpleExtendApplication = BaseMixinClass with _MixinOnObject; +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleExtendApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceExtendApplication = BaseMixinClass with _MixinOnObject; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceExtendApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +/// It is an error if BaseMixinClass is implemented by something which is not base, +/// final or sealed. + +// Simple implementation. +class SimpleImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base class BaseImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +interface class InterfaceImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +final class FinalImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +sealed class SealedImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +// Implementing with a mixin class. +mixin class SimpleMixinClassImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin class BaseMixinClassImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +// Implementing with a mixin application class. +class SimpleImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject + implements + BaseMixinClass; +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base class BaseImplementApplication = Object + with _MixinOnObject + implements BaseMixinClass; +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +interface class InterfaceImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject + implements + BaseMixinClass; +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +final class FinalImplementApplication = Object + with _MixinOnObject + implements BaseMixinClass; +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +sealed class SealedImplementApplication = Object + with _MixinOnObject + implements BaseMixinClass; +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +// Implementing with a mixin. +mixin SimpleMixinImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin BaseMixinImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +/// It is an error if BaseMixinClass is the `on` type of something which is not base. + +mixin SimpleMixinOn on BaseMixinClass {} +// ^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOn' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +mixin SimpleMixinOnSimpleBase on SimpleClass, BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +mixin SimpleMixinOnBaseSimple on BaseMixinClass, SimpleClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +/// It is an error to use BaseMixinClass as a mixin, if the result is not base, +/// final or sealed. + +class SimpleMixinClassApply extends Object with BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +class SimpleMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +class SimpleMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +interface class InterfaceMixinClassApply extends Object with BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +interface class InterfaceMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +// Sealed class from mixing in a base mixin class. (valid, used for tests +// below) +sealed class SealedMixinClassApply extends Object with BaseMixinClass {} + +// Implementing through a sealed class. +class SimpleSealedMixinClassApplyImplement implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base class BaseSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +interface class InterfaceSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +final class FinalSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +sealed class SealedSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin class BaseMixinClassSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin BaseMixinSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +/// It is an error to use BaseMixinClass as a mixin application, if the result +/// is not base, final or sealed. + +class SimpleMixinClassApplication extends Object with BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +class SimpleMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +class SimpleMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +interface class InterfaceMixinClassApplication extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass {} + +interface class InterfaceMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +interface class InterfaceMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +// Sealed class from mixing in a base mixin class. (valid, used for tests +// below) +sealed class SealedMixinApplication = Object with BaseMixinClass; + +// Implementing through a sealed class. +class SimpleSealedMixinApplicationImplement implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base class BaseSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +interface class InterfaceSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +final class FinalSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +sealed class SealedSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin class BaseMixinClassSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. + +base mixin BaseMixinSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixinClass' can't be implemented outside of its library because it's a base class. diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_test.dart new file mode 100644 index 00000000000..2e884b7667f --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_class_different_library_test.dart @@ -0,0 +1,97 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the valid uses of a base mixin class defined in a different library + +import "shared_library_definitions.dart" show BaseMixinClass; + +mixin _MixinOnObject {} + +/// BaseMixinClass can be extended, so long as the subtype is base, final +/// or sealed. + +// Simple extension. +base class BaseExtend extends BaseMixinClass {} + +final class FinalExtend extends BaseMixinClass {} + +// Extending with a sealed class. +sealed class SealedExtend extends BaseMixinClass {} + +// Extending through a sealed class. +base class BaseSealedExtendExtend extends SealedExtend {} + +final class FinalSealedExtendExtend extends SealedExtend {} + +sealed class SealedSealedExtendExtend extends SealedExtend {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedExtendOn on SealedExtend {} + +// Extending via an anonymous mixin class. +base class BaseExtendWith extends BaseMixinClass with _MixinOnObject {} + +final class FinalExtendWith extends BaseMixinClass with _MixinOnObject {} + +sealed class SealedExtendWith extends BaseMixinClass with _MixinOnObject {} + +// Extending via an anonymous mixin application class. +final class FinalExtendApplication = BaseMixinClass with _MixinOnObject; +base class BaseExtendApplication = BaseMixinClass with _MixinOnObject; +sealed class SealedExtendApplication = BaseMixinClass with _MixinOnObject; + +/// BaseMixinClass can be an `on` type, so long as the subtype is base. + +base mixin BaseMixinOn on BaseMixinClass {} + +/// BaseMixinClass can be used as a mixin, so long as the result is base, final, +/// or sealed. + +base class BaseMixinClassApply extends Object with BaseMixinClass {} + +final class FinalMixinClassApply extends Object with BaseMixinClass {} + +sealed class SealedMixinClassApply extends Object with BaseMixinClass {} + +// Extending through a sealed class. +base class BaseSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +final class FinalSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +sealed class SealedSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplyOn on SealedMixinClassApply {} + +/// BaseMixinClass can be used as a mixin application, so long as the result is +/// base, final, or sealed. + +base class BaseMixinApplication = Object with BaseMixinClass; + +final class FinalMixinApplication = Object with BaseMixinClass; + +sealed class SealedMixinApplication = Object with BaseMixinClass; + +// Extending through a sealed class. +base class BaseSealedMixinApplicationExtend extends SealedMixinApplication {} + +final class FinalSealedMixinApplicationExtend extends SealedMixinApplication {} + +sealed class SealedSealedMixinApplicationExtend + extends SealedMixinApplication {} + +// Using a sealed class as an `on` type +base mixin BaseMixinSealedMixinApplicationOn on SealedMixinApplication {} + +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_error_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_error_test.dart new file mode 100644 index 00000000000..8fc41f54676 --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_error_test.dart @@ -0,0 +1,304 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the invalid uses of a base mixin class within the same library + +class SimpleClass {} + +base mixin class BaseMixinClass {} + +mixin _MixinOnObject {} + +/// It is an error if BaseMixinClass is extended by something which is not base, +/// final or sealed. + +// Simple extension. +class SimpleExtend extends BaseMixinClass {} +// ^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceExtend extends BaseMixinClass {} +// ^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Extending with a sealed class (valid, used to check the errors below). +sealed class SealedExtend extends BaseMixinClass {} + +// Extending through a sealed class. +class SimpleSealedExtendExtend extends SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedExtendExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceSealedExtendExtend extends SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedExtendExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing through a sealed class. +class SimpleSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedExtendImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedExtendImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +mixin class MixinClassSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'MixinClassSealedExtendImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +mixin MixinSealedExtendImplement implements SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'MixinSealedExtendImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Using a sealed class as an `on` type +mixin MixinSealedExtendOn on SealedExtend {} +// ^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'MixinSealedExtendOn' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Extending via an anonymous mixin class. +class SimpleExtendWith extends BaseMixinClass with _MixinOnObject {} +// ^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleExtendWith' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceExtendWith extends BaseMixinClass +// ^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceExtendWith' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject {} + +// Extending via an anonymous mixin application class. +class SimpleExtendApplication = BaseMixinClass with _MixinOnObject; +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleExtendApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceExtendApplication = BaseMixinClass with _MixinOnObject; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceExtendApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +/// It is an error if BaseMixinClass is implemented by something which is not base, +/// final or sealed. + +// Simple implementation. +class SimpleImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing with a sealed class (valid, used for tests below). +sealed class SealedImplement implements BaseMixinClass {} + +// Extending through a sealed class. +class SimpleSealedImplementExtend extends SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedImplementExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceSealedImplementExtend extends SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedImplementExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing through a sealed class. +class SimpleSealedImplementImplement implements SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedImplementImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceSealedImplementImplement implements SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedImplementImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing with a mixin class. +mixin class SimpleMixinClassImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing with a base mixin class (valid, used for tests below) +base mixin class BaseMixinClassImplement implements BaseMixinClass {} + +// Implementing by applying a mixin class. +class SimpleMixinClassImplementApplied extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClassImplement' is 'base'. + with + BaseMixinClassImplement {} + +interface class InterfaceMixinClassImplementApplied extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClassImplement' is 'base'. + with + BaseMixinClassImplement {} + +// Implementing with a mixin application class. +interface class InterfaceImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject + implements + BaseMixinClass; +class SimpleImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject + implements + BaseMixinClass; + +// Implementing with a mixin. +mixin SimpleMixinImplement implements BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +// Implementing with a base mixin (valid, used for tests below) +base mixin BaseMixinImplement implements BaseMixinClass {} + +// Implementing by applying a mixin. +class SimpleMixinImplementApplied extends Object with BaseMixinImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinImplement' is 'base'. + +interface class InterfaceMixinImplementApplied extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinImplement' is 'base'. + with + BaseMixinImplement {} + +/// It is an error if BaseMixinClass is the `on` type of something which is not base. + +mixin SimpleMixinOn on BaseMixinClass {} +// ^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOn' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +mixin SimpleMixinOnBaseSimple on BaseMixinClass, SimpleClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +mixin SimpleMixinOnSimpleBase on SimpleClass, BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +/// It is an error to use BaseMixinClass as a mixin, if the result is not base, +/// final or sealed. + +class SimpleMixinClassApply extends Object with BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +class SimpleMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +class SimpleMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +interface class InterfaceMixinClassApply extends Object with BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +interface class InterfaceMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +interface class InterfaceMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +/// It is an error to use BaseMixinClass as a mixin application, if the result +/// is not base, final or sealed. + +class SimpleMixinClassApplication extends Object with BaseMixinClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + +class SimpleMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +class SimpleMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} + +interface class InterfaceMixinClassApplication extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass {} + +interface class InterfaceMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + _MixinOnObject, + BaseMixinClass {} + +interface class InterfaceMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClass' is 'base'. + with + BaseMixinClass, + _MixinOnObject {} diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_test.dart new file mode 100644 index 00000000000..ba43a3bbaf6 --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_class_same_library_test.dart @@ -0,0 +1,201 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the valid uses of a base mixin class within the same library + +base mixin class BaseMixinClass {} + +mixin _MixinOnObject {} + +/// BaseMixinClass can be extended, so long as the subtype is base, final +/// or sealed. + +// Simple extension. +base class BaseExtend extends BaseMixinClass {} + +final class FinalExtend extends BaseMixinClass {} + +// Extending with a sealed class. +sealed class SealedExtend extends BaseMixinClass {} + +// Extending through a sealed class. +base class BaseSealedExtendExtend extends SealedExtend {} + +final class FinalSealedExtendExtend extends SealedExtend {} + +sealed class SealedSealedExtendExtend extends SealedExtend {} + +// Implementing through a sealed class. +base class BaseSealedExtendImplement implements SealedExtend {} + +final class FinalSealedExtendImplement implements SealedExtend {} + +sealed class SealedSealedExtendImplement implements SealedExtend {} + +base mixin class BaseMixinClassSealedExtendImplement implements SealedExtend {} + +base mixin BaseMixinSealedExtendImplement implements SealedExtend {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedExtendOn on SealedExtend {} + +// Extending via an anonymous mixin class. +base class BaseExtendWith extends BaseMixinClass with _MixinOnObject {} + +final class FinalExtendWith extends BaseMixinClass with _MixinOnObject {} + +sealed class SealedExtendWith extends BaseMixinClass with _MixinOnObject {} + +// Extending via an anonymous mixin application class. +final class FinalExtendApplication = BaseMixinClass with _MixinOnObject; +base class BaseExtendApplication = BaseMixinClass with _MixinOnObject; +sealed class SealedExtendApplication = BaseMixinClass with _MixinOnObject; + +/// BaseMixinClass can be implemented, so long as the subtype is base, final, or +/// sealed + +// Simple implementation. +base class BaseImplement implements BaseMixinClass {} + +final class FinalImplement implements BaseMixinClass {} + +// Implementing with a sealed class. +sealed class SealedImplement implements BaseMixinClass {} + +// Extending through a sealed class. +base class BaseSealedImplementExtend extends SealedImplement {} + +final class FinalSealedImplementExtend extends SealedImplement {} + +sealed class SealedSealedImplementExtend extends SealedImplement {} + +// Implementing through a sealed class. +base class BaseSealedImplementImplement implements SealedImplement {} + +final class FinalSealedImplementImplement implements SealedImplement {} + +sealed class SealedSealedImplementImplement implements SealedImplement {} + +// Implementing with a mixin class. +base mixin class BaseMixinClassImplement implements BaseMixinClass {} + +// Implementing by applying a mixin class. +base class BaseMixinClassImplementApplied extends Object + with BaseMixinClassImplement {} + +final class FinalMixinClassImplementApplied extends Object + with BaseMixinClassImplement {} + +sealed class SealedMixinClassImplementApplied extends Object + with BaseMixinClassImplement {} + +// Implementing with a mixin application class. +base class BaseImplementApplication = Object + with _MixinOnObject + implements BaseMixinClass; +final class FinalImplementApplication = Object + with _MixinOnObject + implements BaseMixinClass; +sealed class SealedImplementApplication = Object + with _MixinOnObject + implements BaseMixinClass; + +// Implementing with a mixin. +base mixin BaseMixinImplement implements BaseMixinClass {} + +// Implementing by applying a mixin. +base class BaseMixinImplementApplied extends Object with BaseMixinImplement {} + +final class FinalMixinImplementApplied extends Object with BaseMixinImplement {} + +sealed class SealedMixinImplementApplied extends Object + with BaseMixinImplement {} + +/// BaseMixinClass can be an `on` type, so long as the subtype is base. + +base mixin BaseMixinOn on BaseMixinClass {} + +/// BaseMixinClass can be used as a mixin, so long as the result is base, final, +/// or sealed. + +base class BaseMixinClassApply extends Object with BaseMixinClass {} + +final class FinalMixinClassApply extends Object with BaseMixinClass {} + +sealed class SealedMixinClassApply extends Object with BaseMixinClass {} + +// Extending through a sealed class. +base class BaseSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +final class FinalSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +sealed class SealedSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +// Implementing through a sealed class. +base class BaseSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +final class FinalSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +sealed class SealedSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +base mixin class BaseMixinClassSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +base mixin BaseMixinSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplyOn on SealedMixinClassApply {} + +/// BaseMixinClass can be used as a mixin application, so long as the result is +/// base, final, or sealed. + +base class BaseMixinApplication = Object with BaseMixinClass; + +final class FinalMixinApplication = Object with BaseMixinClass; + +sealed class SealedMixinApplication = Object with BaseMixinClass; + +// Extending through a sealed class. +base class BaseSealedMixinApplicationExtend extends SealedMixinApplication {} + +final class FinalSealedMixinApplicationExtend extends SealedMixinApplication {} + +sealed class SealedSealedMixinApplicationExtend + extends SealedMixinApplication {} + +// Implementing through a sealed class. +base class BaseSealedMixinApplicationImplement + implements SealedMixinApplication {} + +final class FinalSealedMixinApplicationImplement + implements SealedMixinApplication {} + +sealed class SealedSealedMixinApplicationImplement + implements SealedMixinApplication {} + +base mixin class BaseMixinClassSealedMixinApplicationImplement + implements SealedMixinApplication {} + +base mixin BaseMixinSealedMixinApplicationImplement + implements SealedMixinApplication {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplicationOn on SealedMixinApplication {} + +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_different_library_error_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_different_library_error_test.dart new file mode 100644 index 00000000000..956a208c27e --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_different_library_error_test.dart @@ -0,0 +1,317 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the invalid uses of a base mixin defined in a different library. + +import "shared_library_definitions.dart" show SimpleClass, BaseMixin; + +mixin _MixinOnObject {} + +/// It is an error if BaseMixin is implemented by something which is not base, +/// final or sealed. + +// Simple implementation. +class SimpleImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +base class BaseImplement implements BaseMixin {} +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +interface class InterfaceImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +final class FinalImplement implements BaseMixin {} +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +sealed class SealedImplement implements BaseMixin {} +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +// Implementing with a mixin class. +mixin class SimpleMixinClassImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +base mixin class BaseMixinClassImplement implements BaseMixin {} +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +// Implementing with a mixin application class. +class SimpleImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject + implements + BaseMixin; +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +base class BaseImplementApplication = Object + with _MixinOnObject + implements BaseMixin; +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +interface class InterfaceImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject + implements + BaseMixin; +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +final class FinalImplementApplication = Object + with _MixinOnObject + implements BaseMixin; +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +sealed class SealedImplementApplication = Object + with _MixinOnObject + implements BaseMixin; +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +// Implementing with a mixin. +mixin SimpleMixinImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +base mixin BaseMixinImplement implements BaseMixin {} +// ^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The mixin 'BaseMixin' can't be implemented outside of its library because it's a base mixin. + +/// It is an error if BaseMixin is the `on` type of something which is not base. + +mixin SimpleMixinOn on BaseMixin {} +// ^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOn' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +mixin SimpleMixinOnSimpleBase on SimpleClass, BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +mixin SimpleMixinOnBaseSimple on BaseMixin, SimpleClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +/// It is an error to use BaseMixin as a mixin, if the result is not base, +/// final or sealed. + +class SimpleMixinClassApply extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +class SimpleMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +class SimpleMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +interface class InterfaceMixinClassApply extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +interface class InterfaceMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +// Sealed class produced from a base mixin (valid, used for tests below) +sealed class SealedMixinClassApply extends Object with BaseMixin {} + +// Implementing through a sealed class. +class SimpleSealedMixinClassApplyImplement implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +base class BaseSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +interface class InterfaceSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +final class FinalSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +sealed class SealedSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +base mixin class BaseMixinClassSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +base mixin BaseMixinSealedMixinClassApplyImplement + implements SealedMixinClassApply {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +/// It is an error to use BaseMixin as a mixin application, if the result +/// is not base, final or sealed. + +class SimpleMixinClassApplication extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +class SimpleMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +class SimpleMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +interface class InterfaceMixinClassApplication extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +interface class InterfaceMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +// Sealed class produced from a base mixin (valid, used for tests below). +sealed class SealedMixinApplication = Object with BaseMixin; + +// Implementing through a sealed class. +class SimpleSealedMixinApplicationImplement implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +base class BaseSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +interface class InterfaceSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +final class FinalSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +sealed class SealedSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +base mixin class BaseMixinClassSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. + +base mixin BaseMixinSealedMixinApplicationImplement + implements SealedMixinApplication {} +// ^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY +// [cfe] The class 'BaseMixin' can't be implemented outside of its library because it's a base class. diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_different_library_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_different_library_test.dart new file mode 100644 index 00000000000..e93035f8f3c --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_different_library_test.dart @@ -0,0 +1,62 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the valid uses of a base mixin defined in a different library + +import "shared_library_definitions.dart" show BaseMixin; + +/// BaseMixin can be an `on` type, so long as the subtype is base. + +base mixin BaseMixinOn on BaseMixin {} + +/// BaseMixin can be used as a mixin, so long as the result is base, final, +/// or sealed. + +base class BaseMixinApply extends Object with BaseMixin {} + +final class FinalMixinClassApply extends Object with BaseMixin {} + +sealed class SealedMixinClassApply extends Object with BaseMixin {} + +// Extending through a sealed class. +base class BaseSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +final class FinalSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +sealed class SealedSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplyOn on SealedMixinClassApply {} + +/// BaseMixin can be used as a mixin application, so long as the result is +/// base, final, or sealed. + +base class BaseMixinApplication = Object with BaseMixin; + +final class FinalMixinApplication = Object with BaseMixin; + +sealed class SealedMixinApplication = Object with BaseMixin; + +// Extending through a sealed class. +base class BaseSealedMixinApplicationExtend extends SealedMixinApplication {} + +final class FinalSealedMixinApplicationExtend extends SealedMixinApplication {} + +sealed class SealedSealedMixinApplicationExtend + extends SealedMixinApplication {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplicationOn on SealedMixinApplication {} + +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_same_library_error_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_same_library_error_test.dart new file mode 100644 index 00000000000..7b8d0b88cfb --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_same_library_error_test.dart @@ -0,0 +1,223 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the invalid uses of a base mixin class within the same library + +class SimpleClass {} + +base mixin BaseMixin {} + +mixin _MixinOnObject {} + +/// It is an error if BaseMixin is implemented by something which is not +/// base, final or sealed. + +// Simple implementation. +class SimpleImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +// Implementing with a sealed class (valid, used for tests below). +sealed class SealedImplement implements BaseMixin {} + +// Extending through a sealed class. +class SimpleSealedImplementExtend extends SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedImplementExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceSealedImplementExtend extends SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedImplementExtend' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +// Implementing through a sealed class. +class SimpleSealedImplementImplement implements SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleSealedImplementImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceSealedImplementImplement implements SealedImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceSealedImplementImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +// Implementing with a mixin class. +mixin class SimpleMixinClassImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +// Implementing with a base mixin class (valid, used for tests below) +base mixin class BaseMixinClassImplement implements BaseMixin {} + +// Implementing by applying a mixin class. +class SimpleMixinClassImplementApplied extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClassImplement' is 'base'. + with + BaseMixinClassImplement {} + +interface class InterfaceMixinClassImplementApplied extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinClassImplement' is 'base'. + with + BaseMixinClassImplement {} + +// Implementing with a mixin application class. +interface class InterfaceImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject + implements + BaseMixin; +class SimpleImplementApplication = Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleImplementApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject + implements + BaseMixin; + +// Implementing with a mixin. +mixin SimpleMixinImplement implements BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinImplement' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +// Implementing with a base mixin (valid, used for tests below) +base mixin BaseMixinImplement implements BaseMixin {} + +// Implementing by applying a mixin. +class SimpleMixinImplementApplied extends Object with BaseMixinImplement {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinImplement' is 'base'. + +interface class InterfaceMixinImplementApplied extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinImplementApplied' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixinImplement' is 'base'. + with + BaseMixinImplement {} + +/// It is an error if BaseMixin is the `on` type of something which is not base. + +mixin SimpleMixinOn on BaseMixin {} +// ^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOn' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +mixin SimpleMixinOnBaseSimple on BaseMixin, SimpleClass {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +mixin SimpleMixinOnSimpleBase on SimpleClass, BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinOnSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +/// It is an error to use BaseMixin as a mixin, if the result is not base, +/// final or sealed. + +class SimpleMixinClassApply extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +class SimpleMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +class SimpleMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +interface class InterfaceMixinClassApply extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApply' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceMixinClassApplySimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplySimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +interface class InterfaceMixinClassApplyBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplyBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +/// It is an error to use BaseMixin as a mixin application, if the result +/// is not base, final or sealed. + +class SimpleMixinClassApplication extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +class SimpleMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +class SimpleMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'SimpleMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} + +interface class InterfaceMixinClassApplication extends Object with BaseMixin {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplication' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + +interface class InterfaceMixinClassApplicationSimpleBase extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationSimpleBase' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + _MixinOnObject, + BaseMixin {} + +interface class InterfaceMixinClassApplicationBaseSimple extends Object +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED +// [cfe] The type 'InterfaceMixinClassApplicationBaseSimple' must be 'base', 'final' or 'sealed' because the supertype 'BaseMixin' is 'base'. + with + BaseMixin, + _MixinOnObject {} diff --git a/tests/language/class_modifiers/base_transitivity/base_mixin_same_library_test.dart b/tests/language/class_modifiers/base_transitivity/base_mixin_same_library_test.dart new file mode 100644 index 00000000000..494a0f0c560 --- /dev/null +++ b/tests/language/class_modifiers/base_transitivity/base_mixin_same_library_test.dart @@ -0,0 +1,156 @@ +// Copyright (c) 2023, 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. + +// SharedOptions=--enable-experiment=class-modifiers + +/// Test the valid uses of a base mixin within the same library + +base mixin BaseMixin {} + +mixin _MixinOnObject {} + +/// BaseMixin can be implemented, so long as the subtype is base, final, or +/// sealed + +// Simple implementation. +base class BaseImplement implements BaseMixin {} + +final class FinalImplement implements BaseMixin {} + +// Implementing with a sealed class. +sealed class SealedImplement implements BaseMixin {} + +// Extending through a sealed class. +base class BaseSealedImplementExtend extends SealedImplement {} + +final class FinalSealedImplementExtend extends SealedImplement {} + +sealed class SealedSealedImplementExtend extends SealedImplement {} + +// Implementing through a sealed class. +base class BaseSealedImplementImplement implements SealedImplement {} + +final class FinalSealedImplementImplement implements SealedImplement {} + +sealed class SealedSealedImplementImplement implements SealedImplement {} + +// Implementing with a mixin class. +base mixin class BaseMixinClassImplement implements BaseMixin {} + +// Implementing by applying a mixin class. +base class BaseMixinClassImplementApplied extends Object + with BaseMixinClassImplement {} + +final class FinalMixinClassImplementApplied extends Object + with BaseMixinClassImplement {} + +sealed class SealedMixinClassImplementApplied extends Object + with BaseMixinClassImplement {} + +// Implementing with a mixin application class. +base class BaseImplementApplication = Object + with _MixinOnObject + implements BaseMixin; +final class FinalImplementApplication = Object + with _MixinOnObject + implements BaseMixin; +sealed class SealedImplementApplication = Object + with _MixinOnObject + implements BaseMixin; + +// Implementing with a mixin. +base mixin BaseMixinImplement implements BaseMixin {} + +// Implementing by applying a mixin. +base class BaseMixinImplementApplied extends Object with BaseMixinImplement {} + +final class FinalMixinImplementApplied extends Object with BaseMixinImplement {} + +sealed class SealedMixinImplementApplied extends Object + with BaseMixinImplement {} + +/// BaseMixin can be an `on` type, so long as the subtype is base. + +base mixin BaseMixinOn on BaseMixin {} + +/// BaseMixin can be used as a mixin, so long as the result is base, final, +/// or sealed. + +base class BaseMixinApply extends Object with BaseMixin {} + +final class FinalMixinClassApply extends Object with BaseMixin {} + +sealed class SealedMixinClassApply extends Object with BaseMixin {} + +// Extending through a sealed class. +base class BaseSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +final class FinalSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +sealed class SealedSealedMixinClassApplyExtend extends SealedMixinClassApply {} + +// Implementing through a sealed class. +base class BaseSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +final class FinalSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +sealed class SealedSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +base mixin class BaseMixinSealedMixinClassApplyImplement + implements SealedMixinClassApply {} + +base mixin BaseMixinSealedMixinApplyImplement + implements SealedMixinClassApply {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplyOn on SealedMixinClassApply {} + +/// BaseMixin can be used as a mixin application, so long as the result is +/// base, final, or sealed. + +base class BaseMixinApplication = Object with BaseMixin; + +final class FinalMixinApplication = Object with BaseMixin; + +sealed class SealedMixinApplication = Object with BaseMixin; + +// Extending through a sealed class. +base class BaseSealedMixinApplicationExtend extends SealedMixinApplication {} + +final class FinalSealedMixinApplicationExtend extends SealedMixinApplication {} + +sealed class SealedSealedMixinApplicationExtend + extends SealedMixinApplication {} + +// Implementing through a sealed class. +base class BaseSealedMixinApplicationImplement + implements SealedMixinApplication {} + +final class FinalSealedMixinApplicationImplement + implements SealedMixinApplication {} + +sealed class SealedSealedMixinApplicationImplement + implements SealedMixinApplication {} + +base mixin class BaseMixinClassSealedMixinApplicationImplement + implements SealedMixinApplication {} + +base mixin BaseMixinSealedMixinApplicationImplement + implements SealedMixinApplication {} + +// Using a sealed class as an `on` type + +base mixin BaseMixinSealedMixinApplicationOn on SealedMixinApplication {} + +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/final_class_different_library_error_test.dart b/tests/language/class_modifiers/base_transitivity/final_class_different_library_error_test.dart index 6aaab875c30..87aa419c717 100644 --- a/tests/language/class_modifiers/base_transitivity/final_class_different_library_error_test.dart +++ b/tests/language/class_modifiers/base_transitivity/final_class_different_library_error_test.dart @@ -197,7 +197,17 @@ mixin SimpleMixinOnSimpleFinal on SimpleClass, FinalClass {} base mixin BaseMixinOn on FinalClass {} // ^ -// [analyzer] unspecified // [cfe] unspecified +// [analyzer] unspecified + +base mixin BaseMixinOnFinalSimple on SimpleClass, FinalClass {} +// ^ +// [cfe] unspecified +// [analyzer] unspecified + +base mixin BaseMixinOnSimpleFinal on FinalClass, SimpleClass {} +// ^ +// [cfe] unspecified +// [analyzer] unspecified main() {} diff --git a/tests/language/class_modifiers/base_transitivity/final_class_same_library_test.dart b/tests/language/class_modifiers/base_transitivity/final_class_same_library_test.dart index b84d02aef73..5edc707cce2 100644 --- a/tests/language/class_modifiers/base_transitivity/final_class_same_library_test.dart +++ b/tests/language/class_modifiers/base_transitivity/final_class_same_library_test.dart @@ -119,4 +119,10 @@ sealed class SealedMixinImplementApplied extends Object base mixin BaseMixinOn on FinalClass {} -main() {} +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/interface_class_different_library_test.dart b/tests/language/class_modifiers/base_transitivity/interface_class_different_library_test.dart index 7a1e60981f1..5b0e29fa9d8 100644 --- a/tests/language/class_modifiers/base_transitivity/interface_class_different_library_test.dart +++ b/tests/language/class_modifiers/base_transitivity/interface_class_different_library_test.dart @@ -113,4 +113,10 @@ mixin SimpleMixinOn on InterfaceClass {} base mixin BaseMixinOn on InterfaceClass {} -main() {} +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/interface_class_same_library_test.dart b/tests/language/class_modifiers/base_transitivity/interface_class_same_library_test.dart index 5e3a4bce882..ba6dfa935b7 100644 --- a/tests/language/class_modifiers/base_transitivity/interface_class_same_library_test.dart +++ b/tests/language/class_modifiers/base_transitivity/interface_class_same_library_test.dart @@ -185,4 +185,10 @@ mixin SimpleMixinOn on InterfaceClass {} base mixin BaseMixinOn on InterfaceClass {} -main() {} +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'. diff --git a/tests/language/class_modifiers/base_transitivity/sealed_class_same_library_test.dart b/tests/language/class_modifiers/base_transitivity/sealed_class_same_library_test.dart index 028811e717c..19c62974727 100644 --- a/tests/language/class_modifiers/base_transitivity/sealed_class_same_library_test.dart +++ b/tests/language/class_modifiers/base_transitivity/sealed_class_same_library_test.dart @@ -184,4 +184,10 @@ mixin SimpleMixinOn on SealedClass {} base mixin BaseMixinOn on SealedClass {} -main() {} +// This test is intended just to check that certain combinations of modifiers +// are statically allowed. Make this a static error test so that backends don't +// try to run it. +int x = "This is a static error test"; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT +// [cfe] A value of type 'String' can't be assigned to a variable of type 'int'.