Skip to content

Commit 669856c

Browse files
kallentuCommit Queue
authored andcommitted
[cfe] Report error when extending/impl/mixing in sealed classes outside of its library.
Change-Id: I8034cba69ca249c2727dea9641c3076788c6a854 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/271164 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
1 parent 72493a7 commit 669856c

33 files changed

+648
-22
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10659,6 +10659,60 @@ Message _withArgumentsSdkSummaryNotFound(Uri uri_) {
1065910659
arguments: {'uri': uri_});
1066010660
}
1066110661

10662+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
10663+
const Template<
10664+
Message Function(
10665+
String
10666+
name)> templateSealedClassSubtypeOutsideOfLibrary = const Template<
10667+
Message Function(String name)>(
10668+
problemMessageTemplate:
10669+
r"""Sealed class '#name' can't be extended, implemented, or mixed in outside of its library.""",
10670+
withArguments: _withArgumentsSealedClassSubtypeOutsideOfLibrary);
10671+
10672+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
10673+
const Code<Message Function(String name)>
10674+
codeSealedClassSubtypeOutsideOfLibrary =
10675+
const Code<Message Function(String name)>(
10676+
"SealedClassSubtypeOutsideOfLibrary",
10677+
);
10678+
10679+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
10680+
Message _withArgumentsSealedClassSubtypeOutsideOfLibrary(String name) {
10681+
if (name.isEmpty) throw 'No name provided';
10682+
name = demangleMixinApplicationName(name);
10683+
return new Message(codeSealedClassSubtypeOutsideOfLibrary,
10684+
problemMessage:
10685+
"""Sealed class '${name}' can't be extended, implemented, or mixed in outside of its library.""",
10686+
arguments: {'name': name});
10687+
}
10688+
10689+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
10690+
const Template<
10691+
Message Function(
10692+
String
10693+
name)> templateSealedMixinSubtypeOutsideOfLibrary = const Template<
10694+
Message Function(String name)>(
10695+
problemMessageTemplate:
10696+
r"""Sealed mixin '#name' can't be mixed in outside of its library.""",
10697+
withArguments: _withArgumentsSealedMixinSubtypeOutsideOfLibrary);
10698+
10699+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
10700+
const Code<Message Function(String name)>
10701+
codeSealedMixinSubtypeOutsideOfLibrary =
10702+
const Code<Message Function(String name)>(
10703+
"SealedMixinSubtypeOutsideOfLibrary",
10704+
);
10705+
10706+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
10707+
Message _withArgumentsSealedMixinSubtypeOutsideOfLibrary(String name) {
10708+
if (name.isEmpty) throw 'No name provided';
10709+
name = demangleMixinApplicationName(name);
10710+
return new Message(codeSealedMixinSubtypeOutsideOfLibrary,
10711+
problemMessage:
10712+
"""Sealed mixin '${name}' can't be mixed in outside of its library.""",
10713+
arguments: {'name': name});
10714+
}
10715+
1066210716
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1066310717
const Code<Null> codeSetLiteralTooManyTypeArguments =
1066410718
messageSetLiteralTooManyTypeArguments;

pkg/front_end/lib/src/fasta/builder/class_builder.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ abstract class ClassBuilder implements DeclarationBuilder {
7474

7575
bool get isMixin;
7676

77+
bool get isMixinDeclaration;
78+
7779
bool get isMixinApplication;
7880

7981
bool get isAnonymousMixinApplication;

pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class DillClassBuilder extends ClassBuilderImpl {
5757
@override
5858
bool get isMacro => cls.isMacro;
5959

60+
@override
61+
bool get isMixinDeclaration => cls.isMixinDeclaration;
62+
6063
@override
6164
bool get isSealed => cls.isSealed;
6265

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ class SourceClassBuilder extends ClassBuilderImpl
103103
@override
104104
TypeBuilder? mixedInTypeBuilder;
105105

106-
bool isMixinDeclaration;
107-
108106
final IndexedClass? referencesFromIndexed;
109107

110108
@override
@@ -116,6 +114,9 @@ class SourceClassBuilder extends ClassBuilderImpl
116114
@override
117115
final bool isAugmentation;
118116

117+
@override
118+
bool isMixinDeclaration;
119+
119120
bool? _isConflictingAugmentationMember;
120121

121122
/// Returns `true` if this class is a class declared in an augmentation

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,22 @@ severity: $severity
20692069
cls.charOffset,
20702070
noLength);
20712071
}
2072+
} else if (supertype is ClassBuilder &&
2073+
supertype.isSealed &&
2074+
supertype.libraryBuilder.origin != cls.libraryBuilder.origin) {
2075+
if (supertype.isMixinDeclaration) {
2076+
cls.addProblem(
2077+
templateSealedMixinSubtypeOutsideOfLibrary
2078+
.withArguments(supertype.fullNameForErrors),
2079+
cls.charOffset,
2080+
noLength);
2081+
} else {
2082+
cls.addProblem(
2083+
templateSealedClassSubtypeOutsideOfLibrary
2084+
.withArguments(supertype.fullNameForErrors),
2085+
cls.charOffset,
2086+
noLength);
2087+
}
20722088
}
20732089
}
20742090

pkg/front_end/messages.status

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,10 @@ SdkSpecificationNotFound/analyzerCode: Fail
861861
SdkSpecificationNotFound/example: Fail
862862
SdkSummaryNotFound/analyzerCode: Fail
863863
SdkSummaryNotFound/example: Fail
864+
SealedClassSubtypeOutsideOfLibrary/analyzerCode: Fail
865+
SealedClassSubtypeOutsideOfLibrary/part_wrapped_script: Fail # Uses imports
866+
SealedMixinSubtypeOutsideOfLibrary/analyzerCode: Fail
867+
SealedMixinSubtypeOutsideOfLibrary/part_wrapped_script: Fail # Uses imports
864868
SetLiteralTooManyTypeArguments/analyzerCode: Fail
865869
SetLiteralTooManyTypeArguments/example: Fail
866870
SetOrMapLiteralTooManyTypeArguments/analyzerCode: Fail

