Revert "Implement UP for RecordType(s)."
This reverts commit cccc959dd40a119188a01d2c288f5353b3223d5c.
Reason for revert: Breaks Google3 (blaze doesn't support circular dependencies, see b/242614028).
Original change's description:
> Implement UP for RecordType(s).
>
> Change-Id: I9960fbdc5cadbd600ad2ae5c9991b83852c428d9
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255143
> Reviewed-by: Samuel Rawlins <srawlins@google.com>
> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
TBR=scheglov@google.com,brianwilkerson@google.com,srawlins@google.com
Change-Id: Id573d10446c8d966ba96fa1c47d6134388139816
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255241
Reviewed-by: Alexander Thomas <athom@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Ilya Yanok <yanok@google.com>
Commit-Queue: Ilya Yanok <yanok@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index 076b037..e6447f4 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -710,21 +710,6 @@
return getLeastUpperBound(T1, _typeSystem.objectNone);
}
- // Record types.
- if (T1 is RecordTypeImpl && T2 is RecordTypeImpl) {
- return _recordType(T1, T2);
- }
-
- // UP(RecordType, T2) = UP(Object, T2)
- if (T1 is RecordTypeImpl) {
- return getLeastUpperBound(_typeSystem.objectNone, T2);
- }
-
- // UP(T1, RecordType) = UP(T1, Object)
- if (T2 is RecordTypeImpl) {
- return getLeastUpperBound(T1, _typeSystem.objectNone);
- }
-
var futureOrResult = _futureOr(T1, T2);
if (futureOrResult != null) {
return futureOrResult;
@@ -911,45 +896,6 @@
return _typeSystem.getGreatestLowerBound(a.type, b.type);
}
- DartType _recordType(RecordTypeImpl T1, RecordTypeImpl T2) {
- final positional1 = T1.positionalFields;
- final positional2 = T2.positionalFields;
- if (positional1.length != positional2.length) {
- return _typeSystem.typeProvider.recordType;
- }
-
- final named1 = T1.namedFields;
- final named2 = T2.namedFields;
- if (named1.length != named2.length) {
- return _typeSystem.typeProvider.recordType;
- }
-
- final fieldTypes = <DartType>[];
-
- for (var i = 0; i < positional1.length; i++) {
- final field1 = positional1[i];
- final field2 = positional2[i];
- final type = getLeastUpperBound(field1.type, field2.type);
- fieldTypes.add(type);
- }
-
- for (var i = 0; i < named1.length; i++) {
- final field1 = named1[i];
- final field2 = named2[i];
- if (field1.name != field2.name) {
- return _typeSystem.typeProvider.recordType;
- }
- final type = getLeastUpperBound(field1.type, field2.type);
- fieldTypes.add(type);
- }
-
- return RecordTypeImpl(
- element2: T1.element2,
- fieldTypes: fieldTypes,
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
/// Return the promoted or declared bound of the type parameter.
DartType _typeParameterBound(TypeParameterTypeImpl type) {
var bound = type.promotedBound ?? type.element2.bound;
diff --git a/pkg/analyzer/lib/src/dart/element/type_provider.dart b/pkg/analyzer/lib/src/dart/element/type_provider.dart
index d313754..a16dcb9 100644
--- a/pkg/analyzer/lib/src/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_provider.dart
@@ -142,7 +142,6 @@
InterfaceType? _numType;
InterfaceType? _numTypeQuestion;
InterfaceType? _objectType;
- InterfaceType? _recordType;
InterfaceType? _stackTraceType;
InterfaceType? _streamDynamicType;
InterfaceType? _stringType;
@@ -397,13 +396,6 @@
return _recordElement ??= _getClassElement(_coreLibrary, 'Record');
}
- InterfaceType get recordType {
- return _recordType ??= recordElement.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
@override
ClassElement get setElement {
return _setElement ??= _getClassElement(_coreLibrary, 'Set');
diff --git a/pkg/analyzer/test/src/dart/element/string_types.dart b/pkg/analyzer/test/src/dart/element/string_types.dart
deleted file mode 100644
index b346f81..0000000
--- a/pkg/analyzer/test/src/dart/element/string_types.dart
+++ /dev/null
@@ -1,766 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_visitor.dart';
-import 'package:test/test.dart';
-
-import '../../../generated/type_system_test.dart';
-
-mixin StringTypes on AbstractTypeSystemTest {
- final Map<String, DartType> _types = {};
-
- void assertExpectedString(DartType type, String? expectedString) {
- if (expectedString != null) {
- var typeStr = _typeStr(type);
-
- typeStr += _typeParametersStr(type);
-
- expect(typeStr, expectedString);
- }
- }
-
- void defineStringTypes() {
- _defineType('dynamic', dynamicNone);
- _defineType('void', voidNone);
-
- _defineType('Never', neverNone);
- _defineType('Never*', neverStar);
- _defineType('Never?', neverQuestion);
-
- _defineType('Null?', nullQuestion);
-
- _defineType('Object', objectNone);
- _defineType('Object*', objectStar);
- _defineType('Object?', objectQuestion);
-
- _defineType('Comparable<Object*>*', comparableStar(objectStar));
- _defineType('Comparable<num*>*', comparableStar(numStar));
- _defineType('Comparable<int*>*', comparableStar(intStar));
-
- _defineType('num', numNone);
- _defineType('num*', numStar);
- _defineType('num?', numQuestion);
-
- _defineType('int', intNone);
- _defineType('int*', intStar);
- _defineType('int?', intQuestion);
-
- _defineType('double', doubleNone);
- _defineType('double*', doubleStar);
- _defineType('double?', doubleQuestion);
-
- _defineType('List<Object*>*', listStar(objectStar));
- _defineType('List<num*>*', listStar(numStar));
- _defineType('List<int>', listNone(intNone));
- _defineType('List<int>*', listStar(intNone));
- _defineType('List<int>?', listQuestion(intNone));
- _defineType('List<int*>', listNone(intStar));
- _defineType('List<int*>*', listStar(intStar));
- _defineType('List<int*>?', listQuestion(intStar));
- _defineType('List<int?>', listNone(intQuestion));
-
- _defineType(
- 'List<Comparable<Object*>*>*',
- listStar(
- comparableStar(objectStar),
- ),
- );
- _defineType(
- 'List<Comparable<num*>*>*',
- listStar(
- comparableStar(numStar),
- ),
- );
- _defineType(
- 'List<Comparable<Comparable<num*>*>*>*',
- listStar(
- comparableStar(
- comparableStar(numStar),
- ),
- ),
- );
-
- _defineType('Iterable<Object*>*', iterableStar(objectStar));
- _defineType('Iterable<int*>*', iterableStar(intStar));
- _defineType('Iterable<num*>*', iterableStar(numStar));
-
- _defineFunctionTypes();
- _defineFutureTypes();
- _defineRecordTypes();
- }
-
- DartType typeOfString(String str) {
- var type = _types[str];
- if (type == null) {
- fail('No DartType for: $str');
- }
- return type;
- }
-
- void _defineFunctionTypes() {
- _defineType('Function', functionNone);
- _defineType('Function*', functionStar);
- _defineType('Function?', functionQuestion);
-
- _defineType(
- 'void Function()',
- functionTypeNone(
- returnType: voidNone,
- ),
- );
-
- _defineType(
- 'int* Function()',
- functionTypeNone(
- returnType: intStar,
- ),
- );
- _defineType(
- 'int* Function()*',
- functionTypeStar(
- returnType: intStar,
- ),
- );
- _defineType(
- 'int* Function()?',
- functionTypeQuestion(
- returnType: intStar,
- ),
- );
-
- _defineType(
- 'num Function(num)',
- functionTypeNone(
- parameters: [requiredParameter(type: numNone)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num Function(num)?',
- functionTypeQuestion(
- parameters: [requiredParameter(type: numNone)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num Function(num)*',
- functionTypeStar(
- parameters: [requiredParameter(type: numNone)],
- returnType: numNone,
- ),
- );
-
- _defineType(
- 'num* Function(num*)',
- functionTypeNone(
- parameters: [requiredParameter(type: numStar)],
- returnType: numStar,
- ),
- );
- _defineType(
- 'num* Function(num*)*',
- functionTypeStar(
- parameters: [requiredParameter(type: numStar)],
- returnType: numStar,
- ),
- );
- _defineType(
- 'num* Function(num*)?',
- functionTypeQuestion(
- parameters: [requiredParameter(type: numStar)],
- returnType: numStar,
- ),
- );
-
- _defineType(
- 'int* Function(num*)*',
- functionTypeStar(
- parameters: [requiredParameter(type: numStar)],
- returnType: intStar,
- ),
- );
-
- _defineType(
- 'num* Function(int*)',
- functionTypeNone(
- parameters: [requiredParameter(type: intStar)],
- returnType: numStar,
- ),
- );
- _defineType(
- 'num* Function(int*)*',
- functionTypeStar(
- parameters: [requiredParameter(type: intStar)],
- returnType: numStar,
- ),
- );
- _defineType(
- 'num* Function(int*)?',
- functionTypeQuestion(
- parameters: [requiredParameter(type: intStar)],
- returnType: numStar,
- ),
- );
-
- _defineType(
- 'int* Function(int*)*',
- functionTypeStar(
- parameters: [requiredParameter(type: intStar)],
- returnType: intStar,
- ),
- );
-
- _defineType(
- 'num Function(num?)',
- functionTypeNone(
- parameters: [requiredParameter(type: numQuestion)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num? Function(num)',
- functionTypeNone(
- parameters: [requiredParameter(type: numNone)],
- returnType: numQuestion,
- ),
- );
- _defineType(
- 'num? Function(num?)',
- functionTypeNone(
- parameters: [requiredParameter(type: numQuestion)],
- returnType: numQuestion,
- ),
- );
-
- _defineType(
- 'num Function({num x})',
- functionTypeNone(
- parameters: [namedParameter(name: 'x', type: numNone)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num Function({num? x})',
- functionTypeNone(
- parameters: [namedParameter(name: 'x', type: numQuestion)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num? Function({num x})',
- functionTypeNone(
- parameters: [namedParameter(name: 'x', type: numNone)],
- returnType: numQuestion,
- ),
- );
- _defineType(
- 'num? Function({num? x})',
- functionTypeNone(
- parameters: [namedParameter(name: 'x', type: numQuestion)],
- returnType: numQuestion,
- ),
- );
-
- _defineType(
- 'num Function([num])',
- functionTypeNone(
- parameters: [positionalParameter(type: numNone)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num Function([num?])',
- functionTypeNone(
- parameters: [positionalParameter(type: numQuestion)],
- returnType: numNone,
- ),
- );
- _defineType(
- 'num? Function([num])',
- functionTypeNone(
- parameters: [positionalParameter(type: numNone)],
- returnType: numQuestion,
- ),
- );
- _defineType(
- 'num? Function([num?])',
- functionTypeNone(
- parameters: [positionalParameter(type: numQuestion)],
- returnType: numQuestion,
- ),
- );
- }
-
- void _defineFutureTypes() {
- _defineType('FutureOr<Object*>*', futureOrStar(objectStar));
- _defineType('FutureOr<num*>*', futureOrStar(numStar));
- _defineType('FutureOr<int*>*', futureOrStar(intStar));
- _defineType('FutureOr<num?>?', futureOrQuestion(numQuestion));
-
- _defineType('FutureOr<Object>', futureOrNone(objectNone));
- _defineType('FutureOr<Object>?', futureOrQuestion(objectNone));
- _defineType('FutureOr<Object?>', futureOrNone(objectQuestion));
- _defineType('FutureOr<Object?>?', futureOrQuestion(objectQuestion));
-
- _defineType('Future<num>', futureNone(numNone));
- _defineType('Future<num>?', futureQuestion(numNone));
- _defineType('Future<num?>', futureNone(numQuestion));
- _defineType('Future<num?>?', futureQuestion(numQuestion));
-
- _defineType('FutureOr<int>', futureOrNone(intNone));
- _defineType('FutureOr<int>?', futureOrQuestion(intNone));
- _defineType('FutureOr<int?>', futureOrNone(intQuestion));
- _defineType('FutureOr<int?>?', futureOrQuestion(intQuestion));
-
- _defineType('FutureOr<int>*', futureOrStar(intNone));
- _defineType('FutureOr<int*>', futureOrNone(intStar));
- _defineType('Future<int*>*', futureStar(intStar));
-
- _defineType('FutureOr<num>', futureOrNone(numNone));
- _defineType('FutureOr<num>*', futureOrStar(numNone));
- _defineType('FutureOr<num>?', futureOrQuestion(numNone));
-
- _defineType('FutureOr<num*>', futureOrNone(numStar));
- _defineType('FutureOr<num?>', futureOrNone(numQuestion));
-
- _defineType('Future<Object>', futureNone(objectNone));
- _defineType(
- 'FutureOr<Future<Object>>',
- futureOrNone(
- futureNone(objectNone),
- ),
- );
- _defineType(
- 'FutureOr<Future<Object>>?',
- futureOrQuestion(
- futureNone(objectNone),
- ),
- );
- _defineType(
- 'FutureOr<Future<Object>?>',
- futureOrNone(
- futureQuestion(objectNone),
- ),
- );
- _defineType(
- 'FutureOr<Future<Object>?>?',
- futureOrQuestion(
- futureQuestion(objectNone),
- ),
- );
-
- _defineType(
- 'Future<Future<num>>?',
- futureQuestion(
- futureNone(numNone),
- ),
- );
- _defineType(
- 'Future<Future<num?>?>?',
- futureQuestion(
- futureQuestion(numQuestion),
- ),
- );
-
- _defineType(
- 'Future<Future<Future<num>>>?',
- futureQuestion(
- futureNone(
- futureNone(numNone),
- ),
- ),
- );
- _defineType(
- 'Future<Future<Future<num?>?>?>?',
- futureQuestion(
- futureQuestion(
- futureQuestion(numQuestion),
- ),
- ),
- );
-
- _defineType(
- 'FutureOr<FutureOr<FutureOr<num>>?>',
- futureOrNone(
- futureOrQuestion(
- futureOrNone(numNone),
- ),
- ),
- );
- _defineType(
- 'FutureOr<FutureOr<FutureOr<num?>>>',
- futureOrNone(
- futureOrNone(
- futureOrNone(numQuestion),
- ),
- ),
- );
- }
-
- void _defineRecordTypes() {
- _defineType('Record', recordNone);
-
- _defineType(
- '(double)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: doubleNone),
- ],
- ),
- ),
- );
- _defineType(
- '(int)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: intNone),
- ],
- ),
- ),
- );
- _defineType(
- '(num)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: numNone),
- ],
- ),
- ),
- );
-
- _defineType(
- '(double, int)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: doubleNone),
- recordPositionalField(type: intNone),
- ],
- ),
- ),
- );
- _defineType(
- '(int, double)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: intNone),
- recordPositionalField(type: doubleNone),
- ],
- ),
- ),
- );
- _defineType(
- '(int, Object)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: intNone),
- recordPositionalField(type: objectNone),
- ],
- ),
- ),
- );
- _defineType(
- '(int, String)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: intNone),
- recordPositionalField(type: stringNone),
- ],
- ),
- ),
- );
- _defineType(
- '(num, num)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: numNone),
- recordPositionalField(type: numNone),
- ],
- ),
- ),
- );
- _defineType(
- '(num, Object)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: numNone),
- recordPositionalField(type: objectNone),
- ],
- ),
- ),
- );
- _defineType(
- '(num, String)',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: numNone),
- recordPositionalField(type: stringNone),
- ],
- ),
- ),
- );
-
- _defineType(
- '({double f1})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: doubleNone),
- ],
- ),
- ),
- );
- _defineType(
- '({int f1})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: intNone),
- ],
- ),
- ),
- );
- _defineType(
- '({num f1})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: numNone),
- ],
- ),
- ),
- );
- _defineType(
- '({int f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f2', type: intNone),
- ],
- ),
- ),
- );
- _defineType(
- '({double f1, int f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: doubleNone),
- recordNamedField(name: 'f2', type: intNone),
- ],
- ),
- ),
- );
- _defineType(
- '({int f1, double f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: intNone),
- recordNamedField(name: 'f2', type: doubleNone),
- ],
- ),
- ),
- );
- _defineType(
- '({int f1, String f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: intNone),
- recordNamedField(name: 'f2', type: stringNone),
- ],
- ),
- ),
- );
- _defineType(
- '({int f1, Object f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: intNone),
- recordNamedField(name: 'f2', type: objectNone),
- ],
- ),
- ),
- );
- _defineType(
- '({num f1, num f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: numNone),
- recordNamedField(name: 'f2', type: numNone),
- ],
- ),
- ),
- );
- _defineType(
- '({num f1, String f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: numNone),
- recordNamedField(name: 'f2', type: stringNone),
- ],
- ),
- ),
- );
- _defineType(
- '({num f1, Object f2})',
- recordTypeNone(
- element: recordElement(
- namedFields: [
- recordNamedField(name: 'f1', type: numNone),
- recordNamedField(name: 'f2', type: objectNone),
- ],
- ),
- ),
- );
-
- _defineType(
- '(int, {String f2})',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: intNone),
- ],
- namedFields: [
- recordNamedField(name: 'f2', type: stringNone),
- ],
- ),
- ),
- );
- _defineType(
- '(int, {Object f2})',
- recordTypeNone(
- element: recordElement(
- positionalFields: [
- recordPositionalField(type: intNone),
- ],
- namedFields: [
- recordNamedField(name: 'f2', type: objectNone),
- ],
- ),
- ),
- );
- }
-
- void _defineType(String str, DartType type) {
- if (_typeStr(type) != str) {
- fail('Expected: $str\nActual: ${_typeStr(type)}');
- }
-
- for (var entry in _types.entries) {
- var key = entry.key;
- if (key == 'Never' || _typeStr(type) == 'Never') {
- // We have aliases for Never.
- } else {
- var value = entry.value;
- if (key == str) {
- fail('Duplicate type: $str; existing: $value; new: $type');
- }
- if (_typeStr(value) == _typeStr(type)) {
- fail('Duplicate type: $str');
- }
- }
- }
- _types[str] = type;
- }
-
- String _typeParametersStr(DartType type) {
- var typeStr = '';
-
- var typeParameterCollector = _TypeParameterCollector();
- type.accept(typeParameterCollector);
- for (var typeParameter in typeParameterCollector.typeParameters) {
- typeStr += ', $typeParameter';
- }
- return typeStr;
- }
-
- static String _typeStr(DartType type) {
- return type.getDisplayString(withNullability: true);
- }
-}
-
-class _TypeParameterCollector extends TypeVisitor<void> {
- final Set<String> typeParameters = {};
-
- /// We don't need to print bounds for these type parameters, because
- /// they are already included into the function type itself, and cannot
- /// be promoted.
- final Set<TypeParameterElement> functionTypeParameters = {};
-
- @override
- void visitDynamicType(DynamicType type) {}
-
- @override
- void visitFunctionType(FunctionType type) {
- functionTypeParameters.addAll(type.typeFormals);
- for (var typeParameter in type.typeFormals) {
- var bound = typeParameter.bound;
- if (bound != null) {
- bound.accept(this);
- }
- }
- for (var parameter in type.parameters) {
- parameter.type.accept(this);
- }
- type.returnType.accept(this);
- }
-
- @override
- void visitInterfaceType(InterfaceType type) {
- for (var typeArgument in type.typeArguments) {
- typeArgument.accept(this);
- }
- }
-
- @override
- void visitNeverType(NeverType type) {}
-
- @override
- void visitRecordType(RecordType type) {
- final fields = [
- ...type.positionalFields,
- ...type.namedFields,
- ];
- for (final field in fields) {
- field.type.accept(this);
- }
- }
-
- @override
- void visitTypeParameterType(TypeParameterType type) {
- if (!functionTypeParameters.contains(type.element2)) {
- var bound = type.element2.bound;
-
- if (bound == null) {
- return;
- }
-
- var str = '';
-
- var boundStr = bound.getDisplayString(withNullability: true);
- str += '${type.element2.name} extends $boundStr';
-
- typeParameters.add(str);
- }
- }
-
- @override
- void visitVoidType(VoidType type) {}
-}
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index a53a92f..cd2c985 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -5,12 +5,12 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_visitor.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/type_system_test.dart';
-import 'string_types.dart';
main() {
defineReflectiveSuite(() {
@@ -20,7 +20,19 @@
}
@reflectiveTest
-class SubtypeTest extends _SubtypingTestBase with StringTypes {
+class SubtypeTest extends _SubtypingTestBase {
+ final Map<String, DartType> _types = {};
+
+ void assertExpectedString(DartType type, String? expectedString) {
+ if (expectedString != null) {
+ var typeStr = _typeStr(type);
+
+ typeStr += _typeParametersStr(type);
+
+ expect(typeStr, expectedString);
+ }
+ }
+
void isNotSubtype(
DartType T0,
DartType T1, {
@@ -36,8 +48,8 @@
String strT0,
String strT1,
) {
- var T0 = typeOfString(strT0);
- var T1 = typeOfString(strT1);
+ var T0 = _getTypeByStr(strT0);
+ var T1 = _getTypeByStr(strT1);
expect(typeSystem.isSubtypeOf(T0, T1), isFalse);
}
@@ -63,15 +75,15 @@
String strT0,
String strT1,
) {
- var T0 = typeOfString(strT0);
- var T1 = typeOfString(strT1);
+ var T0 = _getTypeByStr(strT0);
+ var T1 = _getTypeByStr(strT1);
expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
}
@override
void setUp() {
super.setUp();
- defineStringTypes();
+ _defineTypes();
}
test_functionType_01() {
@@ -4110,17 +4122,17 @@
}
test_record_functionType() {
- isNotSubtype2('({int f1})', 'void Function()');
+ isNotSubtype2('({int foo})', 'void Function()');
}
test_record_interfaceType() {
- isNotSubtype2('({int f1})', 'int');
- isNotSubtype2('int', '({int f1})');
+ isNotSubtype2('({int foo})', 'int');
+ isNotSubtype2('int', '({int foo})');
}
test_record_Never() {
- isNotSubtype2('({int f1})', 'Never');
- isSubtype2('Never', '({int f1})');
+ isNotSubtype2('({int foo})', 'Never');
+ isSubtype2('Never', '({int foo})');
}
test_record_record2_differentShape() {
@@ -4131,8 +4143,8 @@
check('(int)', '(int, String)');
- check('({int f1, String f2})', '({int f1})');
- check('({int f1})', '({int f2})');
+ check('({int foo, String bar})', '({int foo})');
+ check('({int foo})', '({int bar})');
}
test_record_record2_sameShape_mixed() {
@@ -4141,7 +4153,7 @@
isNotSubtype2(superType, subType);
}
- check('(int, {String f2})', '(int, {Object f2})');
+ check('(int, {String bar})', '(int, {Object bar})');
}
test_record_record2_sameShape_named() {
@@ -4150,12 +4162,12 @@
isNotSubtype2(superType, subType);
}
- check('({int f1})', '({num f1})');
+ check('({int foo})', '({num foo})');
- isSubtype2('({int f1, String f2})', '({int f1, String f2})');
- check('({int f1, String f2})', '({int f1, Object f2})');
- check('({int f1, String f2})', '({num f1, String f2})');
- check('({int f1, String f2})', '({num f1, Object f2})');
+ isSubtype2('({int foo, String bar})', '({int foo, String bar})');
+ check('({int foo, String bar})', '({int foo, Object bar})');
+ check('({int foo, String bar})', '({num foo, String bar})');
+ check('({int foo, String bar})', '({num foo, Object bar})');
}
test_record_record2_sameShape_named_order() {
@@ -4168,20 +4180,20 @@
recordTypeNone(
element: recordElement(
namedFields: [
- recordNamedField(name: 'f1', type: intNone),
- recordNamedField(name: 'f2', type: intNone),
- recordNamedField(name: 'f3', type: intNone),
- recordNamedField(name: 'f4', type: intNone),
+ recordNamedField(name: 'foo01', type: intNone),
+ recordNamedField(name: 'foo02', type: intNone),
+ recordNamedField(name: 'foo03', type: intNone),
+ recordNamedField(name: 'foo04', type: intNone),
],
),
),
recordTypeNone(
element: recordElement(
namedFields: [
- recordNamedField(name: 'f4', type: intNone),
- recordNamedField(name: 'f3', type: intNone),
- recordNamedField(name: 'f2', type: intNone),
- recordNamedField(name: 'f1', type: intNone),
+ recordNamedField(name: 'foo04', type: intNone),
+ recordNamedField(name: 'foo03', type: intNone),
+ recordNamedField(name: 'foo02', type: intNone),
+ recordNamedField(name: 'foo01', type: intNone),
],
),
),
@@ -4203,9 +4215,9 @@
}
test_record_top() {
- isSubtype2('({int f1})', 'dynamic');
- isSubtype2('({int f1})', 'Object');
- isSubtype2('({int f1})', 'Record');
+ isSubtype2('({int foo})', 'dynamic');
+ isSubtype2('({int foo})', 'Object');
+ isSubtype2('({int foo})', 'Record');
}
/// The class `Record` is a subtype of `Object` and `dynamic`, and a
@@ -5324,6 +5336,577 @@
strT1: 'FutureOr<T>, T extends FutureOr<T>',
);
}
+
+ void _defineType(String str, DartType type) {
+ for (var entry in _types.entries) {
+ var key = entry.key;
+ if (key == 'Never' || _typeStr(type) == 'Never') {
+ // We have aliases for Never.
+ } else {
+ var value = entry.value;
+ if (key == str) {
+ fail('Duplicate type: $str; existing: $value; new: $type');
+ }
+ if (_typeStr(value) == _typeStr(type)) {
+ fail('Duplicate type: $str');
+ }
+ }
+ }
+ _types[str] = type;
+ }
+
+ void _defineTypes() {
+ _defineType('dynamic', dynamicNone);
+ _defineType('void', voidNone);
+
+ _defineType('Never', neverNone);
+ _defineType('Never*', neverStar);
+ _defineType('Never?', neverQuestion);
+
+ _defineType('Null?', nullQuestion);
+
+ _defineType('Object', objectNone);
+ _defineType('Object*', objectStar);
+ _defineType('Object?', objectQuestion);
+
+ _defineType('Comparable<Object*>*', comparableStar(objectStar));
+ _defineType('Comparable<num*>*', comparableStar(numStar));
+ _defineType('Comparable<int*>*', comparableStar(intStar));
+
+ _defineType('num', numNone);
+ _defineType('num*', numStar);
+ _defineType('num?', numQuestion);
+
+ _defineType('int', intNone);
+ _defineType('int*', intStar);
+ _defineType('int?', intQuestion);
+
+ _defineType('double', doubleNone);
+ _defineType('double*', doubleStar);
+ _defineType('double?', doubleQuestion);
+
+ _defineType('List<Object*>*', listStar(objectStar));
+ _defineType('List<num*>*', listStar(numStar));
+ _defineType('List<int>', listNone(intNone));
+ _defineType('List<int>*', listStar(intNone));
+ _defineType('List<int>?', listQuestion(intNone));
+ _defineType('List<int*>', listNone(intStar));
+ _defineType('List<int*>*', listStar(intStar));
+ _defineType('List<int*>?', listQuestion(intStar));
+ _defineType('List<int?>', listNone(intQuestion));
+
+ _defineType(
+ 'List<Comparable<Object*>*>*',
+ listStar(
+ comparableStar(objectStar),
+ ),
+ );
+ _defineType(
+ 'List<Comparable<num*>*>*',
+ listStar(
+ comparableStar(numStar),
+ ),
+ );
+ _defineType(
+ 'List<Comparable<Comparable<num*>*>*>*',
+ listStar(
+ comparableStar(
+ comparableStar(numStar),
+ ),
+ ),
+ );
+
+ _defineType('Iterable<Object*>*', iterableStar(objectStar));
+ _defineType('Iterable<int*>*', iterableStar(intStar));
+ _defineType('Iterable<num*>*', iterableStar(numStar));
+
+ _defineType('Function', functionNone);
+ _defineType('Function*', functionStar);
+ _defineType('Function?', functionQuestion);
+
+ _defineType('FutureOr<Object*>*', futureOrStar(objectStar));
+ _defineType('FutureOr<num*>*', futureOrStar(numStar));
+ _defineType('FutureOr<int*>*', futureOrStar(intStar));
+ _defineType('FutureOr<num?>?', futureOrQuestion(numQuestion));
+
+ _defineType('FutureOr<Object>', futureOrNone(objectNone));
+ _defineType('FutureOr<Object>?', futureOrQuestion(objectNone));
+ _defineType('FutureOr<Object?>', futureOrNone(objectQuestion));
+ _defineType('FutureOr<Object?>?', futureOrQuestion(objectQuestion));
+
+ _defineType('Future<num>', futureNone(numNone));
+ _defineType('Future<num>?', futureQuestion(numNone));
+ _defineType('Future<num?>', futureNone(numQuestion));
+ _defineType('Future<num?>?', futureQuestion(numQuestion));
+
+ _defineType('FutureOr<int>', futureOrNone(intNone));
+ _defineType('FutureOr<int>?', futureOrQuestion(intNone));
+ _defineType('FutureOr<int?>', futureOrNone(intQuestion));
+ _defineType('FutureOr<int?>?', futureOrQuestion(intQuestion));
+
+ _defineType('FutureOr<int>*', futureOrStar(intNone));
+ _defineType('FutureOr<int*>', futureOrNone(intStar));
+ _defineType('Future<int*>*', futureStar(intStar));
+
+ _defineType('FutureOr<num>', futureOrNone(numNone));
+ _defineType('FutureOr<num>*', futureOrStar(numNone));
+ _defineType('FutureOr<num>?', futureOrQuestion(numNone));
+
+ _defineType('FutureOr<num*>', futureOrNone(numStar));
+ _defineType('FutureOr<num?>', futureOrNone(numQuestion));
+
+ _defineType('Future<Object>', futureNone(objectNone));
+ _defineType(
+ 'FutureOr<Future<Object>>',
+ futureOrNone(
+ futureNone(objectNone),
+ ),
+ );
+ _defineType(
+ 'FutureOr<Future<Object>>?',
+ futureOrQuestion(
+ futureNone(objectNone),
+ ),
+ );
+ _defineType(
+ 'FutureOr<Future<Object>?>',
+ futureOrNone(
+ futureQuestion(objectNone),
+ ),
+ );
+ _defineType(
+ 'FutureOr<Future<Object>?>?',
+ futureOrQuestion(
+ futureQuestion(objectNone),
+ ),
+ );
+
+ _defineType(
+ 'Future<Future<num>>?',
+ futureQuestion(
+ futureNone(numNone),
+ ),
+ );
+ _defineType(
+ 'Future<Future<num?>?>?',
+ futureQuestion(
+ futureQuestion(numQuestion),
+ ),
+ );
+
+ _defineType(
+ 'Future<Future<Future<num>>>?',
+ futureQuestion(
+ futureNone(
+ futureNone(numNone),
+ ),
+ ),
+ );
+ _defineType(
+ 'Future<Future<Future<num?>?>?>?',
+ futureQuestion(
+ futureQuestion(
+ futureQuestion(numQuestion),
+ ),
+ ),
+ );
+
+ _defineType(
+ 'FutureOr<FutureOr<FutureOr<num>>?>',
+ futureOrNone(
+ futureOrQuestion(
+ futureOrNone(numNone),
+ ),
+ ),
+ );
+ _defineType(
+ 'FutureOr<FutureOr<FutureOr<num?>>>',
+ futureOrNone(
+ futureOrNone(
+ futureOrNone(numQuestion),
+ ),
+ ),
+ );
+
+ _defineType(
+ 'void Function()',
+ functionTypeNone(
+ returnType: voidNone,
+ ),
+ );
+
+ _defineType(
+ 'int* Function()',
+ functionTypeNone(
+ returnType: intStar,
+ ),
+ );
+ _defineType(
+ 'int* Function()*',
+ functionTypeStar(
+ returnType: intStar,
+ ),
+ );
+ _defineType(
+ 'int* Function()?',
+ functionTypeQuestion(
+ returnType: intStar,
+ ),
+ );
+
+ _defineType(
+ 'num Function(num)',
+ functionTypeNone(
+ parameters: [requiredParameter(type: numNone)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num Function(num)?',
+ functionTypeQuestion(
+ parameters: [requiredParameter(type: numNone)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num Function(num)*',
+ functionTypeStar(
+ parameters: [requiredParameter(type: numNone)],
+ returnType: numNone,
+ ),
+ );
+
+ _defineType(
+ 'num* Function(num*)',
+ functionTypeNone(
+ parameters: [requiredParameter(type: numStar)],
+ returnType: numStar,
+ ),
+ );
+ _defineType(
+ 'num* Function(num*)*',
+ functionTypeStar(
+ parameters: [requiredParameter(type: numStar)],
+ returnType: numStar,
+ ),
+ );
+ _defineType(
+ 'num* Function(num*)?',
+ functionTypeQuestion(
+ parameters: [requiredParameter(type: numStar)],
+ returnType: numStar,
+ ),
+ );
+
+ _defineType(
+ 'int* Function(num*)*',
+ functionTypeStar(
+ parameters: [requiredParameter(type: numStar)],
+ returnType: intStar,
+ ),
+ );
+
+ _defineType(
+ 'num* Function(int*)',
+ functionTypeNone(
+ parameters: [requiredParameter(type: intStar)],
+ returnType: numStar,
+ ),
+ );
+ _defineType(
+ 'num* Function(int*)*',
+ functionTypeStar(
+ parameters: [requiredParameter(type: intStar)],
+ returnType: numStar,
+ ),
+ );
+ _defineType(
+ 'num* Function(int*)?',
+ functionTypeQuestion(
+ parameters: [requiredParameter(type: intStar)],
+ returnType: numStar,
+ ),
+ );
+
+ _defineType(
+ 'int* Function(int*)*',
+ functionTypeStar(
+ parameters: [requiredParameter(type: intStar)],
+ returnType: intStar,
+ ),
+ );
+
+ _defineType(
+ 'num Function(num?)',
+ functionTypeNone(
+ parameters: [requiredParameter(type: numQuestion)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num? Function(num)',
+ functionTypeNone(
+ parameters: [requiredParameter(type: numNone)],
+ returnType: numQuestion,
+ ),
+ );
+ _defineType(
+ 'num? Function(num?)',
+ functionTypeNone(
+ parameters: [requiredParameter(type: numQuestion)],
+ returnType: numQuestion,
+ ),
+ );
+
+ _defineType(
+ 'num Function({num x})',
+ functionTypeNone(
+ parameters: [namedParameter(name: 'x', type: numNone)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num Function({num? x})',
+ functionTypeNone(
+ parameters: [namedParameter(name: 'x', type: numQuestion)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num? Function({num x})',
+ functionTypeNone(
+ parameters: [namedParameter(name: 'x', type: numNone)],
+ returnType: numQuestion,
+ ),
+ );
+ _defineType(
+ 'num? Function({num? x})',
+ functionTypeNone(
+ parameters: [namedParameter(name: 'x', type: numQuestion)],
+ returnType: numQuestion,
+ ),
+ );
+
+ _defineType(
+ 'num Function([num])',
+ functionTypeNone(
+ parameters: [positionalParameter(type: numNone)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num Function([num?])',
+ functionTypeNone(
+ parameters: [positionalParameter(type: numQuestion)],
+ returnType: numNone,
+ ),
+ );
+ _defineType(
+ 'num? Function([num])',
+ functionTypeNone(
+ parameters: [positionalParameter(type: numNone)],
+ returnType: numQuestion,
+ ),
+ );
+ _defineType(
+ 'num? Function([num?])',
+ functionTypeNone(
+ parameters: [positionalParameter(type: numQuestion)],
+ returnType: numQuestion,
+ ),
+ );
+
+ _defineType('Record', recordNone);
+ _defineType(
+ '(int, String)',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: intNone),
+ recordPositionalField(type: stringNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '(num, String)',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: numNone),
+ recordPositionalField(type: stringNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '(int, Object)',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: intNone),
+ recordPositionalField(type: objectNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '(num, Object)',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: numNone),
+ recordPositionalField(type: objectNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '(int)',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: intNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '(num)',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: numNone),
+ ],
+ ),
+ ),
+ );
+
+ _defineType(
+ '({int foo})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'foo', type: intNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '({num foo})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'foo', type: numNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '({int bar})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'bar', type: intNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '({int foo, String bar})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'foo', type: intNone),
+ recordNamedField(name: 'bar', type: stringNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '({int foo, Object bar})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'foo', type: intNone),
+ recordNamedField(name: 'bar', type: objectNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '({num foo, String bar})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'foo', type: numNone),
+ recordNamedField(name: 'bar', type: stringNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '({num foo, Object bar})',
+ recordTypeNone(
+ element: recordElement(
+ namedFields: [
+ recordNamedField(name: 'foo', type: numNone),
+ recordNamedField(name: 'bar', type: objectNone),
+ ],
+ ),
+ ),
+ );
+
+ _defineType(
+ '(int, {String bar})',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: intNone),
+ ],
+ namedFields: [
+ recordNamedField(name: 'bar', type: stringNone),
+ ],
+ ),
+ ),
+ );
+ _defineType(
+ '(int, {Object bar})',
+ recordTypeNone(
+ element: recordElement(
+ positionalFields: [
+ recordPositionalField(type: intNone),
+ ],
+ namedFields: [
+ recordNamedField(name: 'bar', type: objectNone),
+ ],
+ ),
+ ),
+ );
+ }
+
+ DartType _getTypeByStr(String str) {
+ var type = _types[str];
+ if (type == null) {
+ fail('No DartType for: $str');
+ }
+ return type;
+ }
+
+ String _typeParametersStr(DartType type) {
+ var typeStr = '';
+
+ var typeParameterCollector = _TypeParameterCollector();
+ type.accept(typeParameterCollector);
+ for (var typeParameter in typeParameterCollector.typeParameters) {
+ typeStr += ', $typeParameter';
+ }
+ return typeStr;
+ }
+
+ static String _typeStr(DartType type) {
+ return type.getDisplayString(withNullability: true);
+ }
}
@reflectiveTest
@@ -5728,3 +6311,72 @@
}
class _SubtypingTestBase extends AbstractTypeSystemTest {}
+
+class _TypeParameterCollector extends TypeVisitor<void> {
+ final Set<String> typeParameters = {};
+
+ /// We don't need to print bounds for these type parameters, because
+ /// they are already included into the function type itself, and cannot
+ /// be promoted.
+ final Set<TypeParameterElement> functionTypeParameters = {};
+
+ @override
+ void visitDynamicType(DynamicType type) {}
+
+ @override
+ void visitFunctionType(FunctionType type) {
+ functionTypeParameters.addAll(type.typeFormals);
+ for (var typeParameter in type.typeFormals) {
+ var bound = typeParameter.bound;
+ if (bound != null) {
+ bound.accept(this);
+ }
+ }
+ for (var parameter in type.parameters) {
+ parameter.type.accept(this);
+ }
+ type.returnType.accept(this);
+ }
+
+ @override
+ void visitInterfaceType(InterfaceType type) {
+ for (var typeArgument in type.typeArguments) {
+ typeArgument.accept(this);
+ }
+ }
+
+ @override
+ void visitNeverType(NeverType type) {}
+
+ @override
+ void visitRecordType(RecordType type) {
+ final fields = [
+ ...type.positionalFields,
+ ...type.namedFields,
+ ];
+ for (final field in fields) {
+ field.type.accept(this);
+ }
+ }
+
+ @override
+ void visitTypeParameterType(TypeParameterType type) {
+ if (!functionTypeParameters.contains(type.element2)) {
+ var bound = type.element2.bound;
+
+ if (bound == null) {
+ return;
+ }
+
+ var str = '';
+
+ var boundStr = bound.getDisplayString(withNullability: true);
+ str += '${type.element2.name} extends $boundStr';
+
+ typeParameters.add(str);
+ }
+ }
+
+ @override
+ void visitVoidType(VoidType type) {}
+}
diff --git a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
index 4231cb3..0cd3424 100644
--- a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
+++ b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
@@ -15,7 +15,6 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/type_system_test.dart';
-import 'string_types.dart';
main() {
defineReflectiveSuite(() {
@@ -23,7 +22,6 @@
defineReflectiveTests(LowerBoundTest);
defineReflectiveTests(UpperBound_FunctionTypes_Test);
defineReflectiveTests(UpperBound_InterfaceTypes_Test);
- defineReflectiveTests(UpperBound_RecordTypes_Test);
defineReflectiveTests(UpperBoundTest);
});
}
@@ -1974,26 +1972,23 @@
);
{
- final T = typeParameter('T', bound: numNone);
- final U = typeParameter('U', bound: numNone);
- final T1 = functionTypeNone(
- returnType: typeParameterTypeNone(T),
- typeFormals: [T],
+ var T = typeParameter('T', bound: numNone);
+ var U = typeParameter('U', bound: numNone);
+ var R = typeParameter('R', bound: numNone);
+ check(
+ functionTypeNone(
+ returnType: typeParameterTypeNone(T),
+ typeFormals: [T],
+ ),
+ functionTypeNone(
+ returnType: typeParameterTypeNone(U),
+ typeFormals: [U],
+ ),
+ functionTypeNone(
+ returnType: typeParameterTypeNone(R),
+ typeFormals: [R],
+ ),
);
- final T2 = functionTypeNone(
- returnType: typeParameterTypeNone(U),
- typeFormals: [U],
- );
- {
- final result = typeSystem.getLeastUpperBound(T1, T2);
- final resultStr = _typeString(result);
- expect(resultStr, 'T Function<T extends num>()');
- }
- {
- final result = typeSystem.getLeastUpperBound(T2, T1);
- final resultStr = _typeString(result);
- expect(resultStr, 'U Function<U extends num>()');
- }
}
}
@@ -2551,84 +2546,6 @@
}
@reflectiveTest
-class UpperBound_RecordTypes_Test extends _BoundsTestBase {
- @override
- void setUp() {
- super.setUp();
- defineStringTypes();
- }
-
- test_differentShape() {
- void check(String T1, String T2) {
- _checkLeastUpperBound2(T1, T2, 'Record');
- }
-
- check('(int)', '(int, String)');
-
- check('({int f1, String f2})', '({int f1})');
- check('({int f1})', '({int f2})');
- }
-
- test_Never() {
- _checkLeastUpperBound2('(int)', 'Never', '(int)');
- }
-
- test_record_andNot() {
- _checkLeastUpperBound2('(int)', 'int', 'Object');
- _checkLeastUpperBound2('(int)', 'void Function()', 'Object');
- }
-
- test_sameShape_named() {
- _checkLeastUpperBound2(
- '({int f1})',
- '({int f1})',
- '({int f1})',
- );
-
- _checkLeastUpperBound2(
- '({int f1})',
- '({num f1})',
- '({num f1})',
- );
-
- _checkLeastUpperBound2(
- '({int f1})',
- '({double f1})',
- '({num f1})',
- );
-
- _checkLeastUpperBound2(
- '({int f1, double f2})',
- '({double f1, int f2})',
- '({num f1, num f2})',
- );
- }
-
- test_sameShape_positional() {
- _checkLeastUpperBound2('(int)', '(int)', '(int)');
- _checkLeastUpperBound2('(int)', '(num)', '(num)');
- _checkLeastUpperBound2('(int)', '(double)', '(num)');
-
- _checkLeastUpperBound2(
- '(int, String)',
- '(int, String)',
- '(int, String)',
- );
-
- _checkLeastUpperBound2(
- '(int, double)',
- '(double, int)',
- '(num, num)',
- );
- }
-
- test_top() {
- _checkLeastUpperBound2('(int)', 'dynamic', 'dynamic');
- _checkLeastUpperBound2('(int)', 'Object?', 'Object?');
- }
-}
-
-@reflectiveTest
class UpperBoundTest extends _BoundsTestBase {
test_bottom_any() {
void check(DartType T1, DartType T2) {
@@ -3422,7 +3339,7 @@
}
@reflectiveTest
-class _BoundsTestBase extends AbstractTypeSystemTest with StringTypes {
+class _BoundsTestBase extends AbstractTypeSystemTest {
void _assertBottom(DartType type) {
if (!typeSystem.isBottom(type)) {
fail('isBottom must be true: ${_typeString(type)}');
@@ -3501,7 +3418,10 @@
var result = typeSystem.getLeastUpperBound(T1, T2);
var resultStr = _typeString(result);
- expect(resultStr, expectedStr);
+ expect(result, expected, reason: '''
+expected: $expectedStr
+actual: $resultStr
+''');
// Check that the result is an upper bound.
expect(typeSystem.isSubtypeOf(T1, result), true);
@@ -3510,15 +3430,10 @@
// Check for symmetry.
result = typeSystem.getLeastUpperBound(T2, T1);
resultStr = _typeString(result);
- expect(resultStr, expectedStr);
- }
-
- void _checkLeastUpperBound2(String T1, String T2, String expected) {
- _checkLeastUpperBound(
- typeOfString(T1),
- typeOfString(T2),
- typeOfString(expected),
- );
+ expect(result, expected, reason: '''
+expected: $expectedStr
+actual: $resultStr
+''');
}
String _typeParametersStr(DartType type) {