Expose greatestLowerBound() from TypeSystem.

Bug: https://github.com/dart-lang/sdk/issues/53042
Change-Id: Ib332a7ab005a432d98066d79c2e48a5f06e88716
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/318000
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-08-04 20:47:46 +00:00 committed by Commit Queue
parent 2edf0d3720
commit 8cb82a35e8
15 changed files with 48 additions and 55 deletions

View file

@ -1,6 +1,7 @@
## 6.1.0-dev
* Added `InstanceElement`, a super-interface for `InterfaceElement`
and `ExtensionElement`.
* Added `TypeSystem.greatestLowerBound`.
## 6.0.0
* Remove deprecated `declaredElement2` from AST.

View file

@ -34,6 +34,12 @@ abstract class TypeSystem {
/// Other type systems may define this operation differently.
DartType flatten(DartType type);
/// Computes the greatest lower bound of [T1] and [T2].
///
/// https://github.com/dart-lang/language
/// See `resources/type-system/upper-lower-bounds.md`
DartType greatestLowerBound(DartType T1, DartType T2);
/// Instantiate the given [element] with default type arguments.
InterfaceType instantiateInterfaceToBounds({
required InterfaceElement element,
@ -151,16 +157,11 @@ abstract class TypeSystem {
/// Other type systems may define this operation differently.
bool isSubtypeOf(DartType leftType, DartType rightType);
/// Compute the least upper bound of two types. This operation if commutative,
/// meaning that `leastUpperBound(t, s) == leastUpperBound(s, t)` for all `t`
/// and `s`.
/// Computes the least upper bound of [T1] and [T2].
///
/// For the Dart 2.0 type system, the definition of the least upper bound is
/// given in the Dart Language Specification, section 19.9.2 Least Upper
/// Bounds.
///
/// Other type systems may define this operation differently.
DartType leastUpperBound(DartType leftType, DartType rightType);
/// https://github.com/dart-lang/language
/// See `resources/type-system/upper-lower-bounds.md`
DartType leastUpperBound(DartType T1, DartType T2);
/// Returns a non-nullable version of [type]. This is equivalent to the
/// operation `NonNull` defined in the spec.

View file

@ -380,8 +380,8 @@ class GenericInferrer {
//
// This resulting constraint may be unsatisfiable; in that case inference
// will fail.
upper = _typeSystem.getGreatestLowerBound(upper, constraint.upperBound);
lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
upper = _typeSystem.greatestLowerBound(upper, constraint.upperBound);
lower = _typeSystem.leastUpperBound(lower, constraint.lowerBound);
upper = _toLegacyElementIfOptOut(upper);
lower = _toLegacyElementIfOptOut(lower);
}

View file

@ -300,7 +300,7 @@ class GreatestLowerBoundHelper {
gIndex++;
parameters.add(
fParameter.copyWith(
type: _typeSystem.getLeastUpperBound(
type: _typeSystem.leastUpperBound(
fParameter.type,
gParameter.type,
),
@ -320,7 +320,7 @@ class GreatestLowerBoundHelper {
gIndex++;
parameters.add(
fParameter.copyWith(
type: _typeSystem.getLeastUpperBound(
type: _typeSystem.leastUpperBound(
fParameter.type,
gParameter.type,
),

View file

@ -211,9 +211,9 @@ class InterfaceLeastUpperBoundHelper {
Variance parameterVariance =
(params[i] as TypeParameterElementImpl).variance;
if (parameterVariance.isCovariant) {
args.add(typeSystem.getLeastUpperBound(args1[i], args2[i]));
args.add(typeSystem.leastUpperBound(args1[i], args2[i]));
} else if (parameterVariance.isContravariant) {
args.add(typeSystem.getGreatestLowerBound(args1[i], args2[i]));
args.add(typeSystem.greatestLowerBound(args1[i], args2[i]));
} else if (parameterVariance.isInvariant) {
if (!typeSystem.isSubtypeOf(args1[i], args2[i]) ||
!typeSystem.isSubtypeOf(args2[i], args1[i])) {
@ -915,7 +915,7 @@ class LeastUpperBoundHelper {
}
DartType _parameterType(ParameterElement a, ParameterElement b) {
return _typeSystem.getGreatestLowerBound(a.type, b.type);
return _typeSystem.greatestLowerBound(a.type, b.type);
}
DartType _recordType(RecordTypeImpl T1, RecordTypeImpl T2) {

View file

@ -72,12 +72,12 @@ class TypeConstraintGatherer {
var parameter = constraint.parameter;
var mergedConstraint = result[parameter]!;
var lower = _typeSystem.getLeastUpperBound(
var lower = _typeSystem.leastUpperBound(
mergedConstraint.lower,
constraint.lower,
);
var upper = _typeSystem.getGreatestLowerBound(
var upper = _typeSystem.greatestLowerBound(
mergedConstraint.upper,
constraint.upper,
);

View file

@ -602,19 +602,6 @@ class TypeSystemImpl implements TypeSystem {
return parameters;
}
/// Computes the greatest lower bound of [T1] and [T2].
DartType getGreatestLowerBound(DartType T1, DartType T2) {
return _greatestLowerBoundHelper.getGreatestLowerBound(T1, T2);
}
/// Compute the least upper bound of two types.
///
/// https://github.com/dart-lang/language
/// See `resources/type-system/upper-lower-bounds.md`
DartType getLeastUpperBound(DartType T1, DartType T2) {
return _leastUpperBoundHelper.getLeastUpperBound(T1, T2);
}
/// Returns the greatest closure of [type] with respect to [typeParameters].
///
/// https://github.com/dart-lang/language
@ -677,6 +664,11 @@ class TypeSystemImpl implements TypeSystem {
}
}
@override
DartType greatestLowerBound(DartType T1, DartType T2) {
return _greatestLowerBoundHelper.getGreatestLowerBound(T1, T2);
}
/// Given a generic function type `F<T0, T1, ... Tn>` and a context type C,
/// infer an instantiation of F, such that `F<S0, S1, ..., Sn>` <: C.
///
@ -1558,8 +1550,8 @@ class TypeSystemImpl implements TypeSystem {
}
@override
DartType leastUpperBound(DartType leftType, DartType rightType) {
return getLeastUpperBound(leftType, rightType);
DartType leastUpperBound(DartType T1, DartType T2) {
return _leastUpperBoundHelper.getLeastUpperBound(T1, T2);
}
/// Returns a nullable version of [type]. The result would be equivalent to

View file

@ -296,7 +296,7 @@ class AssignmentExpressionResolver {
leftType = _typeSystem.promoteToNonNull(leftType);
}
nodeType = _typeSystem.getLeastUpperBound(leftType, assignedType);
nodeType = _typeSystem.leastUpperBound(leftType, assignedType);
} else {
nodeType = assignedType;
}

View file

@ -87,7 +87,7 @@ class BinaryExpressionResolver {
void _analyzeLeastUpperBoundTypes(
ExpressionImpl node, DartType staticType1, DartType staticType2,
{required DartType? contextType}) {
var staticType = _typeSystem.getLeastUpperBound(staticType1, staticType2);
var staticType = _typeSystem.leastUpperBound(staticType1, staticType2);
staticType = _resolver.toLegacyTypeIfOptOut(staticType);

View file

@ -152,13 +152,13 @@ class BodyInferenceContext {
if (_returnTypes.isEmpty) {
return DynamicTypeImpl.instance;
}
return _returnTypes.reduce(_typeSystem.getLeastUpperBound);
return _returnTypes.reduce(_typeSystem.leastUpperBound);
}
var initialType = endOfBlockIsReachable
? _typeProvider.nullType
: _typeProvider.neverType;
return _returnTypes.fold(initialType, _typeSystem.getLeastUpperBound);
return _returnTypes.fold(initialType, _typeSystem.leastUpperBound);
}
static BodyInferenceContext? of(FunctionBody node) {

View file

@ -420,7 +420,7 @@ class TypeSystemOperations
@override
DartType glb(DartType type1, DartType type2) {
return typeSystem.getGreatestLowerBound(type1, type2);
return typeSystem.greatestLowerBound(type1, type2);
}
@override

View file

@ -205,7 +205,7 @@ class TypedLiteralResolver {
}
var elseType = _computeElementType(elseElement);
return _typeSystem.getLeastUpperBound(thenType, elseType);
return _typeSystem.leastUpperBound(thenType, elseType);
} else if (element is MapLiteralEntry) {
// This error will be reported elsewhere.
return _typeProvider.dynamicType;
@ -847,7 +847,7 @@ class _InferredCollectionElementTypeInformation {
} else if (second == null) {
return first;
} else {
return typeSystem.getLeastUpperBound(first, second);
return typeSystem.leastUpperBound(first, second);
}
}
}

View file

@ -308,8 +308,7 @@ class StaticTypeAnalyzer {
void _analyzeLeastUpperBoundTypes(
ExpressionImpl node, DartType staticType1, DartType staticType2,
{required DartType? contextType}) {
DartType staticType =
_typeSystem.getLeastUpperBound(staticType1, staticType2);
DartType staticType = _typeSystem.leastUpperBound(staticType1, staticType2);
staticType = _resolver.toLegacyTypeIfOptOut(staticType);

View file

@ -1557,7 +1557,7 @@ class LowerBoundTest extends _BoundsTestBase {
{bool checkSubtype = true}) {
var expectedStr = typeString(expected);
var result = typeSystem.getGreatestLowerBound(T1, T2);
var result = typeSystem.greatestLowerBound(T1, T2);
var resultStr = typeString(result);
expect(result, expected, reason: '''
expected: $expectedStr
@ -1571,7 +1571,7 @@ actual: $resultStr
}
// Check for symmetry.
result = typeSystem.getGreatestLowerBound(T2, T1);
result = typeSystem.greatestLowerBound(T2, T1);
resultStr = typeString(result);
expect(result, expected, reason: '''
expected: $expectedStr
@ -2132,12 +2132,12 @@ class UpperBound_FunctionTypes_Test extends _BoundsTestBase {
typeFormals: [U],
);
{
final result = typeSystem.getLeastUpperBound(T1, T2);
final result = typeSystem.leastUpperBound(T1, T2);
final resultStr = typeString(result);
expect(resultStr, 'T Function<T extends num>()');
}
{
final result = typeSystem.getLeastUpperBound(T2, T1);
final result = typeSystem.leastUpperBound(T2, T1);
final resultStr = typeString(result);
expect(resultStr, 'U Function<U extends num>()');
}
@ -2260,8 +2260,8 @@ class UpperBound_InterfaceTypes_Test extends _BoundsTestBase {
var bNoneNone = bTypeNoneElement(NullabilitySuffix.none);
void assertLUB(DartType type1, DartType type2, DartType expected) {
expect(typeSystem.getLeastUpperBound(type1, type2), expected);
expect(typeSystem.getLeastUpperBound(type2, type1), expected);
expect(typeSystem.leastUpperBound(type1, type2), expected);
expect(typeSystem.leastUpperBound(type2, type1), expected);
}
assertLUB(bStarQuestion, aQuestion, aQuestion);
@ -2340,8 +2340,8 @@ class UpperBound_InterfaceTypes_Test extends _BoundsTestBase {
var aNone = interfaceTypeNone(aElement);
void assertLUB(DartType type1, DartType type2, DartType expected) {
expect(typeSystem.getLeastUpperBound(type1, type2), expected);
expect(typeSystem.getLeastUpperBound(type2, type1), expected);
expect(typeSystem.leastUpperBound(type1, type2), expected);
expect(typeSystem.leastUpperBound(type2, type1), expected);
}
assertLUB(aQuestion, aQuestion, aQuestion);
@ -2498,8 +2498,8 @@ class UpperBound_InterfaceTypes_Test extends _BoundsTestBase {
var cStarNone = cTypeElementStar(NullabilitySuffix.none);
void assertLUB(DartType type1, DartType type2, DartType expected) {
expect(typeSystem.getLeastUpperBound(type1, type2), expected);
expect(typeSystem.getLeastUpperBound(type2, type1), expected);
expect(typeSystem.leastUpperBound(type1, type2), expected);
expect(typeSystem.leastUpperBound(type2, type1), expected);
}
assertLUB(bNoneQuestion, cNoneQuestion, aQuestion);
@ -3678,7 +3678,7 @@ class _BoundsTestBase extends AbstractTypeSystemTest with StringTypes {
void _checkLeastUpperBound(DartType T1, DartType T2, DartType expected) {
var expectedStr = typeString(expected);
var result = typeSystem.getLeastUpperBound(T1, T2);
var result = typeSystem.leastUpperBound(T1, T2);
var resultStr = typeString(result);
expect(result, expected, reason: '''
expected: $expectedStr
@ -3690,7 +3690,7 @@ actual: $resultStr
expect(typeSystem.isSubtypeOf(T2, result), true);
// Check for symmetry.
result = typeSystem.getLeastUpperBound(T2, T1);
result = typeSystem.leastUpperBound(T2, T1);
resultStr = typeString(result);
expect(result, expected, reason: '''
expected: $expectedStr

View file

@ -701,7 +701,7 @@ class MigrationResolutionHooksImpl
} else {
_flowAnalysis!.asExpression_end(node, contextType);
var glb = _fixBuilder._typeSystem
.getGreatestLowerBound(contextType, expressionType);
.greatestLowerBound(contextType, expressionType);
if (glb != _fixBuilder._typeSystem.typeProvider.neverType &&
!identical(glb, expressionType)) {