Skip to content

Commit fee350c

Browse files
scheglovCommit Queue
authored and
Commit Queue
committed
Extension type. Perform ExtensionTypeErasure recursively, move to API.
Bug: #54057 Change-Id: Ib1bb67ae98d49f98f3b70c5c19744f1b74a386da Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/337261 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 42e5cc2 commit fee350c

File tree

9 files changed

+42
-40
lines changed

9 files changed

+42
-40
lines changed

pkg/analyzer/lib/dart/element/type.dart

+11
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ abstract class DartType {
4444
@Deprecated('Use element instead')
4545
Element? get element2;
4646

47+
/// The extension type erasure of this type.
48+
///
49+
/// The extension type erasure of a type `V` is obtained by recursively
50+
/// replacing every subterm of `V` which is an extension type with the
51+
/// corresponding representation type.
52+
///
53+
/// This getter can be used on any type, not necessary on a type that has
54+
/// an extension type as a subterm. If there are no extension types, the
55+
/// same type is returned.
56+
DartType get extensionTypeErasure;
57+
4758
/// Return `true` if this type represents the bottom type.
4859
bool get isBottom;
4960

pkg/analyzer/lib/src/dart/constant/evaluation.dart

+2-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ import 'package:analyzer/src/dart/element/element.dart';
2626
import 'package:analyzer/src/dart/element/member.dart';
2727
import 'package:analyzer/src/dart/element/type.dart';
2828
import 'package:analyzer/src/dart/element/type_algebra.dart';
29-
import 'package:analyzer/src/dart/element/type_system.dart'
30-
show ExtensionTypeErasure, TypeSystemImpl;
29+
import 'package:analyzer/src/dart/element/type_system.dart' show TypeSystemImpl;
3130
import 'package:analyzer/src/diagnostic/diagnostic.dart';
3231
import 'package:analyzer/src/error/codes.dart';
3332
import 'package:analyzer/src/generated/engine.dart';
@@ -3140,7 +3139,7 @@ extension RuntimeExtensions on TypeSystemImpl {
31403139
DartObjectImpl obj,
31413140
DartType type,
31423141
) {
3143-
type = ExtensionTypeErasure().perform(type);
3142+
type = type.extensionTypeErasure;
31443143
if (!isNonNullableByDefault) {
31453144
type = toLegacyTypeIfOptOut(type);
31463145
}

pkg/analyzer/lib/src/dart/constant/value.dart

+3-5
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class DartObjectImpl implements DartObject, Constant {
187187
InstanceState state, {
188188
VariableElementImpl? variable,
189189
}) {
190-
type = ExtensionTypeErasure().perform(type);
190+
type = type.extensionTypeErasure;
191191
return DartObjectImpl._(
192192
typeSystem,
193193
type,
@@ -2506,7 +2506,7 @@ class ListState extends InstanceState {
25062506
required List<DartObjectImpl> elements,
25072507
bool isUnknown = false,
25082508
}) {
2509-
elementType = ExtensionTypeErasure().perform(elementType);
2509+
elementType = elementType.extensionTypeErasure;
25102510
return ListState._(
25112511
elementType: elementType,
25122512
elements: elements,
@@ -3105,9 +3105,7 @@ class TypeState extends InstanceState {
31053105
final DartType? _type;
31063106

31073107
factory TypeState(DartType? type) {
3108-
if (type != null) {
3109-
type = ExtensionTypeErasure().perform(type);
3110-
}
3108+
type = type?.extensionTypeErasure;
31113109
return TypeState._(type);
31123110
}
31133111

pkg/analyzer/lib/src/dart/element/extensions.dart

-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/dart/element/nullability_suffix.dart';
77
import 'package:analyzer/dart/element/type.dart';
88
import 'package:analyzer/src/dart/element/element.dart';
9-
import 'package:analyzer/src/dart/element/type.dart';
109
import 'package:analyzer/src/generated/utilities_dart.dart';
1110
import 'package:collection/collection.dart';
1211
import 'package:meta/meta_meta.dart';
@@ -15,16 +14,6 @@ extension DartTypeExtension on DartType {
1514
bool get isExtensionType {
1615
return element is ExtensionTypeElement;
1716
}
18-
19-
/// If `this` is an [InterfaceType] that is an instantiation of an extension
20-
/// type, returns its representation type erasure. Otherwise, returns self.
21-
DartType get representationTypeErasureOrSelf {
22-
final self = this;
23-
if (self is InterfaceTypeImpl) {
24-
return self.representationTypeErasure ?? self;
25-
}
26-
return self;
27-
}
2817
}
2918

3019
extension ElementAnnotationExtensions on ElementAnnotation {

pkg/analyzer/lib/src/dart/element/type.dart

+5-11
Original file line numberDiff line numberDiff line change
@@ -666,17 +666,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
666666
return null;
667667
}
668668

669-
/// The instantiated representation type erasure, if [element] is an
670-
/// extension type.
671-
DartType? get representationTypeErasure {
672-
if (element case ExtensionTypeElement element) {
673-
final substitution = Substitution.fromInterfaceType(this);
674-
final typeErasure = element.typeErasure;
675-
return substitution.substituteType(typeErasure);
676-
}
677-
return null;
678-
}
679-
680669
@override
681670
InterfaceType? get superclass {
682671
var supertype = element.supertype;
@@ -1269,6 +1258,11 @@ abstract class TypeImpl implements DartType {
12691258
/// Initialize a newly created type.
12701259
TypeImpl({this.alias});
12711260

1261+
@override
1262+
DartType get extensionTypeErasure {
1263+
return const ExtensionTypeErasure().perform(this);
1264+
}
1265+
12721266
@override
12731267
bool get isBottom => false;
12741268

pkg/analyzer/lib/src/dart/element/type_system.dart

+5-6
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ import 'package:analyzer/src/utilities/extensions/collection.dart';
3636
import 'package:meta/meta.dart';
3737

3838
class ExtensionTypeErasure extends ReplacementVisitor {
39+
const ExtensionTypeErasure();
40+
3941
DartType perform(DartType type) {
4042
return type.accept(this) ?? type;
4143
}
4244

4345
@override
4446
DartType? visitInterfaceType(covariant InterfaceTypeImpl type) {
45-
final typeErasure = type.representationTypeErasure;
46-
if (typeErasure != null) {
47-
return typeErasure;
47+
if (type.representationType case final representationType?) {
48+
return representationType.accept(this) ?? representationType;
4849
}
4950

5051
return super.visitInterfaceType(type);
@@ -156,9 +157,7 @@ class TypeSystemImpl implements TypeSystem {
156157
/// type that implements both [left] and [right], regardless of whether
157158
/// [left] is a subtype of [right], or [right] is a subtype of [left].
158159
bool canBeSubtypeOf(DartType left, DartType right) {
159-
if (left case InterfaceTypeImpl(:final representationTypeErasure?)) {
160-
left = representationTypeErasure;
161-
}
160+
left = left.extensionTypeErasure;
162161

163162
// If one is `Null`, then the other must be nullable.
164163
final leftIsNullable = isPotentiallyNullable(left);

pkg/analyzer/lib/src/generated/error_verifier.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import 'package:analyzer/src/dart/ast/ast.dart';
2020
import 'package:analyzer/src/dart/ast/extensions.dart';
2121
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
2222
import 'package:analyzer/src/dart/element/element.dart';
23-
import 'package:analyzer/src/dart/element/extensions.dart';
2423
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
2524
import 'package:analyzer/src/dart/element/non_covariant_type_parameter_position.dart';
2625
import 'package:analyzer/src/dart/element/type.dart';
@@ -4904,7 +4903,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
49044903
final boundNode = current.bound;
49054904
if (boundNode is NamedType) {
49064905
var boundType = boundNode.typeOrThrow;
4907-
boundType = boundType.representationTypeErasureOrSelf;
4906+
boundType = boundType.extensionTypeErasure;
49084907
current = elementToNode[boundType.element];
49094908
} else {
49104909
current = null;

pkg/analyzer/lib/src/summary2/extension_type.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import 'package:analyzer/src/dart/ast/ast.dart';
88
import 'package:analyzer/src/dart/ast/extensions.dart';
99
import 'package:analyzer/src/dart/element/element.dart';
1010
import 'package:analyzer/src/dart/element/type.dart';
11-
import 'package:analyzer/src/dart/element/type_system.dart';
1211
import 'package:analyzer/src/dart/element/type_visitor.dart';
1312
import 'package:analyzer/src/summary2/link.dart';
1413
import 'package:analyzer/src/utilities/extensions/collection.dart';
@@ -151,7 +150,7 @@ class _Node extends graph.Node<_Node> {
151150
final typeSystem = element.library.typeSystem;
152151

153152
element.representation.type = type;
154-
element.typeErasure = ExtensionTypeErasure().perform(type);
153+
element.typeErasure = type.extensionTypeErasure;
155154

156155
final interfaces = node.implementsClause?.interfaces
157156
.map((e) => e.type)

pkg/analyzer/test/src/dart/constant/evaluation_test.dart

+14
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,20 @@ const v = int;
601601
_assertHasPrimitiveEqualityTrue('v');
602602
}
603603

604+
test_identical_extensionType_types_recursive() async {
605+
await assertNoErrorsInCode('''
606+
const c = identical(ExList<ExInt>, List<int>);
607+
608+
extension type const ExInt(int value) implements int {}
609+
extension type const ExList<T>(List<T> value) implements List<T> {}
610+
''');
611+
final result = _topLevelVar('c');
612+
assertDartObjectText(result, r'''
613+
bool true
614+
variable: self::@variable::c
615+
''');
616+
}
617+
604618
test_identical_typeLiteral_explicitTypeArgs_differentTypeArgs() async {
605619
await assertNoErrorsInCode('''
606620
class C<T> {}

0 commit comments

Comments
 (0)