Skip to content

Commit 1345fb8

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Use TypeParameterElement instead of TypeParameterType in inference.
Change-Id: I416dc03c01742cc0552eb73d5e3c7093a280e06a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117900 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 430ff6d commit 1345fb8

File tree

2 files changed

+65
-60
lines changed

2 files changed

+65
-60
lines changed

pkg/analyzer/lib/src/dart/element/member.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,10 @@ class TypeParameterMember extends Member implements TypeParameterElement {
971971
List<TypeParameterElement> formals,
972972
MapSubstitution substitution,
973973
) {
974+
if (substitution.map.isEmpty) {
975+
return formals;
976+
}
977+
974978
// Create type formals with specialized bounds.
975979
// For example `<U extends T>` where T comes from an outer scope.
976980
var newElements = formals.toList(growable: false);

pkg/analyzer/lib/src/generated/type_system.dart

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ class Dart2TypeSystem extends TypeSystem {
318318
* and generic functions; compute lazily and cache.
319319
*/
320320
DartType instantiateToBounds(DartType type,
321-
{List<bool> hasError, Map<TypeParameterType, DartType> knownTypes}) {
321+
{List<bool> hasError, Map<TypeParameterElement, DartType> knownTypes}) {
322322
List<TypeParameterElement> typeFormals = typeFormalsAsElements(type);
323323
List<DartType> arguments = instantiateTypeFormalsToBounds(typeFormals,
324324
hasError: hasError, knownTypes: knownTypes);
@@ -338,20 +338,19 @@ class Dart2TypeSystem extends TypeSystem {
338338
List<DartType> instantiateTypeFormalsToBounds(
339339
List<TypeParameterElement> typeFormals,
340340
{List<bool> hasError,
341-
Map<TypeParameterType, DartType> knownTypes}) {
341+
Map<TypeParameterElement, DartType> knownTypes}) {
342342
int count = typeFormals.length;
343343
if (count == 0) {
344344
return const <DartType>[];
345345
}
346346

347-
Set<TypeParameterType> all = new Set<TypeParameterType>();
347+
Set<TypeParameterElement> all = new Set<TypeParameterElement>();
348348
// all ground
349-
Map<TypeParameterType, DartType> defaults = knownTypes ?? {};
349+
Map<TypeParameterElement, DartType> defaults = knownTypes ?? {};
350350
// not ground
351-
Map<TypeParameterType, DartType> partials = {};
351+
Map<TypeParameterElement, DartType> partials = {};
352352

353-
for (TypeParameterElement typeParameterElement in typeFormals) {
354-
TypeParameterType typeParameter = typeParameterElement.type;
353+
for (TypeParameterElement typeParameter in typeFormals) {
355354
all.add(typeParameter);
356355
if (!defaults.containsKey(typeParameter)) {
357356
if (typeParameter.bound == null) {
@@ -362,8 +361,8 @@ class Dart2TypeSystem extends TypeSystem {
362361
}
363362
}
364363

365-
List<TypeParameterType> getFreeParameters(DartType rootType) {
366-
List<TypeParameterType> parameters = null;
364+
List<TypeParameterElement> getFreeParameters(DartType rootType) {
365+
List<TypeParameterElement> parameters = null;
367366
Set<DartType> visitedTypes = new HashSet<DartType>();
368367

369368
void appendParameters(DartType type) {
@@ -374,9 +373,12 @@ class Dart2TypeSystem extends TypeSystem {
374373
return;
375374
}
376375
visitedTypes.add(type);
377-
if (type is TypeParameterType && all.contains(type)) {
378-
parameters ??= <TypeParameterType>[];
379-
parameters.add(type);
376+
if (type is TypeParameterType) {
377+
var element = type.element;
378+
if (all.contains(element)) {
379+
parameters ??= <TypeParameterElement>[];
380+
parameters.add(element);
381+
}
380382
} else if (AnalysisDriver.useSummary2) {
381383
if (type is FunctionType) {
382384
appendParameters(type.returnType);
@@ -396,17 +398,17 @@ class Dart2TypeSystem extends TypeSystem {
396398
bool hasProgress = true;
397399
while (hasProgress) {
398400
hasProgress = false;
399-
for (TypeParameterType parameter in partials.keys) {
401+
for (TypeParameterElement parameter in partials.keys) {
400402
DartType value = partials[parameter];
401-
List<TypeParameterType> freeParameters = getFreeParameters(value);
403+
List<TypeParameterElement> freeParameters = getFreeParameters(value);
402404
if (freeParameters == null) {
403405
defaults[parameter] = value;
404406
partials.remove(parameter);
405407
hasProgress = true;
406408
break;
407409
} else if (freeParameters.every(defaults.containsKey)) {
408-
defaults[parameter] = value.substitute2(
409-
defaults.values.toList(), defaults.keys.toList());
410+
defaults[parameter] =
411+
Substitution.fromMap(defaults).substituteType(value);
410412
partials.remove(parameter);
411413
hasProgress = true;
412414
break;
@@ -426,19 +428,20 @@ class Dart2TypeSystem extends TypeSystem {
426428
var range = defaults.values.toList();
427429
// Build a substitution Phi mapping each uncompleted type variable to
428430
// dynamic, and each completed type variable to its default.
429-
for (TypeParameterType parameter in partials.keys) {
431+
for (TypeParameterElement parameter in partials.keys) {
430432
domain.add(parameter);
431433
range.add(DynamicTypeImpl.instance);
432434
}
433435
// Set the default for an uncompleted type variable (T extends B)
434436
// to be Phi(B)
435-
for (TypeParameterType parameter in partials.keys) {
436-
defaults[parameter] = partials[parameter].substitute2(range, domain);
437+
for (TypeParameterElement parameter in partials.keys) {
438+
defaults[parameter] = Substitution.fromPairs(domain, range)
439+
.substituteType(partials[parameter]);
437440
}
438441
}
439442

440443
List<DartType> orderedArguments =
441-
typeFormals.map((p) => defaults[p.type]).toList();
444+
typeFormals.map((p) => defaults[p]).toList();
442445
return orderedArguments;
443446
}
444447

@@ -1217,18 +1220,15 @@ class Dart2TypeSystem extends TypeSystem {
12171220
class GenericInferrer {
12181221
final Dart2TypeSystem _typeSystem;
12191222
final TypeProvider typeProvider;
1220-
final Map<TypeParameterElement, List<_TypeConstraint>> constraints;
1223+
final Map<TypeParameterElement, List<_TypeConstraint>> constraints = {};
12211224

12221225
/// Buffer recording constraints recorded while performing a recursive call to
12231226
/// [_matchSubtypeOf] that might fail, so that any constraints recorded during
12241227
/// the failed match can be rewound.
12251228
final _undoBuffer = <_TypeConstraint>[];
12261229

12271230
GenericInferrer(this.typeProvider, this._typeSystem,
1228-
Iterable<TypeParameterElement> typeFormals)
1229-
: constraints = new HashMap(
1230-
equals: (x, y) => x.location == y.location,
1231-
hashCode: (x) => x.location.hashCode) {
1231+
Iterable<TypeParameterElement> typeFormals) {
12321232
for (var formal in typeFormals) {
12331233
constraints[formal] = [];
12341234
}
@@ -1280,30 +1280,29 @@ class GenericInferrer {
12801280
AstNode errorNode,
12811281
bool failAtError: false,
12821282
bool downwardsInferPhase: false}) {
1283-
var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals);
1284-
12851283
// Initialize the inferred type array.
12861284
//
12871285
// In the downwards phase, they all start as `?` to offer reasonable
12881286
// degradation for f-bounded type parameters.
12891287
var inferredTypes = new List<DartType>.filled(
1290-
fnTypeParams.length, UnknownInferredType.instance);
1288+
typeFormals.length, UnknownInferredType.instance);
12911289
var _inferTypeParameter = downwardsInferPhase
12921290
? _inferTypeParameterFromContext
12931291
: _inferTypeParameterFromAll;
12941292

1295-
for (int i = 0; i < fnTypeParams.length; i++) {
1296-
TypeParameterType typeParam = fnTypeParams[i];
1293+
for (int i = 0; i < typeFormals.length; i++) {
1294+
TypeParameterElement typeParam = typeFormals[i];
12971295

1298-
var typeParamBound = typeParam.bound;
12991296
_TypeConstraint extendsClause;
1300-
if (considerExtendsClause && !typeParamBound.isDynamic) {
1301-
extendsClause = new _TypeConstraint.fromExtends(typeParam,
1302-
typeParam.bound.substitute2(inferredTypes, fnTypeParams));
1297+
if (considerExtendsClause && typeParam.bound != null) {
1298+
extendsClause = new _TypeConstraint.fromExtends(
1299+
typeParam,
1300+
Substitution.fromPairs(typeFormals, inferredTypes)
1301+
.substituteType(typeParam.bound));
13031302
}
13041303

13051304
inferredTypes[i] =
1306-
_inferTypeParameter(constraints[typeParam.element], extendsClause);
1305+
_inferTypeParameter(constraints[typeParam], extendsClause);
13071306
}
13081307

13091308
// If the downwards infer phase has failed, we'll catch this in the upwards
@@ -1313,14 +1312,14 @@ class GenericInferrer {
13131312
}
13141313

13151314
// Check the inferred types against all of the constraints.
1316-
var knownTypes = new HashMap<TypeParameterType, DartType>(
1317-
equals: (x, y) => x.element == y.element,
1318-
hashCode: (x) => x.element.hashCode);
1319-
for (int i = 0; i < fnTypeParams.length; i++) {
1320-
TypeParameterType typeParam = fnTypeParams[i];
1321-
var constraints = this.constraints[typeParam.element];
1322-
var typeParamBound =
1323-
typeParam.bound.substitute2(inferredTypes, fnTypeParams);
1315+
var knownTypes = <TypeParameterElement, DartType>{};
1316+
for (int i = 0; i < typeFormals.length; i++) {
1317+
TypeParameterElement typeParam = typeFormals[i];
1318+
var constraints = this.constraints[typeParam];
1319+
var typeParamBound = typeParam.bound != null
1320+
? Substitution.fromPairs(typeFormals, inferredTypes)
1321+
.substituteType(typeParam.bound)
1322+
: typeProvider.dynamicType;
13241323

13251324
var inferred = inferredTypes[i];
13261325
bool success =
@@ -1338,7 +1337,7 @@ class GenericInferrer {
13381337
errorReporter?.reportErrorForNode(
13391338
StrongModeCode.COULD_NOT_INFER,
13401339
errorNode,
1341-
[typeParam, _formatError(typeParam, inferred, constraints)]);
1340+
[typeParam.name, _formatError(typeParam, inferred, constraints)]);
13421341

13431342
// Heuristic: even if we failed, keep the erroneous type.
13441343
// It should satisfy at least some of the constraints (e.g. the return
@@ -1350,7 +1349,7 @@ class GenericInferrer {
13501349
if (failAtError) return null;
13511350
errorReporter
13521351
?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
1353-
typeParam,
1352+
typeParam.name,
13541353
' Inferred candidate type $inferred has type parameters'
13551354
' ${(inferred as FunctionType).typeFormals}, but a function with'
13561355
' type parameters cannot be used as a type argument.'
@@ -1383,21 +1382,21 @@ class GenericInferrer {
13831382
}
13841383

13851384
// Use instantiate to bounds to finish things off.
1386-
var hasError = new List<bool>.filled(fnTypeParams.length, false);
1385+
var hasError = new List<bool>.filled(typeFormals.length, false);
13871386
var result = _typeSystem.instantiateTypeFormalsToBounds(typeFormals,
13881387
hasError: hasError, knownTypes: knownTypes);
13891388

13901389
// Report any errors from instantiateToBounds.
13911390
for (int i = 0; i < hasError.length; i++) {
13921391
if (hasError[i]) {
13931392
if (failAtError) return null;
1394-
TypeParameterType typeParam = fnTypeParams[i];
1395-
var typeParamBound =
1396-
typeParam.bound.substitute2(inferredTypes, fnTypeParams);
1393+
TypeParameterElement typeParam = typeFormals[i];
1394+
var typeParamBound = Substitution.fromPairs(typeFormals, inferredTypes)
1395+
.substituteType(typeParam.bound ?? typeProvider.objectType);
13971396
// TODO(jmesserly): improve this error message.
13981397
errorReporter
13991398
?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
1400-
typeParam,
1399+
typeParam.name,
14011400
"\nRecursive bound cannot be instantiated: '$typeParamBound'."
14021401
"\nConsider passing explicit type argument(s) "
14031402
"to the generic.\n\n'"
@@ -1485,9 +1484,9 @@ class GenericInferrer {
14851484
return lower;
14861485
}
14871486

1488-
String _formatError(TypeParameterType typeParam, DartType inferred,
1487+
String _formatError(TypeParameterElement typeParam, DartType inferred,
14891488
Iterable<_TypeConstraint> constraints) {
1490-
var intro = "Tried to infer '$inferred' for '$typeParam'"
1489+
var intro = "Tried to infer '$inferred' for '${typeParam.name}'"
14911490
" which doesn't work:";
14921491

14931492
var constraintsByOrigin = <_TypeConstraintOrigin, List<_TypeConstraint>>{};
@@ -1680,7 +1679,7 @@ class GenericInferrer {
16801679
var constraints = this.constraints[t1.element];
16811680
if (constraints != null) {
16821681
if (!identical(t2, UnknownInferredType.instance)) {
1683-
var constraint = new _TypeConstraint(origin, t1, upper: t2);
1682+
var constraint = new _TypeConstraint(origin, t1.element, upper: t2);
16841683
constraints.add(constraint);
16851684
_undoBuffer.add(constraint);
16861685
}
@@ -1691,7 +1690,7 @@ class GenericInferrer {
16911690
var constraints = this.constraints[t2.element];
16921691
if (constraints != null) {
16931692
if (!identical(t1, UnknownInferredType.instance)) {
1694-
var constraint = new _TypeConstraint(origin, t2, lower: t1);
1693+
var constraint = new _TypeConstraint(origin, t2.element, lower: t1);
16951694
constraints.add(constraint);
16961695
_undoBuffer.add(constraint);
16971696
}
@@ -1831,7 +1830,7 @@ class GenericInferrer {
18311830
void _rewindConstraints(int previousRewindBufferLength) {
18321831
while (_undoBuffer.length > previousRewindBufferLength) {
18331832
var constraint = _undoBuffer.removeLast();
1834-
var element = constraint.typeParameter.element;
1833+
var element = constraint.typeParameter;
18351834
assert(identical(constraints[element].last, constraint));
18361835
constraints[element].removeLast();
18371836
}
@@ -2985,7 +2984,7 @@ class UnknownInferredTypeElement extends ElementImpl
29852984
/// A constraint on a type parameter that we're inferring.
29862985
class _TypeConstraint extends _TypeRange {
29872986
/// The type parameter that is constrained by [lowerBound] or [upperBound].
2988-
final TypeParameterType typeParameter;
2987+
final TypeParameterElement typeParameter;
29892988

29902989
/// Where this constraint comes from, used for error messages.
29912990
///
@@ -2996,8 +2995,10 @@ class _TypeConstraint extends _TypeRange {
29962995
{DartType upper, DartType lower})
29972996
: super(upper: upper, lower: lower);
29982997

2999-
_TypeConstraint.fromExtends(TypeParameterType type, DartType extendsType)
3000-
: this(new _TypeConstraintFromExtendsClause(type, extendsType), type,
2998+
_TypeConstraint.fromExtends(
2999+
TypeParameterElement element, DartType extendsType)
3000+
: this(
3001+
new _TypeConstraintFromExtendsClause(element, extendsType), element,
30013002
upper: extendsType);
30023003

30033004
bool get isDownwards => origin is! _TypeConstraintFromArgument;
@@ -3049,15 +3050,15 @@ class _TypeConstraintFromArgument extends _TypeConstraintOrigin {
30493050
}
30503051

30513052
class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
3052-
final TypeParameterType typeParam;
3053+
final TypeParameterElement typeParam;
30533054
final DartType extendsType;
30543055

30553056
_TypeConstraintFromExtendsClause(this.typeParam, this.extendsType);
30563057

30573058
@override
30583059
formatError() {
30593060
return [
3060-
"Type parameter '$typeParam'",
3061+
"Type parameter '${typeParam.name}'",
30613062
"declared to extend '$extendsType'."
30623063
];
30633064
}

0 commit comments

Comments
 (0)