Extension types. Report when implemented extension type representation is not a supertype of the declared extention type.

Change-Id: Iebb19c3f57046db600305993cc69dae04946889d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319861
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-08-10 18:38:04 +00:00 committed by Commit Queue
parent acefe9ab6d
commit 53cccf9c8b
8 changed files with 112 additions and 11 deletions

View file

@ -656,6 +656,8 @@ CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_ITSELF:
status: noFix
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE:
status: noFix
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE:
status: noFix
CompileTimeErrorCode.EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT:
status: noFix
CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF:

View file

@ -1780,17 +1780,39 @@ class ResolutionVisitor extends RecursiveAstVisitor<void> {
return;
}
if (type.element is! ExtensionTypeElement) {
final erasure = declaredElement.typeErasure;
if (!typeSystem.isSubtypeOf(erasure, type)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode
.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE,
node,
[type, erasure],
);
// When `type` is an extension type.
if (type is InterfaceTypeImpl) {
final implementedRepresentation = type.representationType;
if (implementedRepresentation != null) {
final declaredRepresentation = declaredElement.representation.type;
if (!typeSystem.isSubtypeOf(
declaredRepresentation,
implementedRepresentation,
)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode
.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE,
node,
[
implementedRepresentation,
type.element.name,
declaredRepresentation,
declaredElement.name,
],
);
}
return;
}
}
final erasure = declaredElement.typeErasure;
if (!typeSystem.isSubtypeOf(erasure, type)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE,
node,
[type, erasure],
);
}
}
void _visitIf(IfElementOrStatementImpl node) {

View file

@ -1663,6 +1663,21 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
"Try specifying a different type, or remove the type from the list.",
);
/// Parameters:
/// 0: the representation type of the implemented extension type
/// 1: the name of the implemented extension type
/// 2: the representation type of the this extension type
/// 3: the name of the this extension type
static const CompileTimeErrorCode
EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE =
CompileTimeErrorCode(
'EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE',
"'{0}', the representation type of '{1}', is not a supertype of '{2}', the "
"representation type of '{3}'.",
correctionMessage:
"Try specifying a different type, or remove the type from the list.",
);
/// Parameters:
/// 0: the name of the extension type
/// 1: the name of the conflicting member

View file

@ -198,6 +198,7 @@ const List<ErrorCode> errorCodeValues = [
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_DISALLOWED_TYPE,
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_ITSELF,
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE,
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE,
CompileTimeErrorCode.EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT,
CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF,
CompileTimeErrorCode.EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER,

View file

@ -5090,6 +5090,15 @@ CompileTimeErrorCode:
Parameters:
0: the implemented not extension type
1: the ultimate representation type
EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE:
problemMessage: "'{0}', the representation type of '{1}', is not a supertype of '{2}', the representation type of '{3}'."
correctionMessage: Try specifying a different type, or remove the type from the list.
comment: |-
Parameters:
0: the representation type of the implemented extension type
1: the name of the implemented extension type
2: the representation type of the this extension type
3: the name of the this extension type
EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT:
problemMessage: "The extension type '{0}' has more than one distinct member named '{1}' from implemented types."
correctionMessage: Try redeclaring the corresponding member in this extension type.

View file

@ -9,12 +9,12 @@ import '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ExtensionTypeImplementsDisallowedTypeTest);
defineReflectiveTests(ExtensionTypeImplementsNotSupertypeOfErasureTest);
});
}
@reflectiveTest
class ExtensionTypeImplementsDisallowedTypeTest
class ExtensionTypeImplementsNotSupertypeOfErasureTest
extends PubPackageResolutionTest {
test_notSupertype() async {
await assertErrorsInCode('''

View file

@ -0,0 +1,49 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(
ExtensionTypeImplementsRepresentationNotSupertypeTest);
});
}
@reflectiveTest
class ExtensionTypeImplementsRepresentationNotSupertypeTest
extends PubPackageResolutionTest {
test_notSupertype() async {
await assertErrorsInCode('''
extension type A(String it) {}
extension type B(int it) implements A {}
''', [
error(
CompileTimeErrorCode
.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE,
67,
1),
]);
}
test_supertype() async {
await assertNoErrorsInCode('''
extension type A(num it) {}
extension type B(int it) implements A {}
''');
}
test_supertype2() async {
await assertNoErrorsInCode('''
extension type A(S1 it) {}
extension type B(S3 it) implements A {}
class S1 {}
class S2 extends S1 {}
class S3 extends S2 {}
''');
}
}

View file

@ -252,6 +252,8 @@ import 'extension_type_implements_itself_test.dart'
as extension_type_implements_itself;
import 'extension_type_implements_not_supertype_of_erasure_test.dart'
as extension_type_implements_not_supertype_of_erasure;
import 'extension_type_implements_representation_not_supertype_test.dart'
as extension_type_implements_representation_not_supertype;
import 'extension_type_inherited_member_conflict_test.dart'
as extension_type_inherited_member_conflict;
import 'extension_type_representation_depends_on_itself_test.dart'
@ -1061,6 +1063,7 @@ main() {
extension_type_implements_disallowed_type.main();
extension_type_implements_itself.main();
extension_type_implements_not_supertype_of_erasure.main();
extension_type_implements_representation_not_supertype.main();
extension_type_inherited_member_conflict.main();
extension_type_representation_depends_on_itself.main();
external_field_constructor_initializer.main();