Skip to content

Commit b9ab8ef

Browse files
committed
Implement LUB for interface types with nullability.
Using InstantiatedClass is a necessary step for fixing DartType.== #37587 Change-Id: Ia959d841778b3894f50f47b7490b59b9d7ab6ba6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/110348 Reviewed-by: Paul Berry <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 8fb6f68 commit b9ab8ef

File tree

8 files changed

+1090
-547
lines changed

8 files changed

+1090
-547
lines changed

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

Lines changed: 0 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,80 +2415,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
24152415
return result;
24162416
}
24172417

2418-
/**
2419-
* Compute the least upper bound of types [i] and [j], both of which are
2420-
* known to be interface types.
2421-
*
2422-
* In the event that the algorithm fails (which might occur due to a bug in
2423-
* the analyzer), `null` is returned.
2424-
*/
2425-
static InterfaceType computeLeastUpperBound(InterfaceType i, InterfaceType j,
2426-
{@deprecated bool strong = true}) {
2427-
// compute set of supertypes
2428-
Set<InterfaceType> si = computeSuperinterfaceSet(i);
2429-
Set<InterfaceType> sj = computeSuperinterfaceSet(j);
2430-
// union si with i and sj with j
2431-
si.add(i);
2432-
sj.add(j);
2433-
// compute intersection, reference as set 's'
2434-
List<InterfaceType> s = _intersection(si, sj);
2435-
return computeTypeAtMaxUniqueDepth(s);
2436-
}
2437-
2438-
/**
2439-
* Return the length of the longest inheritance path from the given [type] to
2440-
* Object.
2441-
*
2442-
* See [computeLeastUpperBound].
2443-
*/
2444-
static int computeLongestInheritancePathToObject(InterfaceType type) =>
2445-
_computeLongestInheritancePathToObject(
2446-
type, 0, new HashSet<ClassElement>());
2447-
2448-
/**
2449-
* Returns the set of all superinterfaces of the given [type].
2450-
*
2451-
* See [computeLeastUpperBound].
2452-
*/
2453-
static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type,
2454-
{@deprecated bool strong = true}) =>
2455-
_computeSuperinterfaceSet(type, new HashSet<InterfaceType>(), true);
2456-
2457-
/**
2458-
* Return the type from the [types] list that has the longest inheritance path
2459-
* to Object of unique length.
2460-
*/
2461-
static InterfaceType computeTypeAtMaxUniqueDepth(List<InterfaceType> types) {
2462-
// for each element in Set s, compute the largest inheritance path to Object
2463-
List<int> depths = new List<int>.filled(types.length, 0);
2464-
int maxDepth = 0;
2465-
for (int n = 0; n < types.length; n++) {
2466-
depths[n] = computeLongestInheritancePathToObject(types[n]);
2467-
if (depths[n] > maxDepth) {
2468-
maxDepth = depths[n];
2469-
}
2470-
}
2471-
// ensure that the currently computed maxDepth is unique,
2472-
// otherwise, decrement and test for uniqueness again
2473-
for (; maxDepth >= 0; maxDepth--) {
2474-
int indexOfLeastUpperBound = -1;
2475-
int numberOfTypesAtMaxDepth = 0;
2476-
for (int m = 0; m < depths.length; m++) {
2477-
if (depths[m] == maxDepth) {
2478-
numberOfTypesAtMaxDepth++;
2479-
indexOfLeastUpperBound = m;
2480-
}
2481-
}
2482-
if (numberOfTypesAtMaxDepth == 1) {
2483-
return types[indexOfLeastUpperBound];
2484-
}
2485-
}
2486-
// Should be impossible--there should always be exactly one type with the
2487-
// maximum depth.
2488-
assert(false);
2489-
return null;
2490-
}
2491-
24922418
/**
24932419
* If there is a single type which is at least as specific as all of the
24942420
* types in [types], return it. Otherwise return `null`.
@@ -2565,105 +2491,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
25652491
return context.typeSystem.getLeastUpperBound(first, second);
25662492
}
25672493

2568-
/**
2569-
* Return the length of the longest inheritance path from a subtype of the
2570-
* given [type] to Object, where the given [depth] is the length of the
2571-
* longest path from the subtype to this type. The set of [visitedTypes] is
2572-
* used to prevent infinite recursion in the case of a cyclic type structure.
2573-
*
2574-
* See [computeLongestInheritancePathToObject], and [computeLeastUpperBound].
2575-
*/
2576-
static int _computeLongestInheritancePathToObject(
2577-
InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) {
2578-
ClassElement classElement = type.element;
2579-
// Object case
2580-
if (type.isObject || visitedTypes.contains(classElement)) {
2581-
return depth;
2582-
}
2583-
int longestPath = 1;
2584-
try {
2585-
visitedTypes.add(classElement);
2586-
int pathLength;
2587-
2588-
// loop through each of the superinterfaces recursively calling this
2589-
// method and keeping track of the longest path to return
2590-
for (InterfaceType interface in classElement.superclassConstraints) {
2591-
pathLength = _computeLongestInheritancePathToObject(
2592-
interface, depth + 1, visitedTypes);
2593-
if (pathLength > longestPath) {
2594-
longestPath = pathLength;
2595-
}
2596-
}
2597-
2598-
// loop through each of the superinterfaces recursively calling this
2599-
// method and keeping track of the longest path to return
2600-
for (InterfaceType interface in classElement.interfaces) {
2601-
pathLength = _computeLongestInheritancePathToObject(
2602-
interface, depth + 1, visitedTypes);
2603-
if (pathLength > longestPath) {
2604-
longestPath = pathLength;
2605-
}
2606-
}
2607-
2608-
// finally, perform this same check on the super type
2609-
// TODO(brianwilkerson) Does this also need to add in the number of mixin
2610-
// classes?
2611-
InterfaceType supertype = classElement.supertype;
2612-
if (supertype != null) {
2613-
pathLength = _computeLongestInheritancePathToObject(
2614-
supertype, depth + 1, visitedTypes);
2615-
if (pathLength > longestPath) {
2616-
longestPath = pathLength;
2617-
}
2618-
}
2619-
} finally {
2620-
visitedTypes.remove(classElement);
2621-
}
2622-
return longestPath;
2623-
}
2624-
2625-
/**
2626-
* Add all of the superinterfaces of the given [type] to the given [set].
2627-
* Return the [set] as a convenience.
2628-
*
2629-
* If [strong] mode is enabled (Dart 2), then the `Function` interface is
2630-
* ignored and not treated as a superinterface.
2631-
*
2632-
* See [computeSuperinterfaceSet], and [computeLeastUpperBound].
2633-
*/
2634-
static Set<InterfaceType> _computeSuperinterfaceSet(
2635-
InterfaceType type, HashSet<InterfaceType> set, bool _) {
2636-
Element element = type.element;
2637-
if (element != null) {
2638-
List<InterfaceType> superinterfaces = type.interfaces;
2639-
for (InterfaceType superinterface in superinterfaces) {
2640-
if (!superinterface.isDartCoreFunction) {
2641-
if (set.add(superinterface)) {
2642-
_computeSuperinterfaceSet(superinterface, set, true);
2643-
}
2644-
}
2645-
}
2646-
InterfaceType supertype = type.superclass;
2647-
if (supertype != null && !supertype.isDartCoreFunction) {
2648-
if (set.add(supertype)) {
2649-
_computeSuperinterfaceSet(supertype, set, true);
2650-
}
2651-
}
2652-
}
2653-
return set;
2654-
}
2655-
2656-
/**
2657-
* Return the intersection of the [first] and [second] sets of types, where
2658-
* intersection is based on the equality of the types themselves.
2659-
*/
2660-
static List<InterfaceType> _intersection(
2661-
Set<InterfaceType> first, Set<InterfaceType> second) {
2662-
Set<InterfaceType> result = new HashSet<InterfaceType>.from(first);
2663-
result.retainAll(second);
2664-
return new List.from(result);
2665-
}
2666-
26672494
/**
26682495
* Return the "least upper bound" of the given types under the assumption that
26692496
* the types have the same element and differ only in terms of the type

pkg/analyzer/lib/src/generated/testing/element_factory.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:analyzer/src/generated/resolver.dart';
1616
import 'package:analyzer/src/generated/source.dart';
1717
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
1818
import 'package:analyzer/src/generated/utilities_dart.dart';
19+
import 'package:meta/meta.dart';
1920
import 'package:path/path.dart';
2021

2122
/**
@@ -54,6 +55,26 @@ class ElementFactory {
5455
[List<String> parameterNames]) =>
5556
classElement(typeName, objectType, parameterNames);
5657

58+
static ClassElementImpl classElement3({
59+
@required String name,
60+
List<TypeParameterElement> typeParameters,
61+
List<String> typeParameterNames = const [],
62+
InterfaceType supertype,
63+
List<InterfaceType> mixins = const [],
64+
List<InterfaceType> interfaces = const [],
65+
}) {
66+
typeParameters ??= ElementFactory.typeParameters(typeParameterNames);
67+
supertype ??= objectType;
68+
69+
var element = ClassElementImpl(name, 0);
70+
element.typeParameters = typeParameters;
71+
element.supertype = supertype;
72+
element.mixins = mixins;
73+
element.interfaces = interfaces;
74+
element.constructors = const <ConstructorElement>[];
75+
return element;
76+
}
77+
5778
static classTypeAlias(String typeName, InterfaceType superclassType,
5879
[List<String> parameterNames]) {
5980
ClassElementImpl element =

0 commit comments

Comments
 (0)