Issue 52164. Include enums and mixins into types of a sealed class.

Bug: https://github.com/dart-lang/sdk/issues/52164
Change-Id: Icd6ac232d6356b7e05995b79e5f7d8b33b88a719
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298260
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-04-25 20:01:52 +00:00 committed by Commit Queue
parent 018dadcf5b
commit b81fd66ed5
2 changed files with 86 additions and 6 deletions

View file

@ -62,7 +62,7 @@ class AnalyzerEnumOperations
}
class AnalyzerExhaustivenessCache extends ExhaustivenessCache<DartType,
ClassElement, EnumElement, FieldElement, DartObject> {
InterfaceElement, EnumElement, FieldElement, DartObject> {
final TypeSystemImpl typeSystem;
AnalyzerExhaustivenessCache(this.typeSystem, LibraryElement enclosingLibrary)
@ -73,18 +73,18 @@ class AnalyzerExhaustivenessCache extends ExhaustivenessCache<DartType,
}
class AnalyzerSealedClassOperations
implements SealedClassOperations<DartType, ClassElement> {
implements SealedClassOperations<DartType, InterfaceElement> {
final TypeSystemImpl _typeSystem;
AnalyzerSealedClassOperations(this._typeSystem);
@override
List<ClassElement> getDirectSubclasses(ClassElement sealedClass) {
List<ClassElement> subclasses = [];
List<InterfaceElement> getDirectSubclasses(InterfaceElement sealedClass) {
List<InterfaceElement> subclasses = [];
LibraryElement library = sealedClass.library;
outer:
for (Element declaration in library.topLevelElements) {
if (declaration != sealedClass && declaration is ClassElement) {
if (declaration != sealedClass && declaration is InterfaceElement) {
bool checkType(InterfaceType? type) {
if (type?.element == sealedClass) {
subclasses.add(declaration);
@ -122,7 +122,7 @@ class AnalyzerSealedClassOperations
@override
DartType? getSubclassAsInstanceOf(
ClassElement subClass, covariant InterfaceType sealedClassType) {
InterfaceElement subClass, covariant InterfaceType sealedClassType) {
InterfaceType thisType = subClass.thisType;
InterfaceType asSealedClass =
thisType.asInstanceOf(sealedClassType.element)!;

View file

@ -325,6 +325,86 @@ void f(A x) {
''');
}
test_alwaysExhaustive_sealedClass_implementedByEnum_3at2() async {
await assertErrorsInCode(r'''
sealed class A {}
class B implements A {}
enum E implements A {
a, b
}
void f(A x) {
switch (x) {
case B _:
case E.a:
break;
}
}
''', [
error(CompileTimeErrorCode.NON_EXHAUSTIVE_SWITCH_STATEMENT, 92, 6),
]);
}
test_alwaysExhaustive_sealedClass_implementedByEnum_3at3() async {
await assertNoErrorsInCode(r'''
sealed class A {}
class B implements A {}
enum E implements A {
a, b
}
void f(A x) {
switch (x) {
case B _:
case E.a:
case E.b:
break;
}
}
''');
}
test_alwaysExhaustive_sealedClass_implementedByMixin_2at1() async {
await assertErrorsInCode(r'''
sealed class A {}
class B implements A {}
mixin M implements A {}
void f(A x) {
switch (x) {
case B _:
break;
}
}
''', [
error(CompileTimeErrorCode.NON_EXHAUSTIVE_SWITCH_STATEMENT, 85, 6),
]);
}
test_alwaysExhaustive_sealedClass_implementedByMixin_2at2() async {
await assertNoErrorsInCode(r'''
sealed class A {}
class B implements A {}
mixin M implements A {}
void f(A x) {
switch (x) {
case B _:
case M _:
break;
}
}
''');
}
test_alwaysExhaustive_typeVariable_bound_bool_true() async {
await assertErrorsInCode(r'''
void f<T extends bool>(T x) {