Augment. Report INVALID_OVERRIDE using merged interfaces.

Change-Id: Id515aaf813b60ccbfc3d5fece1b728f1e909a261
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373762
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2024-06-28 21:00:50 +00:00 committed by Commit Queue
parent b792a0c914
commit aa8ea803cf
2 changed files with 77 additions and 23 deletions

View file

@ -196,10 +196,13 @@ class _ClassVerifier {
return true;
}
var classElement = this.classElement;
if (classElement is! EnumElement &&
classElement is ClassElement &&
!classElement.isAbstract &&
var fragment = classElement;
var augmented = fragment.augmented;
var declaration = augmented.declaration;
if (declaration is! EnumElement &&
declaration is ClassElement &&
!declaration.isAbstract &&
implementsDartCoreEnum) {
reporter.atToken(
classNameToken,
@ -208,23 +211,23 @@ class _ClassVerifier {
return true;
}
if (_checkForRecursiveInterfaceInheritance(classElement)) {
if (_checkForRecursiveInterfaceInheritance(declaration)) {
return true;
}
// Compute the interface of the class.
var interface = inheritance.getInterface(classElement);
var interface = inheritance.getInterface(declaration);
// Report conflicts between direct superinterfaces of the class.
for (var conflict in interface.conflicts) {
_reportInconsistentInheritance(classNameToken, conflict);
}
if (classElement.supertype != null) {
directSuperInterfaces.add(classElement.supertype!);
if (declaration.supertype != null) {
directSuperInterfaces.add(declaration.supertype!);
}
if (classElement is MixinElement) {
directSuperInterfaces.addAll(classElement.superclassConstraints);
if (augmented is AugmentedMixinElement) {
directSuperInterfaces.addAll(augmented.superclassConstraints);
}
// Each mixin in `class C extends S with M0, M1, M2 {}` is equivalent to:
@ -235,14 +238,14 @@ class _ClassVerifier {
// So, we need to check members of each mixin against superinterfaces
// of `S`, and superinterfaces of all previous mixins.
var mixinNodes = withClause?.mixinTypes;
var mixinTypes = classElement.mixins;
var mixinTypes = declaration.mixins;
for (var i = 0; i < mixinTypes.length; i++) {
var mixinType = mixinTypes[i];
_checkDeclaredMembers(mixinNodes![i], mixinType, mixinIndex: i);
directSuperInterfaces.add(mixinType);
}
directSuperInterfaces.addAll(classElement.interfaces);
directSuperInterfaces.addAll(augmented.interfaces);
// Check the members of the class itself, against all the previously
// collected superinterfaces of the supertype, mixins, and interfaces.
@ -253,7 +256,7 @@ class _ClassVerifier {
var fieldElement = field.declaredElement as FieldElement;
_checkDeclaredMember(field.name, libraryUri, fieldElement.getter);
_checkDeclaredMember(field.name, libraryUri, fieldElement.setter);
if (!member.isStatic && classElement is! EnumElement) {
if (!member.isStatic && declaration is! EnumElement) {
_checkIllegalEnumValuesDeclaration(field.name);
}
if (!member.isStatic) {
@ -271,7 +274,7 @@ class _ClassVerifier {
if (!(member.isStatic || member.isAbstract || member.isSetter)) {
_checkIllegalConcreteEnumMemberDeclaration(member.name);
}
if (!member.isStatic && classElement is! EnumElement) {
if (!member.isStatic && declaration is! EnumElement) {
_checkIllegalEnumValuesDeclaration(member.name);
}
}
@ -283,10 +286,10 @@ class _ClassVerifier {
GetterSetterTypesVerifier(
typeSystem: typeSystem,
errorReporter: reporter,
).checkInterface(classElement, interface);
).checkInterface(declaration, interface);
if (classElement is ClassElement && !classElement.isAbstract ||
classElement is EnumElement) {
if (declaration is ClassElement && !declaration.isAbstract ||
declaration is EnumElement) {
List<ExecutableElement>? inheritedAbstract;
for (var name in interface.map.keys) {
@ -302,11 +305,11 @@ class _ClassVerifier {
if (_reportConcreteClassWithAbstractMember(name.name)) {
continue;
}
if (_isNotImplementedInConcreteSuperClass(classElement, name)) {
if (_isNotImplementedInConcreteSuperClass(declaration, name)) {
continue;
}
// We already reported ILLEGAL_ENUM_VALUES_INHERITANCE.
if (classElement is EnumElement &&
if (declaration is EnumElement &&
const {'values', 'values='}.contains(name.name)) {
continue;
}

View file

@ -602,6 +602,23 @@ class B implements A {
]);
}
test_method_returnType_interface_fromAugmentation() async {
await assertErrorsInCode('''
class A {
int foo() => 0;
}
class B {
String foo() => '';
}
augment class B implements A {}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 3,
contextMessages: [message(testFile, 16, 3)]),
]);
}
test_method_returnType_interface_grandparent() async {
await assertErrorsInCode('''
abstract class A {
@ -646,6 +663,23 @@ class B extends A {
]);
}
test_method_returnType_superclass_fromAugmentation() async {
await assertErrorsInCode('''
class A {
int foo() => 0;
}
class B {
String foo() => '';
}
augment class B extends A {}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 3,
contextMessages: [message(testFile, 16, 3)]),
]);
}
test_method_returnType_superclass_grandparent() async {
await assertErrorsInCode('''
class A {
@ -694,7 +728,7 @@ class B extends A {
]);
}
test_mixin_field_type() async {
test_mixin_field_type_on() async {
await assertErrorsInCode(r'''
class A {
String foo = '';
@ -711,7 +745,7 @@ mixin M on A {
]);
}
test_mixin_getter_type() async {
test_mixin_getter_type_on() async {
await assertErrorsInCode(r'''
class A {
String get foo => '';
@ -726,7 +760,7 @@ mixin M on A {
]);
}
test_mixin_method_returnType() async {
test_mixin_method_returnType_on() async {
await assertErrorsInCode(r'''
class A {
String foo() => '';
@ -741,7 +775,24 @@ mixin M on A {
]);
}
test_mixin_setter_type() async {
test_mixin_method_returnType_on_fromAugmentation() async {
await assertErrorsInCode(r'''
class A {
int foo() => 0;
}
mixin M {
String foo() => '';
}
augment mixin M on A {}
''', [
error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 3,
contextMessages: [message(testFile, 16, 3)]),
]);
}
test_mixin_setter_type_on() async {
await assertErrorsInCode(r'''
class A {
set foo(String _) {}