mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 05:26:57 +00:00
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:
parent
018dadcf5b
commit
b81fd66ed5
|
@ -62,7 +62,7 @@ class AnalyzerEnumOperations
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnalyzerExhaustivenessCache extends ExhaustivenessCache<DartType,
|
class AnalyzerExhaustivenessCache extends ExhaustivenessCache<DartType,
|
||||||
ClassElement, EnumElement, FieldElement, DartObject> {
|
InterfaceElement, EnumElement, FieldElement, DartObject> {
|
||||||
final TypeSystemImpl typeSystem;
|
final TypeSystemImpl typeSystem;
|
||||||
|
|
||||||
AnalyzerExhaustivenessCache(this.typeSystem, LibraryElement enclosingLibrary)
|
AnalyzerExhaustivenessCache(this.typeSystem, LibraryElement enclosingLibrary)
|
||||||
|
@ -73,18 +73,18 @@ class AnalyzerExhaustivenessCache extends ExhaustivenessCache<DartType,
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnalyzerSealedClassOperations
|
class AnalyzerSealedClassOperations
|
||||||
implements SealedClassOperations<DartType, ClassElement> {
|
implements SealedClassOperations<DartType, InterfaceElement> {
|
||||||
final TypeSystemImpl _typeSystem;
|
final TypeSystemImpl _typeSystem;
|
||||||
|
|
||||||
AnalyzerSealedClassOperations(this._typeSystem);
|
AnalyzerSealedClassOperations(this._typeSystem);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<ClassElement> getDirectSubclasses(ClassElement sealedClass) {
|
List<InterfaceElement> getDirectSubclasses(InterfaceElement sealedClass) {
|
||||||
List<ClassElement> subclasses = [];
|
List<InterfaceElement> subclasses = [];
|
||||||
LibraryElement library = sealedClass.library;
|
LibraryElement library = sealedClass.library;
|
||||||
outer:
|
outer:
|
||||||
for (Element declaration in library.topLevelElements) {
|
for (Element declaration in library.topLevelElements) {
|
||||||
if (declaration != sealedClass && declaration is ClassElement) {
|
if (declaration != sealedClass && declaration is InterfaceElement) {
|
||||||
bool checkType(InterfaceType? type) {
|
bool checkType(InterfaceType? type) {
|
||||||
if (type?.element == sealedClass) {
|
if (type?.element == sealedClass) {
|
||||||
subclasses.add(declaration);
|
subclasses.add(declaration);
|
||||||
|
@ -122,7 +122,7 @@ class AnalyzerSealedClassOperations
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DartType? getSubclassAsInstanceOf(
|
DartType? getSubclassAsInstanceOf(
|
||||||
ClassElement subClass, covariant InterfaceType sealedClassType) {
|
InterfaceElement subClass, covariant InterfaceType sealedClassType) {
|
||||||
InterfaceType thisType = subClass.thisType;
|
InterfaceType thisType = subClass.thisType;
|
||||||
InterfaceType asSealedClass =
|
InterfaceType asSealedClass =
|
||||||
thisType.asInstanceOf(sealedClassType.element)!;
|
thisType.asInstanceOf(sealedClassType.element)!;
|
||||||
|
|
|
@ -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 {
|
test_alwaysExhaustive_typeVariable_bound_bool_true() async {
|
||||||
await assertErrorsInCode(r'''
|
await assertErrorsInCode(r'''
|
||||||
void f<T extends bool>(T x) {
|
void f<T extends bool>(T x) {
|
||||||
|
|
Loading…
Reference in a new issue