Index: pkg/kernel/lib/type_algebra.dart |
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart |
index 19508b1ab630d540caaad498d6bfae759e8c54a4..ce4a553dc4a851e34e003d9e907e98002f8abd15 100644 |
--- a/pkg/kernel/lib/type_algebra.dart |
+++ b/pkg/kernel/lib/type_algebra.dart |
@@ -30,6 +30,18 @@ Map<TypeParameter, DartType> getSubstitutionMap(Supertype type) { |
type.classNode.typeParameters, type.typeArguments); |
} |
+Map<TypeParameter, DartType> getUpperBoundSubstitutionMap(Class host) { |
+ if (host.typeParameters.isEmpty) return const <TypeParameter, DartType>{}; |
+ var result = <TypeParameter, DartType>{}; |
+ for (var parameter in host.typeParameters) { |
+ result[parameter] = const DynamicType(); |
+ } |
+ for (var parameter in host.typeParameters) { |
+ result[parameter] = substitute(parameter.bound, result); |
+ } |
+ return result; |
+} |
+ |
/// Like [substitute], except when a type in the [substitution] map references |
/// another substituted type variable, the mapping for that type is recursively |
/// inserted. |
@@ -180,6 +192,21 @@ abstract class Substitution { |
return new _ClassBottomSubstitution(class_); |
} |
+ /// Substitutes covariant uses of [class_]'s type parameters with the upper |
+ /// bound of that type parameter. Recursive references in the bound have |
+ /// been replaced by dynamic. |
+ static Substitution upperBoundForClass(Class class_) { |
+ if (class_.typeParameters.isEmpty) return _NullSubstitution.instance; |
+ var upper = <TypeParameter, DartType>{}; |
+ for (var parameter in class_.typeParameters) { |
+ upper[parameter] = const DynamicType(); |
+ } |
+ for (var parameter in class_.typeParameters) { |
+ upper[parameter] = substitute(parameter.bound, upper); |
+ } |
+ return fromUpperAndLowerBounds(upper, {}); |
+ } |
+ |
/// Substitutes both variables from [first] and [second], favoring those from |
/// [first] if they overlap. |
/// |