Skip to content

Commit 2083db9

Browse files
committed
[cfe] Emit error for mixing in class outside of its library except mixin classes.
It is an error to mix in a class declaration that does not have the 'mixin' modifier, outside of its library for class declarations in a library version lower than sealed class' release version. Change-Id: I318bb243705748eae60482b6c3513669f1cbb90c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275440 Reviewed-by: Johnni Winther <[email protected]>
1 parent bf5fa95 commit 2083db9

File tree

60 files changed

+2225
-992
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2225
-992
lines changed

pkg/front_end/lib/src/fasta/source/source_loader.dart

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,23 +2072,35 @@ severity: $severity
20722072
noLength);
20732073
}
20742074
} else if (supertype is ClassBuilder &&
2075-
cls.libraryBuilder.libraryFeatures.sealedClass.isEnabled) {
2076-
// Check for implicit class mixins.
2077-
TypeBuilder? mixedInType = cls.mixedInTypeBuilder;
2078-
if (cls.isMixinApplication &&
2079-
mixedInType != null &&
2080-
mixedInType.declaration == supertype &&
2081-
!supertype.isMixinDeclaration) {
2082-
cls.addProblem(
2083-
templateCantUseClassAsMixin
2084-
.withArguments(supertype.fullNameForErrors),
2085-
cls.charOffset,
2086-
noLength);
2075+
supertype.libraryBuilder.origin != cls.libraryBuilder.origin) {
2076+
if (supertype.libraryBuilder.library.languageVersion >=
2077+
ExperimentalFlag.classModifiers.experimentEnabledVersion &&
2078+
// TODO (kallentu): Only enable with classes that have the
2079+
// 'classModifiers' experiment enabled right now, otherwise the
2080+
// change breaks core libraries. Remove when class modifiers are
2081+
// done.
2082+
cls.libraryBuilder.libraryFeatures.classModifiers.isEnabled) {
2083+
// Check for implicit class mixins.
2084+
// Only classes declared with a 'mixin' modifier are allowed to be
2085+
// mixed in outside of its library.
2086+
TypeBuilder? mixedInType = cls.mixedInTypeBuilder;
2087+
bool isSuperTypeImplicitMixin = mixedInType != null &&
2088+
mixedInType.declaration == supertype &&
2089+
!supertype.isMixinDeclaration;
2090+
if (cls.isMixinApplication &&
2091+
isSuperTypeImplicitMixin &&
2092+
!supertype.isMixinClass) {
2093+
cls.addProblem(
2094+
templateCantUseClassAsMixin
2095+
.withArguments(supertype.fullNameForErrors),
2096+
cls.charOffset,
2097+
noLength);
2098+
}
20872099
}
20882100

20892101
// Report error for subtyping outside of sealed supertype's library.
2090-
if (supertype.isSealed &&
2091-
supertype.libraryBuilder.origin != cls.libraryBuilder.origin) {
2102+
if (cls.libraryBuilder.libraryFeatures.sealedClass.isEnabled &&
2103+
supertype.isSealed) {
20922104
// If the class is a mixin declaration with an `on` clause which is
20932105
// the supertype we are evaluating right now, we want to avoid
20942106
// reporting an error.

pkg/front_end/messages.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ CantInferPackagesFromPackageUri/example: Fail
6565
CantInferTypeDueToCircularity/example: Fail
6666
CantReadFile/part_wrapped_script: Fail # Importing file in the (now) part.
6767
CantUseClassAsMixin/analyzerCode: Fail
68+
CantUseClassAsMixin/part_wrapped_script: Fail # Uses imports
6869
CantUseControlFlowOrSpreadAsConstant/example: Fail
6970
CantUseDeferredPrefixAsConstant/part_wrapped_script: Fail # Importing file in the (now) part.
7071
CantUsePrefixAsExpression/part_wrapped_script: Fail # Importing file in the (now) part.

pkg/front_end/messages.yaml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6021,10 +6021,13 @@ SealedMixinSubtypeOutsideOfLibrary:
60216021

60226022
CantUseClassAsMixin:
60236023
problemMessage: "Class '#name' can't be used as a mixin."
6024-
experiments: sealed-class
6025-
script: |
6026-
class A {}
6027-
class B with A {}
6024+
experiments: class-modifiers
6025+
script:
6026+
main.dart:
6027+
import 'lib.dart';
6028+
class B with A {}
6029+
lib.dart:
6030+
class A {}
60286031

60296032
UnspecifiedGetterNameInObjectPattern:
60306033
problemMessage: "The getter name is not specified explicitly, and the pattern is not a variable. Try specifying the getter name explicitly, or using a variable pattern."
@@ -6033,4 +6036,3 @@ UnspecifiedGetterNameInObjectPattern:
60336036
script: |
60346037
abstract class A { int get foo;}
60356038
test(dynamic x) { if (x case A(: 0)) {} }
6036-

pkg/front_end/testcases/class_modifiers/mixin/mixin_class_declaration.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,13 @@ abstract mixin class B {}
88

99
mixin M {}
1010
mixin class C = Object with M;
11+
12+
class AWith with A {}
13+
14+
class BWith with B {}
15+
16+
class CWith with C {}
17+
18+
class MultipleWithMixin with A, M {}
19+
20+
class MultipleWithAnotherClass with A, B {}

pkg/front_end/testcases/class_modifiers/mixin/mixin_class_declaration.dart.strong.expect

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,63 @@ mixin class C = core::Object with self::M /*hasConstConstructor*/ {
1919
: super core::Object::•()
2020
;
2121
}
22+
abstract class _AWith&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
23+
const synthetic constructor •() → self::_AWith&Object&A
24+
: super core::Object::•()
25+
;
26+
}
27+
class AWith extends self::_AWith&Object&A {
28+
synthetic constructor •() → self::AWith
29+
: super self::_AWith&Object&A::•()
30+
;
31+
}
32+
abstract class _BWith&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/ {
33+
const synthetic constructor •() → self::_BWith&Object&B
34+
: super core::Object::•()
35+
;
36+
}
37+
class BWith extends self::_BWith&Object&B {
38+
synthetic constructor •() → self::BWith
39+
: super self::_BWith&Object&B::•()
40+
;
41+
}
42+
abstract class _CWith&Object&C = core::Object with self::C /*isAnonymousMixin,hasConstConstructor*/ {
43+
const synthetic constructor •() → self::_CWith&Object&C
44+
: super core::Object::•()
45+
;
46+
}
47+
class CWith extends self::_CWith&Object&C {
48+
synthetic constructor •() → self::CWith
49+
: super self::_CWith&Object&C::•()
50+
;
51+
}
52+
abstract class _MultipleWithMixin&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
53+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A
54+
: super core::Object::•()
55+
;
56+
}
57+
abstract class _MultipleWithMixin&Object&A&M = self::_MultipleWithMixin&Object&A with self::M /*isAnonymousMixin,hasConstConstructor*/ {
58+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A&M
59+
: super self::_MultipleWithMixin&Object&A::•()
60+
;
61+
}
62+
class MultipleWithMixin extends self::_MultipleWithMixin&Object&A&M {
63+
synthetic constructor •() → self::MultipleWithMixin
64+
: super self::_MultipleWithMixin&Object&A&M::•()
65+
;
66+
}
67+
abstract class _MultipleWithAnotherClass&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
68+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A
69+
: super core::Object::•()
70+
;
71+
}
72+
abstract class _MultipleWithAnotherClass&Object&A&B = self::_MultipleWithAnotherClass&Object&A with self::B /*isAnonymousMixin,hasConstConstructor*/ {
73+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A&B
74+
: super self::_MultipleWithAnotherClass&Object&A::•()
75+
;
76+
}
77+
class MultipleWithAnotherClass extends self::_MultipleWithAnotherClass&Object&A&B {
78+
synthetic constructor •() → self::MultipleWithAnotherClass
79+
: super self::_MultipleWithAnotherClass&Object&A&B::•()
80+
;
81+
}

pkg/front_end/testcases/class_modifiers/mixin/mixin_class_declaration.dart.strong.transformed.expect

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,63 @@ mixin class C extends core::Object implements self::M /*isEliminatedMixin,hasCon
1919
: super core::Object::•()
2020
;
2121
}
22+
abstract class _AWith&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
23+
const synthetic constructor •() → self::_AWith&Object&A
24+
: super core::Object::•()
25+
;
26+
}
27+
class AWith extends self::_AWith&Object&A {
28+
synthetic constructor •() → self::AWith
29+
: super self::_AWith&Object&A::•()
30+
;
31+
}
32+
abstract class _BWith&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
33+
const synthetic constructor •() → self::_BWith&Object&B
34+
: super core::Object::•()
35+
;
36+
}
37+
class BWith extends self::_BWith&Object&B {
38+
synthetic constructor •() → self::BWith
39+
: super self::_BWith&Object&B::•()
40+
;
41+
}
42+
abstract class _CWith&Object&C extends core::Object implements self::C /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
43+
const synthetic constructor •() → self::_CWith&Object&C
44+
: super core::Object::•()
45+
;
46+
}
47+
class CWith extends self::_CWith&Object&C {
48+
synthetic constructor •() → self::CWith
49+
: super self::_CWith&Object&C::•()
50+
;
51+
}
52+
abstract class _MultipleWithMixin&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
53+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A
54+
: super core::Object::•()
55+
;
56+
}
57+
abstract class _MultipleWithMixin&Object&A&M extends self::_MultipleWithMixin&Object&A implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
58+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A&M
59+
: super self::_MultipleWithMixin&Object&A::•()
60+
;
61+
}
62+
class MultipleWithMixin extends self::_MultipleWithMixin&Object&A&M {
63+
synthetic constructor •() → self::MultipleWithMixin
64+
: super self::_MultipleWithMixin&Object&A&M::•()
65+
;
66+
}
67+
abstract class _MultipleWithAnotherClass&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
68+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A
69+
: super core::Object::•()
70+
;
71+
}
72+
abstract class _MultipleWithAnotherClass&Object&A&B extends self::_MultipleWithAnotherClass&Object&A implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
73+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A&B
74+
: super self::_MultipleWithAnotherClass&Object&A::•()
75+
;
76+
}
77+
class MultipleWithAnotherClass extends self::_MultipleWithAnotherClass&Object&A&B {
78+
synthetic constructor •() → self::MultipleWithAnotherClass
79+
: super self::_MultipleWithAnotherClass&Object&A&B::•()
80+
;
81+
}

pkg/front_end/testcases/class_modifiers/mixin/mixin_class_declaration.dart.textual_outline.expect

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ abstract mixin class B {}
44
mixin M {}
55
mixin
66
class C = Object with M;
7+
class AWith with A {}
8+
class BWith with B {}
9+
class CWith with C {}
10+
class MultipleWithMixin with A, M {}
11+
class MultipleWithAnotherClass with A, B {}

pkg/front_end/testcases/class_modifiers/mixin/mixin_class_declaration.dart.weak.expect

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,63 @@ mixin class C = core::Object with self::M /*hasConstConstructor*/ {
1919
: super core::Object::•()
2020
;
2121
}
22+
abstract class _AWith&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
23+
const synthetic constructor •() → self::_AWith&Object&A
24+
: super core::Object::•()
25+
;
26+
}
27+
class AWith extends self::_AWith&Object&A {
28+
synthetic constructor •() → self::AWith
29+
: super self::_AWith&Object&A::•()
30+
;
31+
}
32+
abstract class _BWith&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/ {
33+
const synthetic constructor •() → self::_BWith&Object&B
34+
: super core::Object::•()
35+
;
36+
}
37+
class BWith extends self::_BWith&Object&B {
38+
synthetic constructor •() → self::BWith
39+
: super self::_BWith&Object&B::•()
40+
;
41+
}
42+
abstract class _CWith&Object&C = core::Object with self::C /*isAnonymousMixin,hasConstConstructor*/ {
43+
const synthetic constructor •() → self::_CWith&Object&C
44+
: super core::Object::•()
45+
;
46+
}
47+
class CWith extends self::_CWith&Object&C {
48+
synthetic constructor •() → self::CWith
49+
: super self::_CWith&Object&C::•()
50+
;
51+
}
52+
abstract class _MultipleWithMixin&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
53+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A
54+
: super core::Object::•()
55+
;
56+
}
57+
abstract class _MultipleWithMixin&Object&A&M = self::_MultipleWithMixin&Object&A with self::M /*isAnonymousMixin,hasConstConstructor*/ {
58+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A&M
59+
: super self::_MultipleWithMixin&Object&A::•()
60+
;
61+
}
62+
class MultipleWithMixin extends self::_MultipleWithMixin&Object&A&M {
63+
synthetic constructor •() → self::MultipleWithMixin
64+
: super self::_MultipleWithMixin&Object&A&M::•()
65+
;
66+
}
67+
abstract class _MultipleWithAnotherClass&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
68+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A
69+
: super core::Object::•()
70+
;
71+
}
72+
abstract class _MultipleWithAnotherClass&Object&A&B = self::_MultipleWithAnotherClass&Object&A with self::B /*isAnonymousMixin,hasConstConstructor*/ {
73+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A&B
74+
: super self::_MultipleWithAnotherClass&Object&A::•()
75+
;
76+
}
77+
class MultipleWithAnotherClass extends self::_MultipleWithAnotherClass&Object&A&B {
78+
synthetic constructor •() → self::MultipleWithAnotherClass
79+
: super self::_MultipleWithAnotherClass&Object&A&B::•()
80+
;
81+
}

