Chromium Code Reviews| 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; |
| } |
| } |