@@ -140,6 +140,7 @@ class GenericInferrer {
140
140
if (considerExtendsClause && bound != null ) {
141
141
extendsClause = _TypeConstraint .fromExtends (
142
142
typeParam,
143
+ bound,
143
144
Substitution .fromPairs (typeFormals, inferredTypes)
144
145
.substituteType (bound),
145
146
isNonNullableByDefault: isNonNullableByDefault,
@@ -164,38 +165,38 @@ class GenericInferrer {
164
165
// Check the inferred types against all of the constraints.
165
166
var knownTypes = < TypeParameterElement , DartType > {};
166
167
for (int i = 0 ; i < typeFormals.length; i++ ) {
167
- TypeParameterElement typeParam = typeFormals[i];
168
- var constraints = _constraints[typeParam]! ;
169
-
170
- var typeParamBound = typeParam.bound;
171
- if (typeParamBound != null ) {
172
- typeParamBound = Substitution .fromPairs (typeFormals, inferredTypes)
173
- .substituteType (typeParamBound);
174
- typeParamBound = _toLegacyElementIfOptOut (typeParamBound);
175
- } else {
176
- typeParamBound = typeProvider.dynamicType;
177
- }
168
+ TypeParameterElement parameter = typeFormals[i];
169
+ var constraints = _constraints[parameter]! ;
178
170
179
171
var inferred = inferredTypes[i];
180
172
bool success =
181
173
constraints.every ((c) => c.isSatisfiedBy (_typeSystem, inferred));
182
- if (success && ! typeParamBound.isDynamic) {
183
- // If everything else succeeded, check the `extends` constraint.
184
- var extendsConstraint = _TypeConstraint .fromExtends (
185
- typeParam,
186
- typeParamBound,
187
- isNonNullableByDefault: isNonNullableByDefault,
188
- );
189
- constraints.add (extendsConstraint);
190
- success = extendsConstraint.isSatisfiedBy (_typeSystem, inferred);
174
+
175
+ // If everything else succeeded, check the `extends` constraint.
176
+ if (success) {
177
+ var parameterBoundRaw = parameter.bound;
178
+ if (parameterBoundRaw != null ) {
179
+ var parameterBound =
180
+ Substitution .fromPairs (typeFormals, inferredTypes)
181
+ .substituteType (parameterBoundRaw);
182
+ parameterBound = _toLegacyElementIfOptOut (parameterBound);
183
+ var extendsConstraint = _TypeConstraint .fromExtends (
184
+ parameter,
185
+ parameterBoundRaw,
186
+ parameterBound,
187
+ isNonNullableByDefault: isNonNullableByDefault,
188
+ );
189
+ constraints.add (extendsConstraint);
190
+ success = extendsConstraint.isSatisfiedBy (_typeSystem, inferred);
191
+ }
191
192
}
192
193
193
194
if (! success) {
194
195
if (failAtError) return null ;
195
196
errorReporter? .reportErrorForNode (
196
197
CompileTimeErrorCode .COULD_NOT_INFER ,
197
198
errorNode! ,
198
- [typeParam .name, _formatError (typeParam , inferred, constraints)]);
199
+ [parameter .name, _formatError (parameter , inferred, constraints)]);
199
200
200
201
// Heuristic: even if we failed, keep the erroneous type.
201
202
// It should satisfy at least some of the constraints (e.g. the return
@@ -209,7 +210,7 @@ class GenericInferrer {
209
210
var typeFormalsStr = typeFormals.map (_elementStr).join (', ' );
210
211
errorReporter? .reportErrorForNode (
211
212
CompileTimeErrorCode .COULD_NOT_INFER , errorNode! , [
212
- typeParam .name,
213
+ parameter .name,
213
214
' Inferred candidate type ${_typeStr (inferred )} has type parameters'
214
215
' [$typeFormalsStr ], but a function with'
215
216
' type parameters cannot be used as a type argument.'
@@ -223,7 +224,7 @@ class GenericInferrer {
223
224
}
224
225
225
226
if (UnknownInferredType .isKnown (inferred)) {
226
- knownTypes[typeParam ] = inferred;
227
+ knownTypes[parameter ] = inferred;
227
228
} else if (_typeSystem.strictInference) {
228
229
// [typeParam] could not be inferred. A result will still be returned
229
230
// by [infer], with [typeParam] filled in as its bounds. This is
@@ -538,11 +539,12 @@ class _TypeConstraint extends _TypeRange {
538
539
: super (upper: upper, lower: lower);
539
540
540
541
_TypeConstraint .fromExtends (
541
- TypeParameterElement element, DartType extendsType,
542
+ TypeParameterElement element, DartType boundType, DartType extendsType,
542
543
{required bool isNonNullableByDefault})
543
544
: this (
544
545
_TypeConstraintFromExtendsClause (
545
546
element,
547
+ boundType,
546
548
extendsType,
547
549
isNonNullableByDefault: isNonNullableByDefault,
548
550
),
@@ -601,17 +603,31 @@ class _TypeConstraintFromArgument extends _TypeConstraintOrigin {
601
603
602
604
class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
603
605
final TypeParameterElement typeParam;
606
+
607
+ /// The declared bound of [typeParam] , not `null` , because we create
608
+ /// this clause only when it is not `null` .
609
+ ///
610
+ /// For example `Iterable<T>` for `<T, E extends Iterable<T>>` .
611
+ final DartType boundType;
612
+
613
+ /// [boundType] in which type parameters are substituted with inferred
614
+ /// type arguments.
615
+ ///
616
+ /// For example `Iterable<int>` if `T` inferred to `int` .
604
617
final DartType extendsType;
605
618
606
- _TypeConstraintFromExtendsClause (this .typeParam, this .extendsType,
619
+ _TypeConstraintFromExtendsClause (
620
+ this .typeParam, this .boundType, this .extendsType,
607
621
{required bool isNonNullableByDefault})
608
622
: super (isNonNullableByDefault: isNonNullableByDefault);
609
623
610
624
@override
611
625
List <String > formatError () {
626
+ var boundStr = _typeStr (boundType);
627
+ var extendsStr = _typeStr (extendsType);
612
628
return [
613
629
"Type parameter '${typeParam .name }'" ,
614
- "declared to extend '${ _typeStr ( extendsType )} '."
630
+ "is declared to extend '$boundStr ' producing '$ extendsStr '."
615
631
];
616
632
}
617
633
}
0 commit comments