Skip to content

Commit 53cccf9

Browse files
scheglovCommit Queue
authored and
Commit Queue
committed
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 <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent acefe9a commit 53cccf9

File tree

8 files changed

+112
-11
lines changed

8 files changed

+112
-11
lines changed

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,8 @@ CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_ITSELF:
656656
status: noFix
657657
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE:
658658
status: noFix
659+
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE:
660+
status: noFix
659661
CompileTimeErrorCode.EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT:
660662
status: noFix
661663
CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF:

pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,17 +1780,39 @@ class ResolutionVisitor extends RecursiveAstVisitor<void> {
17801780
return;
17811781
}
17821782

1783-
if (type.element is! ExtensionTypeElement) {
1784-
final erasure = declaredElement.typeErasure;
1785-
if (!typeSystem.isSubtypeOf(erasure, type)) {
1786-
_errorReporter.reportErrorForNode(
1787-
CompileTimeErrorCode
1788-
.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE,
1789-
node,
1790-
[type, erasure],
1791-
);
1783+
// When `type` is an extension type.
1784+
if (type is InterfaceTypeImpl) {
1785+
final implementedRepresentation = type.representationType;
1786+
if (implementedRepresentation != null) {
1787+
final declaredRepresentation = declaredElement.representation.type;
1788+
if (!typeSystem.isSubtypeOf(
1789+
declaredRepresentation,
1790+
implementedRepresentation,
1791+
)) {
1792+
_errorReporter.reportErrorForNode(
1793+
CompileTimeErrorCode
1794+
.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE,
1795+
node,
1796+
[
1797+
implementedRepresentation,
1798+
type.element.name,
1799+
declaredRepresentation,
1800+
declaredElement.name,
1801+
],
1802+
);
1803+
}
1804+
return;
17921805
}
17931806
}
1807+
1808+
final erasure = declaredElement.typeErasure;
1809+
if (!typeSystem.isSubtypeOf(erasure, type)) {
1810+
_errorReporter.reportErrorForNode(
1811+
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE,
1812+
node,
1813+
[type, erasure],
1814+
);
1815+
}
17941816
}
17951817

17961818
void _visitIf(IfElementOrStatementImpl node) {

pkg/analyzer/lib/src/error/codes.g.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,21 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
16631663
"Try specifying a different type, or remove the type from the list.",
16641664
);
16651665

1666+
/// Parameters:
1667+
/// 0: the representation type of the implemented extension type
1668+
/// 1: the name of the implemented extension type
1669+
/// 2: the representation type of the this extension type
1670+
/// 3: the name of the this extension type
1671+
static const CompileTimeErrorCode
1672+
EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE =
1673+
CompileTimeErrorCode(
1674+
'EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE',
1675+
"'{0}', the representation type of '{1}', is not a supertype of '{2}', the "
1676+
"representation type of '{3}'.",
1677+
correctionMessage:
1678+
"Try specifying a different type, or remove the type from the list.",
1679+
);
1680+
16661681
/// Parameters:
16671682
/// 0: the name of the extension type
16681683
/// 1: the name of the conflicting member

pkg/analyzer/lib/src/error/error_code_values.g.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ const List<ErrorCode> errorCodeValues = [
198198
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_DISALLOWED_TYPE,
199199
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_ITSELF,
200200
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE_OF_ERASURE,
201+
CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE,
201202
CompileTimeErrorCode.EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT,
202203
CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF,
203204
CompileTimeErrorCode.EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER,

pkg/analyzer/messages.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5090,6 +5090,15 @@ CompileTimeErrorCode:
50905090
Parameters:
50915091
0: the implemented not extension type
50925092
1: the ultimate representation type
5093+
EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE:
5094+
problemMessage: "'{0}', the representation type of '{1}', is not a supertype of '{2}', the representation type of '{3}'."
5095+
correctionMessage: Try specifying a different type, or remove the type from the list.
5096+
comment: |-
5097+
Parameters:
5098+
0: the representation type of the implemented extension type
5099+
1: the name of the implemented extension type
5100+
2: the representation type of the this extension type
5101+
3: the name of the this extension type
50935102
EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT:
50945103
problemMessage: "The extension type '{0}' has more than one distinct member named '{1}' from implemented types."
50955104
correctionMessage: Try redeclaring the corresponding member in this extension type.

pkg/analyzer/test/src/diagnostics/extension_type_implements_not_supertype_of_erasure_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import '../dart/resolution/context_collection_resolution.dart';
99

1010
main() {
1111
defineReflectiveSuite(() {
12-
defineReflectiveTests(ExtensionTypeImplementsDisallowedTypeTest);
12+
defineReflectiveTests(ExtensionTypeImplementsNotSupertypeOfErasureTest);
1313
});
1414
}
1515

1616
@reflectiveTest
17-
class ExtensionTypeImplementsDisallowedTypeTest
17+
class ExtensionTypeImplementsNotSupertypeOfErasureTest
1818
extends PubPackageResolutionTest {
1919
test_notSupertype() async {
2020
await assertErrorsInCode('''
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) 2023, 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 'package:analyzer/src/error/codes.dart';
6+
import 'package:test_reflective_loader/test_reflective_loader.dart';
7+
8+
import '../dart/resolution/context_collection_resolution.dart';
9+
10+
main() {
11+
defineReflectiveSuite(() {
12+
defineReflectiveTests(
13+
ExtensionTypeImplementsRepresentationNotSupertypeTest);
14+
});
15+
}
16+
17+
@reflectiveTest
18+
class ExtensionTypeImplementsRepresentationNotSupertypeTest
19+
extends PubPackageResolutionTest {
20+
test_notSupertype() async {
21+
await assertErrorsInCode('''
22+
extension type A(String it) {}
23+
extension type B(int it) implements A {}
24+
''', [
25+
error(
26+
CompileTimeErrorCode
27+
.EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE,
28+
67,
29+
1),
30+
]);
31+
}
32+
33+
test_supertype() async {
34+
await assertNoErrorsInCode('''
35+
extension type A(num it) {}
36+
extension type B(int it) implements A {}
37+
''');
38+
}
39+
40+
test_supertype2() async {
41+
await assertNoErrorsInCode('''
42+
extension type A(S1 it) {}
43+
extension type B(S3 it) implements A {}
44+
class S1 {}
45+
class S2 extends S1 {}
46+
class S3 extends S2 {}
47+
''');
48+
}
49+
}

pkg/analyzer/test/src/diagnostics/test_all.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ import 'extension_type_implements_itself_test.dart'
252252
as extension_type_implements_itself;
253253
import 'extension_type_implements_not_supertype_of_erasure_test.dart'
254254
as extension_type_implements_not_supertype_of_erasure;
255+
import 'extension_type_implements_representation_not_supertype_test.dart'
256+
as extension_type_implements_representation_not_supertype;
255257
import 'extension_type_inherited_member_conflict_test.dart'
256258
as extension_type_inherited_member_conflict;
257259
import 'extension_type_representation_depends_on_itself_test.dart'
@@ -1061,6 +1063,7 @@ main() {
10611063
extension_type_implements_disallowed_type.main();
10621064
extension_type_implements_itself.main();
10631065
extension_type_implements_not_supertype_of_erasure.main();
1066+
extension_type_implements_representation_not_supertype.main();
10641067
extension_type_inherited_member_conflict.main();
10651068
extension_type_representation_depends_on_itself.main();
10661069
external_field_constructor_initializer.main();

0 commit comments

Comments
 (0)