pkg/front_end/messages.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5997,3 +5997,23 @@ InheritedRestrictedMemberOfEnumImplementer:
59975997
script: |
59985998
abstract class A { int get hashCode => 0; }
59995999
abstract class B extends A implements Enum {}
6000+
6001+
SealedClassSubtypeOutsideOfLibrary:
6002+
problemMessage: "Sealed class '#name' can't be extended, implemented, or mixed in outside of its library."
6003+
experiments: sealed-class
6004+
script:
6005+
main.dart:
6006+
import 'lib.dart';
6007+
class B extends A {}
6008+
lib.dart:
6009+
sealed class A {}
6010+
6011+
SealedMixinSubtypeOutsideOfLibrary:
6012+
problemMessage: "Sealed mixin '#name' can't be mixed in outside of its library."
6013+
experiments: sealed-class
6014+
script:
6015+
main.dart:
6016+
import 'lib.dart';
6017+
class B with M {}
6018+
lib.dart:
6019+
sealed mixin M {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'main_lib.dart';
6+
7+
class Class1 extends Sealed {}
8+
9+
class Class2 implements Sealed {}
10+
11+
class Class3 with Sealed {}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/sealed_class/extends_implements_with/main.dart:7:7: Error: Sealed class 'Sealed' can't be extended, implemented, or mixed in outside of its library.
6+
// class Class1 extends Sealed {}
7+
// ^
8+
//
9+
// pkg/front_end/testcases/sealed_class/extends_implements_with/main.dart:9:7: Error: Sealed class 'Sealed' can't be extended, implemented, or mixed in outside of its library.
10+
// class Class2 implements Sealed {}
11+
// ^
12+
//
13+
// pkg/front_end/testcases/sealed_class/extends_implements_with/main.dart:11:7: Error: Sealed class 'Sealed' can't be extended, implemented, or mixed in outside of its library.
14+
// class Class3 with Sealed {}
15+
// ^
16+
//
17+
import self as self;
18+
import "main_lib.dart" as mai;
19+
import "dart:core" as core;
20+
21+
import "org-dartlang-testcase:///main_lib.dart";
22+
23+
class Class1 extends mai::Sealed {
24+
synthetic constructor •() → self::Class1
25+
: super mai::Sealed::•()
26+
;
27+
}
28+
class Class2 extends core::Object implements mai::Sealed {
29+
synthetic constructor •() → self::Class2
30+
: super core::Object::•()
31+
;
32+
}
33+
abstract class _Class3&Object&Sealed = core::Object with mai::Sealed /*isAnonymousMixin,hasConstConstructor*/ {
34+
const synthetic constructor •() → self::_Class3&Object&Sealed
35+
: super core::Object::•()
36+
;
37+
}
38+
class Class3 extends self::_Class3&Object&Sealed {
39+
synthetic constructor •() → self::Class3
40+
: super self::_Class3&Object&Sealed::•()
41+
;
42+
}
43+
44+
library /*isNonNullableByDefault*/;
45+
import self as mai;
46+
import "dart:core" as core;
47+
48+
abstract sealed class Sealed extends core::Object {
49+
synthetic constructor •() → mai::Sealed
50+
: super core::Object::•()
51+
;
52+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/sealed_class/extends_implements_with/main.dart:7:7: Error: Sealed class 'Sealed' can't be extended, implemented, or mixed in outside of its library.
6+
// class Class1 extends Sealed {}
7+
// ^
8+
//
9+
// pkg/front_end/testcases/sealed_class/extends_implements_with/main.dart:9:7: Error: Sealed class 'Sealed' can't be extended, implemented, or mixed in outside of its library.
10+
// class Class2 implements Sealed {}
11+
// ^
12+
//
13+
// pkg/front_end/testcases/sealed_class/extends_implements_with/main.dart:11:7: Error: Sealed class 'Sealed' can't be extended, implemented, or mixed in outside of its library.
14+
// class Class3 with Sealed {}
15+
// ^
16+
//
17+
import self as self;
18+
import "main_lib.dart" as mai;
19+
import "dart:core" as core;
20+
21+
import "org-dartlang-testcase:///main_lib.dart";
22+
23+
class Class1 extends mai::Sealed {
24+
synthetic constructor •() → self::Class1
25+
: super mai::Sealed::•()
26+
;
27+
}
28+
class Class2 extends core::Object implements mai::Sealed {
29+
synthetic constructor •() → self::Class2
30+
: super core::Object::•()
31+
;
32+
}
33+
abstract class _Class3&Object&Sealed extends core::Object implements mai::Sealed /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
34+
const synthetic constructor •() → self::_Class3&Object&Sealed
35+
: super core::Object::•()
36+
;
37+
}
38+
class Class3 extends self::_Class3&Object&Sealed {
39+
synthetic constructor •() → self::Class3
40+
: super self::_Class3&Object&Sealed::•()
41+
;
42+
}
43+
44+
library /*isNonNullableByDefault*/;
45+
import self as mai;
46+
import "dart:core" as core;
47+
48+
abstract sealed class Sealed extends core::Object {
49+
synthetic constructor •() → mai::Sealed
50+
: super core::Object::•()
51+
;
52+
}

0 commit comments

Comments
 (0)