Index: pkg/analyzer/lib/src/dart/element/member.dart |
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart |
index 27510764a1a7f91eb95df17dfebc5fb17e401dd0..12c7b36f69842bea1ffcbe99e39adbbe7712335c 100644 |
--- a/pkg/analyzer/lib/src/dart/element/member.dart |
+++ b/pkg/analyzer/lib/src/dart/element/member.dart |
@@ -908,13 +908,11 @@ class PropertyAccessorMember extends ExecutableMember |
* [FunctionType.returnType], and [ParameterMember]. |
*/ |
class TypeParameterMember extends Member implements TypeParameterElement { |
- @override |
- final DartType bound; |
- |
+ DartType _bound; |
DartType _type; |
TypeParameterMember( |
- TypeParameterElement baseElement, DartType definingType, this.bound) |
+ TypeParameterElement baseElement, DartType definingType, this._bound) |
: super(baseElement, definingType) { |
_type = new TypeParameterTypeImpl(this); |
} |
@@ -924,6 +922,9 @@ class TypeParameterMember extends Member implements TypeParameterElement { |
super.baseElement as TypeParameterElement; |
@override |
+ DartType get bound => _bound; |
+ |
+ @override |
Element get enclosingElement => baseElement.enclosingElement; |
@override |
@@ -943,19 +944,40 @@ class TypeParameterMember extends Member implements TypeParameterElement { |
* the given parameter. Return the member that was created, or the base |
* parameter if no member was created. |
*/ |
- static TypeParameterElement from( |
- TypeParameterElement parameter, ParameterizedType definingType) { |
- if (parameter?.bound == null || definingType.typeArguments.isEmpty) { |
- return parameter; |
- } |
- |
- DartType bound = parameter.bound; |
+ static List<TypeParameterElement> from( |
+ List<TypeParameterElement> formals, FunctionType definingType) { |
List<DartType> argumentTypes = definingType.typeArguments; |
+ if (argumentTypes.isEmpty) { |
+ return formals; |
+ } |
List<DartType> parameterTypes = |
TypeParameterTypeImpl.getTypes(definingType.typeParameters); |
- DartType substitutedBound = |
- bound.substitute2(argumentTypes, parameterTypes); |
- return new TypeParameterMember(parameter, definingType, substitutedBound); |
+ List<TypeParameterType> formalTypes = |
+ TypeParameterTypeImpl.getTypes(formals); |
+ |
+ // Create type formals with specialized bounds. |
+ // For example `<U extends T>` where T comes from an outer scope. |
+ var result = formals.toList(growable: false); |
+ for (int i = 0; i < result.length; i++) { |
+ var formal = formals[i]; |
+ DartType bound = formal?.bound; |
+ if (bound != null) { |
+ // substitute type arguments from the function. |
+ bound = bound.substitute2(argumentTypes, parameterTypes); |
+ var newTypeFormal = |
+ new TypeParameterMember(formal, definingType, bound); |
+ result[i] = newTypeFormal; |
+ // recursive bounds are allowed too, so make sure these are updated |
+ // to refer to any new TypeParameterMember we just made, rather than |
+ // the original type parameter |
+ // TODO(jmesserly): this is required so substituting for the |
+ // typeFormal will work. Investigate if there's a better solution, |
+ // e.g. TypeParameterMember. |
+ newTypeFormal._bound = bound.substitute2( |
Leaf
2017/01/24 19:10:05
Consider doing this in a separate loop afterwards
Jennifer Messerly
2017/01/24 22:44:00
excellent idea
|
+ TypeParameterTypeImpl.getTypes(result), formalTypes); |
+ } |
+ } |
+ return result; |
} |
} |