| 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.
|
| ///
|
|
|