[fasta] Make explicit Object in bound a constraint during type inference

Change-Id: I1da9c822e83663dd285880a074e5a36ff295003c
Reviewed-on: https://dart-review.googlesource.com/55897
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
This commit is contained in:
Dmitry Stefantsov 2018-05-22 13:06:11 +00:00 committed by commit-bot@chromium.org
parent 5924c35640
commit 2c9d8924e3
2 changed files with 24 additions and 8 deletions

View file

@ -267,7 +267,22 @@ class TypeSchemaEnvironment extends TypeEnvironment {
downwardsInferPhase: formalTypes == null);
}
/// Use the given [constraints] to substitute for type variables..
bool hasOmittedBound(TypeParameter parameter) {
// If the bound was omitted by the programmer, the Kernel representation for
// the parameter will look similar to the following:
//
// T extends Object = dynamic
//
// Note that it's not possible to receive [Object] as [TypeParameter.bound]
// and `dynamic` as [TypeParameter.defaultType] from the front end in any
// other way.
DartType bound = parameter.bound;
return bound is InterfaceType &&
identical(bound.classNode, coreTypes.objectClass) &&
parameter.defaultType is DynamicType;
}
/// Use the given [constraints] to substitute for type variables.
///
/// [typeParametersToInfer] is the set of type parameters that should be
/// substituted for. [inferredTypes] should be a list of the same length.
@ -293,7 +308,7 @@ class TypeSchemaEnvironment extends TypeEnvironment {
var typeParamBound = typeParam.bound;
DartType extendsConstraint;
if (!_isObjectOrDynamic(typeParamBound)) {
if (!hasOmittedBound(typeParam)) {
extendsConstraint = Substitution
.fromPairs(typeParametersToInfer, inferredTypes)
.substituteType(typeParamBound);
@ -326,7 +341,7 @@ class TypeSchemaEnvironment extends TypeEnvironment {
var inferred = inferredTypes[i];
bool success = typeSatisfiesConstraint(inferred, constraint);
if (success && !_isObjectOrDynamic(typeParamBound)) {
if (success && !hasOmittedBound(typeParam)) {
// If everything else succeeded, check the `extends` constraint.
var extendsConstraint = typeParamBound;
success = isSubtypeOf(inferred, extendsConstraint);
@ -666,11 +681,6 @@ class TypeSchemaEnvironment extends TypeEnvironment {
return hierarchy.getClassicLeastUpperBound(type1, type2);
}
bool _isObjectOrDynamic(DartType type) =>
type is DynamicType ||
(type is InterfaceType &&
identical(type.classNode, coreTypes.objectClass));
DartType _typeParameterLeastUpperBound(DartType type1, DartType type2) {
// This currently just implements a simple least upper bound to
// handle some common cases. It also avoids some termination issues

View file

@ -229,6 +229,12 @@ FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
}
for (int i = 0; i < typeParameters.length; ++i) {
freshParameters[i].bound = substitute(typeParameters[i].bound, map);
// [defaultType] is populated using instantiate-to-bound algorithm, so it
// shouldn't refer to type parameters from the same declaration. However,
// if a transformation changes [defaultType], it may get such references,
// and the line below should invoke [substitute], like for [bound] above.
freshParameters[i].defaultType = typeParameters[i].defaultType;
}
return new FreshTypeParameters(freshParameters, Substitution.fromMap(map));
}