Index: pkg/analyzer/lib/src/generated/type_system.dart |
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart |
index fb823260619f025fdc3ea6a5a279041f352537e6..44e6eb02321adc1f76118de9e4a1fbe73752824c 100644 |
--- a/pkg/analyzer/lib/src/generated/type_system.dart |
+++ b/pkg/analyzer/lib/src/generated/type_system.dart |
@@ -91,26 +91,24 @@ class StrongTypeSystemImpl extends TypeSystem { |
/// Computes the greatest lower bound of [type1] and [type2]. |
DartType getGreatestLowerBound( |
- TypeProvider provider, DartType type1, DartType type2) { |
+ TypeProvider provider, DartType type1, DartType type2, |
+ {dynamicIsBottom: false}) { |
// The greatest lower bound relation is reflexive. |
if (identical(type1, type2)) { |
return type1; |
} |
- // Treat dynamic as top. The GLB of dynamic and any type is just that type |
- // since dynamic permits all values. |
- if (type1.isDynamic) { |
+ // The GLB of top and any type is just that type. |
+ // Also GLB of bottom and any type is bottom. |
+ if (_isTop(type1, dynamicIsBottom: dynamicIsBottom) || |
+ _isBottom(type2, dynamicIsBottom: dynamicIsBottom)) { |
return type2; |
} |
- if (type2.isDynamic) { |
+ if (_isTop(type2, dynamicIsBottom: dynamicIsBottom) || |
+ _isBottom(type1, dynamicIsBottom: dynamicIsBottom)) { |
return type1; |
} |
- // You can't get any lower than bottom. |
- if (type1.isBottom || type2.isBottom) { |
- return provider.bottomType; |
- } |
- |
// Treat void as top-like for GLB. This only comes into play with the |
// return types of two functions whose GLB is being taken. We allow a |
// non-void-returning function to subtype a void-returning one, so match |
@@ -146,7 +144,8 @@ class StrongTypeSystemImpl extends TypeSystem { |
*/ |
@override |
DartType getLeastUpperBound( |
- TypeProvider typeProvider, DartType type1, DartType type2) { |
+ TypeProvider typeProvider, DartType type1, DartType type2, |
+ {bool dynamicIsBottom: false}) { |
if (isNullableType(type1) && isNonNullableType(type2)) { |
assert(type2 is InterfaceType); |
type2 = getLeastNullableSupertype(type2 as InterfaceType); |
@@ -155,7 +154,8 @@ class StrongTypeSystemImpl extends TypeSystem { |
assert(type1 is InterfaceType); |
type1 = getLeastNullableSupertype(type1 as InterfaceType); |
} |
- return super.getLeastUpperBound(typeProvider, type1, type2); |
+ return super.getLeastUpperBound(typeProvider, type1, type2, |
+ dynamicIsBottom: dynamicIsBottom); |
} |
/** |
@@ -476,7 +476,8 @@ class StrongTypeSystemImpl extends TypeSystem { |
DartType paramType; |
if (fType != null && gType != null) { |
// If both functions have this parameter, include both of their types. |
- paramType = getLeastUpperBound(provider, fType, gType); |
+ paramType = |
+ getLeastUpperBound(provider, fType, gType, dynamicIsBottom: true); |
} else { |
paramType = fType ?? gType; |
} |
@@ -560,7 +561,7 @@ class StrongTypeSystemImpl extends TypeSystem { |
@override |
DartType _functionParameterBound( |
TypeProvider provider, DartType f, DartType g) => |
- getGreatestLowerBound(provider, f, g); |
+ getGreatestLowerBound(provider, f, g, dynamicIsBottom: true); |
/** |
* Guard against loops in the class hierarchy |
@@ -639,10 +640,6 @@ class StrongTypeSystemImpl extends TypeSystem { |
provider.dynamicType; |
} |
- bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { |
- return (t.isDynamic && dynamicIsBottom) || t.isBottom; |
- } |
- |
/** |
* Check that [f1] is a subtype of [f2]. |
* |
@@ -791,11 +788,6 @@ class StrongTypeSystemImpl extends TypeSystem { |
return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType); |
} |
- bool _isTop(DartType t, {bool dynamicIsBottom: false}) { |
- // TODO(leafp): Document the rules in play here |
- return (t.isDynamic && !dynamicIsBottom) || t.isObject; |
- } |
- |
/// Check if [type] is in a set of preselected non-nullable types. |
/// [FunctionType]s are always nullable. |
bool isNonNullableType(DartType type) { |
@@ -914,16 +906,20 @@ abstract class TypeSystem { |
* Compute the least upper bound of two types. |
*/ |
DartType getLeastUpperBound( |
- TypeProvider typeProvider, DartType type1, DartType type2) { |
+ TypeProvider typeProvider, DartType type1, DartType type2, |
+ {dynamicIsBottom: false}) { |
// The least upper bound relation is reflexive. |
if (identical(type1, type2)) { |
return type1; |
} |
- // The least upper bound of dynamic and any type T is dynamic. |
- if (type1.isDynamic) { |
+ // The least upper bound of top and any type T is top. |
+ // The least upper bound of bottom and any type T is T. |
+ if (_isTop(type1, dynamicIsBottom: dynamicIsBottom) || |
+ _isBottom(type2, dynamicIsBottom: dynamicIsBottom)) { |
return type1; |
} |
- if (type2.isDynamic) { |
+ if (_isTop(type2, dynamicIsBottom: dynamicIsBottom) || |
+ _isBottom(type1, dynamicIsBottom: dynamicIsBottom)) { |
return type2; |
} |
// The least upper bound of void and any type T != dynamic is void. |
@@ -933,13 +929,6 @@ abstract class TypeSystem { |
if (type2.isVoid) { |
return type2; |
} |
- // The least upper bound of bottom and any type T is T. |
- if (type1.isBottom) { |
- return type2; |
- } |
- if (type2.isBottom) { |
- return type1; |
- } |
if (type1 is TypeParameterType || type2 is TypeParameterType) { |
return _typeParameterLeastUpperBound(typeProvider, type1, type2); |
@@ -1557,3 +1546,12 @@ class _TypeParameterVariance { |
} |
} |
} |
+ |
+bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { |
+ return (t.isDynamic && dynamicIsBottom) || t.isBottom; |
+} |
+ |
+bool _isTop(DartType t, {bool dynamicIsBottom: false}) { |
+ // TODO(leafp): Document the rules in play here |
+ return (t.isDynamic && !dynamicIsBottom) || t.isObject; |
+} |