mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
[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:
parent
5924c35640
commit
2c9d8924e3
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue