Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Unified Diff: pkg/kernel/lib/src/incremental_class_hierarchy.dart

Issue 2915263003: Implement getClassAsInstanceOf() and getTypeAsInstanceOf() for IncrementalClassHierarchy. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/kernel/test/class_hierarchy_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/src/incremental_class_hierarchy.dart
diff --git a/pkg/kernel/lib/src/incremental_class_hierarchy.dart b/pkg/kernel/lib/src/incremental_class_hierarchy.dart
index bdca807d4ca06740978362fe52f538992cc66f02..2f29efc1d0114f4f96663b8d0d85af4dc2cecb8c 100644
--- a/pkg/kernel/lib/src/incremental_class_hierarchy.dart
+++ b/pkg/kernel/lib/src/incremental_class_hierarchy.dart
@@ -3,11 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
library kernel.incremental_class_hierarchy;
+import 'dart:collection';
import 'dart:math';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/src/heap.dart';
+import 'package:kernel/type_algebra.dart';
/// Lazy and incremental implementation of [ClassHierarchy].
class IncrementalClassHierarchy implements ClassHierarchy {
@@ -32,9 +34,13 @@ class IncrementalClassHierarchy implements ClassHierarchy {
}
@override
- Supertype getClassAsInstanceOf(Class class_, Class superclass) {
- // TODO(scheglov): implement getClassAsInstanceOf
- throw new UnimplementedError();
+ Supertype getClassAsInstanceOf(Class node, Class superclass) {
+ if (identical(node, superclass)) return node.asThisSupertype;
+ _ClassInfo info = _getInfo(node);
+ _ClassInfo superInfo = _getInfo(superclass);
+ if (!info.isSubtypeOf(superInfo)) return null;
+ if (superclass.typeParameters.isEmpty) return superclass.asRawSupertype;
+ return info.genericSuperTypes[superclass];
}
@override
@@ -74,8 +80,11 @@ class IncrementalClassHierarchy implements ClassHierarchy {
@override
InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
- // TODO(scheglov): implement getTypeAsInstanceOf
- throw new UnimplementedError();
+ Supertype castedType = getClassAsInstanceOf(type.classNode, superclass);
+ if (castedType == null) return null;
+ return Substitution
+ .fromInterfaceType(type)
+ .substituteType(castedType.asInterfaceType);
}
@override
@@ -91,18 +100,29 @@ class IncrementalClassHierarchy implements ClassHierarchy {
info = new _ClassInfo(_nextId++, node);
_info[node] = info;
+ void addSupertypeIdentifiers(_ClassInfo superInfo) {
+ info.supertypeIdSet.add(superInfo.id);
+ info.supertypeIdSet.addAll(superInfo.supertypeIdSet);
+ }
+
int superDepth = -1;
if (node.supertype != null) {
var superInfo = _getInfo(node.supertype.classNode);
superDepth = max(superDepth, superInfo.depth);
+ addSupertypeIdentifiers(superInfo);
+ _recordSuperTypes(info, node.supertype, superInfo);
}
if (node.mixedInType != null) {
var mixedInfo = _getInfo(node.mixedInType.classNode);
superDepth = max(superDepth, mixedInfo.depth);
+ addSupertypeIdentifiers(mixedInfo);
+ _recordSuperTypes(info, node.mixedInType, mixedInfo);
}
- for (var supertype in node.implementedTypes) {
- var implementedInfo = _getInfo(supertype.classNode);
+ for (var implementedType in node.implementedTypes) {
+ var implementedInfo = _getInfo(implementedType.classNode);
superDepth = max(superDepth, implementedInfo.depth);
+ addSupertypeIdentifiers(implementedInfo);
+ _recordSuperTypes(info, implementedType, implementedInfo);
}
info.depth = superDepth + 1;
}
@@ -138,6 +158,42 @@ class IncrementalClassHierarchy implements ClassHierarchy {
}
return chain;
}
+
+ void _recordSuperTypes(
+ _ClassInfo subInfo, Supertype supertype, _ClassInfo superInfo) {
+ if (supertype.typeArguments.isEmpty) {
+ // The supertype is not generic, and if it does not have generic
+ // supertypes itself, then subclass also does not have generic supertypes.
+ if (superInfo.genericSuperTypes == null) return;
+ // Since the immediate super type is not generic, all entries in its
+ // super type map are also valid entries for this class.
+ if (subInfo.genericSuperTypes == null &&
+ superInfo.ownsGenericSuperTypeMap) {
+ // Instead of copying the map, take ownership of the map object.
+ // This may result in more entries being added to the map later. Those
+ // are not valid for the super type, but it works out because all
+ // lookups in the map are guarded by a subtype check, so the super type
+ // will not be bothered by the extra entries.
+ subInfo.genericSuperTypes = superInfo.genericSuperTypes;
+ superInfo.ownsGenericSuperTypeMap = false;
+ } else {
+ // Copy over the super type entries.
+ subInfo.genericSuperTypes ??= <Class, Supertype>{};
+ subInfo.genericSuperTypes.addAll(superInfo.genericSuperTypes);
+ }
+ } else {
+ // Copy over all transitive generic super types, and substitute the
+ // free variables with those provided in [supertype].
+ Class superclass = supertype.classNode;
+ var substitution = Substitution.fromPairs(
+ superclass.typeParameters, supertype.typeArguments);
+ subInfo.genericSuperTypes ??= <Class, Supertype>{};
+ superInfo.genericSuperTypes?.forEach((Class key, Supertype type) {
+ subInfo.genericSuperTypes[key] = substitution.substituteSupertype(type);
+ });
+ subInfo.genericSuperTypes[superclass] = supertype;
+ }
+ }
}
/// Information about a [Class].
@@ -157,8 +213,45 @@ class _ClassInfo {
/// been computed yet.
List<_ClassInfo> rankedSuperclassList;
+ /// The set of [id]s for supertypes.
+ /// TODO(scheglov): Maybe optimize.
+ final Set<int> supertypeIdSet = new HashSet<int>();
+
+ /// Maps generic supertype classes to the instantiation implemented by this
+ /// class, or `null` if the class does not have generic supertypes.
+ ///
+ /// E.g. `List` maps to `List<String>` for a class that directly of indirectly
+ /// implements `List<String>`.
+ ///
+ /// However, the map may contain additional entries for classes that are not
+ /// supertypes of this class, so that a single map object can be shared
+ /// between different classes. Lookups into the map should therefore be
+ /// guarded by a subtype check.
+ ///
+ /// For example:
+ ///
+ /// class Q<T>
+ /// class A<T>
+ ///
+ /// class B extends A<String>
+ /// class C extends B implements Q<int>
+ ///
+ /// In this case, a single map object `{A: A<String>, Q: Q<int>}` may be
+ /// shared by the classes `B` and `C`.
+ Map<Class, Supertype> genericSuperTypes;
+
+ /// If true, this is the current "owner" of [genericSuperTypes], meaning
+ /// we may add additional entries to the map or transfer ownership to another
+ /// class.
+ bool ownsGenericSuperTypeMap = true;
+
_ClassInfo(this.id, this.node);
+ /// Return `true` if the [superInfo] corresponds to a supertype of this class.
+ bool isSubtypeOf(_ClassInfo superInfo) {
+ return supertypeIdSet.contains(superInfo.id);
+ }
+
@override
String toString() => node.toString();
}
« no previous file with comments | « no previous file | pkg/kernel/test/class_hierarchy_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698