pkg/front_end/testcases/class_modifiers/mixin/mixin_class_declaration.dart.weak.modular.expect

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,63 @@ mixin class C = core::Object with self::M /*hasConstConstructor*/ {
1919
: super core::Object::•()
2020
;
2121
}
22+
abstract class _AWith&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
23+
const synthetic constructor •() → self::_AWith&Object&A
24+
: super core::Object::•()
25+
;
26+
}
27+
class AWith extends self::_AWith&Object&A {
28+
synthetic constructor •() → self::AWith
29+
: super self::_AWith&Object&A::•()
30+
;
31+
}
32+
abstract class _BWith&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/ {
33+
const synthetic constructor •() → self::_BWith&Object&B
34+
: super core::Object::•()
35+
;
36+
}
37+
class BWith extends self::_BWith&Object&B {
38+
synthetic constructor •() → self::BWith
39+
: super self::_BWith&Object&B::•()
40+
;
41+
}
42+
abstract class _CWith&Object&C = core::Object with self::C /*isAnonymousMixin,hasConstConstructor*/ {
43+
const synthetic constructor •() → self::_CWith&Object&C
44+
: super core::Object::•()
45+
;
46+
}
47+
class CWith extends self::_CWith&Object&C {
48+
synthetic constructor •() → self::CWith
49+
: super self::_CWith&Object&C::•()
50+
;
51+
}
52+
abstract class _MultipleWithMixin&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
53+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A
54+
: super core::Object::•()
55+
;
56+
}
57+
abstract class _MultipleWithMixin&Object&A&M = self::_MultipleWithMixin&Object&A with self::M /*isAnonymousMixin,hasConstConstructor*/ {
58+
const synthetic constructor •() → self::_MultipleWithMixin&Object&A&M
59+
: super self::_MultipleWithMixin&Object&A::•()
60+
;
61+
}
62+
class MultipleWithMixin extends self::_MultipleWithMixin&Object&A&M {
63+
synthetic constructor •() → self::MultipleWithMixin
64+
: super self::_MultipleWithMixin&Object&A&M::•()
65+
;
66+
}
67+
abstract class _MultipleWithAnotherClass&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/ {
68+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A
69+
: super core::Object::•()
70+
;
71+
}
72+
abstract class _MultipleWithAnotherClass&Object&A&B = self::_MultipleWithAnotherClass&Object&A with self::B /*isAnonymousMixin,hasConstConstructor*/ {
73+
const synthetic constructor •() → self::_MultipleWithAnotherClass&Object&A&B
74+
: super self::_MultipleWithAnotherClass&Object&A::•()
75+
;
76+
}
77+
class MultipleWithAnotherClass extends self::_MultipleWithAnotherClass&Object&A&B {
78+
synthetic constructor •() → self::MultipleWithAnotherClass
79+
: super self::_MultipleWithAnotherClass&Object&A&B::•()
80+
;
81+
}

0 commit comments

Comments
 (0)