mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 14:32:24 +00:00
Use promotedBound for TypeParameterType promotion.
Change-Id: I217a8b9140f60d4f6a9ffc052564388c24c1a7ff Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136100 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
999eeea5a3
commit
21e944f1bc
12 changed files with 577 additions and 770 deletions
|
@ -10,7 +10,6 @@ import 'package:analyzer/dart/element/type.dart';
|
|||
import 'package:analyzer/src/dart/element/display_string_builder.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/type_algebra.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
|
||||
import 'package:analyzer/src/generated/java_engine.dart';
|
||||
|
@ -1016,82 +1015,6 @@ class TopLevelVariableMember extends VariableMember
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type parameter defined inside of another parameterized type, where the
|
||||
* values of the enclosing type parameters are known.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* class C<T> {
|
||||
* S m<S extends T>(S s);
|
||||
* }
|
||||
*
|
||||
* If we have `C<num>.m` and we ask for the type parameter "S", we should get
|
||||
* `<S extends num>` instead of `<S extends T>`. This is how the parameter
|
||||
* and return types work, see: [FunctionType.parameters],
|
||||
* [FunctionType.returnType], and [ParameterMember].
|
||||
*/
|
||||
class TypeParameterMember extends Member implements TypeParameterElement {
|
||||
DartType _bound;
|
||||
DartType _type;
|
||||
|
||||
TypeParameterMember(TypeParameterElement declaration,
|
||||
MapSubstitution substitution, this._bound)
|
||||
: super(declaration, substitution, false) {
|
||||
_type = TypeParameterTypeImpl(
|
||||
element: this,
|
||||
nullabilitySuffix: NullabilitySuffix.star,
|
||||
);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
@override
|
||||
TypeParameterElement get baseElement => declaration;
|
||||
|
||||
@override
|
||||
DartType get bound => _bound;
|
||||
|
||||
@override
|
||||
TypeParameterElement get declaration =>
|
||||
super.declaration as TypeParameterElement;
|
||||
|
||||
@override
|
||||
Element get enclosingElement => declaration.enclosingElement;
|
||||
|
||||
@override
|
||||
int get hashCode => declaration.hashCode;
|
||||
|
||||
@override
|
||||
TypeParameterType get type => _type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other is TypeParameterMember) {
|
||||
return declaration == other.declaration;
|
||||
}
|
||||
return declaration == other;
|
||||
}
|
||||
|
||||
@override
|
||||
T accept<T>(ElementVisitor<T> visitor) =>
|
||||
visitor.visitTypeParameterElement(this);
|
||||
|
||||
@override
|
||||
void appendTo(ElementDisplayStringBuilder builder) {
|
||||
builder.writeTypeParameter(this);
|
||||
}
|
||||
|
||||
@override
|
||||
TypeParameterType instantiate({
|
||||
@required NullabilitySuffix nullabilitySuffix,
|
||||
}) {
|
||||
return TypeParameterTypeImpl(
|
||||
element: this,
|
||||
nullabilitySuffix: nullabilitySuffix,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable element defined in a parameterized type where the values of the
|
||||
* type parameters are known.
|
||||
|
|
|
@ -6,7 +6,6 @@ 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/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/type_algebra.dart';
|
||||
import 'package:analyzer/src/dart/element/type_provider.dart';
|
||||
|
@ -234,11 +233,18 @@ class NormalizeHelper {
|
|||
return (S as TypeImpl).withNullability(NullabilitySuffix.star);
|
||||
}
|
||||
|
||||
/// NORM(X extends T)
|
||||
/// NORM(X & T)
|
||||
DartType _typeParameterType(TypeParameterType T) {
|
||||
/// NORM(X extends T)
|
||||
DartType _typeParameterType(TypeParameterTypeImpl T) {
|
||||
var element = T.element;
|
||||
|
||||
// NORM(X & T)
|
||||
if (T.promotedBound != null) {
|
||||
// let S be NORM(T)
|
||||
var S = _normalize(T.promotedBound);
|
||||
return _typeParameterType_promoted(element, S);
|
||||
}
|
||||
|
||||
var bound = element.bound;
|
||||
if (bound == null) {
|
||||
return T;
|
||||
|
@ -258,18 +264,18 @@ class NormalizeHelper {
|
|||
return NeverTypeImpl.instance;
|
||||
}
|
||||
|
||||
if (element is TypeParameterMember) {
|
||||
return _typeParameterType_promoted(element, S);
|
||||
} else {
|
||||
// NORM(X extends T)
|
||||
// * else X
|
||||
return T;
|
||||
}
|
||||
// else X extends T
|
||||
return T;
|
||||
}
|
||||
|
||||
/// NORM(X & T)
|
||||
/// * let S be NORM(T)
|
||||
DartType _typeParameterType_promoted(TypeParameterMember X, DartType S) {
|
||||
DartType _typeParameterType_promoted(TypeParameterElement X, DartType S) {
|
||||
// * if S is Never then Never
|
||||
if (identical(S, NeverTypeImpl.instance)) {
|
||||
return NeverTypeImpl.instance;
|
||||
}
|
||||
|
||||
// * if S is a top type then X
|
||||
if (typeSystem.isTop(S)) {
|
||||
return X.declaration.instantiate(
|
||||
|
@ -301,13 +307,10 @@ class NormalizeHelper {
|
|||
}
|
||||
|
||||
// * else X & S
|
||||
var promoted = TypeParameterMember(
|
||||
X.declaration,
|
||||
Substitution.empty,
|
||||
S,
|
||||
);
|
||||
return promoted.instantiate(
|
||||
return TypeParameterTypeImpl(
|
||||
element: X.declaration,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
promotedBound: S,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2040,6 +2040,12 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
|||
@override
|
||||
final NullabilitySuffix nullabilitySuffix;
|
||||
|
||||
/// An optional promoted bound on the type parameter.
|
||||
///
|
||||
/// 'null' indicates that the type parameter's bound has not been promoted and
|
||||
/// is therefore the same as the bound of [element].
|
||||
final DartType promotedBound;
|
||||
|
||||
/**
|
||||
* Initialize a newly created type parameter type to be declared by the given
|
||||
* [element] and to have the given name.
|
||||
|
@ -2047,10 +2053,12 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
|||
TypeParameterTypeImpl({
|
||||
@required TypeParameterElement element,
|
||||
@required this.nullabilitySuffix,
|
||||
this.promotedBound,
|
||||
}) : super(element);
|
||||
|
||||
@override
|
||||
DartType get bound => element.bound ?? DynamicTypeImpl.instance;
|
||||
DartType get bound =>
|
||||
promotedBound ?? element.bound ?? DynamicTypeImpl.instance;
|
||||
|
||||
@override
|
||||
ElementLocation get definition => element.location;
|
||||
|
@ -2077,22 +2085,7 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the same declaration, or the same promoted element.
|
||||
if (identical(other.element, element)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the same declaration, but one or both are promoted.
|
||||
if (identical(other.element.declaration, element.declaration)) {
|
||||
return other.bound == bound;
|
||||
}
|
||||
|
||||
// The rare case when we have equal, but not the same declarations.
|
||||
// This happens when we create fresh elements, when new library context.
|
||||
// Type promotion works only locally, where we have same declarations.
|
||||
// So, there is no need to check bounds.
|
||||
return true;
|
||||
return other.promotedBound == promotedBound;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -2111,6 +2104,10 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
|||
|
||||
@override
|
||||
DartType resolveToBound(DartType objectType) {
|
||||
if (promotedBound != null) {
|
||||
return promotedBound;
|
||||
}
|
||||
|
||||
if (element.bound == null) {
|
||||
return objectType;
|
||||
}
|
||||
|
@ -2184,6 +2181,7 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
|||
return TypeParameterTypeImpl(
|
||||
element: element,
|
||||
nullabilitySuffix: nullabilitySuffix,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import 'package:analyzer/dart/element/type_system.dart' as public;
|
|||
import 'package:analyzer/error/listener.dart' show ErrorReporter;
|
||||
import 'package:analyzer/src/dart/element/display_string_builder.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
|
||||
import 'package:analyzer/src/dart/element/normalize.dart';
|
||||
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
|
||||
import 'package:analyzer/src/dart/element/runtime_type_equality.dart';
|
||||
|
@ -973,9 +972,16 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
|
||||
// BOTTOM(X&T) is true iff BOTTOM(T)
|
||||
// BOTTOM(X extends T) is true iff BOTTOM(T)
|
||||
if (type is TypeParameterType) {
|
||||
var T = type.element.bound;
|
||||
return isBottom(T);
|
||||
if (type is TypeParameterTypeImpl) {
|
||||
var T = type.promotedBound;
|
||||
if (T != null) {
|
||||
return isBottom(T);
|
||||
}
|
||||
|
||||
T = type.element.bound;
|
||||
if (T != null) {
|
||||
return isBottom(T);
|
||||
}
|
||||
}
|
||||
|
||||
// BOTTOM(T) is false otherwise
|
||||
|
@ -1049,28 +1055,31 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
}
|
||||
|
||||
// Type parameters.
|
||||
if (T is TypeParameterType && S is TypeParameterType) {
|
||||
if (T is TypeParameterTypeImpl && S is TypeParameterTypeImpl) {
|
||||
// We have eliminated the possibility that T_nullability or S_nullability
|
||||
// is anything except none by this point.
|
||||
assert(T_nullability == NullabilitySuffix.none);
|
||||
assert(S_nullability == NullabilitySuffix.none);
|
||||
var T_element = T.element;
|
||||
var S_element = S.element;
|
||||
|
||||
// MOREBOTTOM(X&T, Y&S) = MOREBOTTOM(T, S)
|
||||
if (T_element is TypeParameterMember &&
|
||||
S_element is TypeParameterMember) {
|
||||
var T_bound = T_element.bound;
|
||||
var S_bound = S_element.bound;
|
||||
return isMoreBottom(T_bound, S_bound);
|
||||
var T_promotedBound = T.promotedBound;
|
||||
var S_promotedBound = S.promotedBound;
|
||||
if (T_promotedBound != null && S_promotedBound != null) {
|
||||
return isMoreBottom(T_promotedBound, S_promotedBound);
|
||||
}
|
||||
|
||||
// MOREBOTTOM(X&T, S) = true
|
||||
if (T_element is TypeParameterMember) {
|
||||
if (T_promotedBound != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// MOREBOTTOM(T, Y&S) = false
|
||||
if (S_element is TypeParameterMember) {
|
||||
if (S_promotedBound != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MOREBOTTOM(X extends T, Y extends S) = MOREBOTTOM(T, S)
|
||||
var T_bound = T_element.bound;
|
||||
var S_bound = S_element.bound;
|
||||
|
@ -1282,11 +1291,17 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
// * if `T0` is an unpromoted type variable with bound `B`,
|
||||
// then `T0 <: T1` iff `B <: Object`.
|
||||
// * if `T0` is a promoted type variable `X & S`,
|
||||
// then `T0 <: T1`iff `S <: Object`.
|
||||
// then `T0 <: T1` iff `S <: Object`.
|
||||
if (T0_nullability == NullabilitySuffix.none &&
|
||||
T0 is TypeParameterTypeImpl) {
|
||||
var bound = T0.element.bound ?? objectQuestion;
|
||||
return isSubtypeOf2(bound, objectNone);
|
||||
var S = T0.promotedBound;
|
||||
var B = T0.element.bound;
|
||||
if (S == null && B != null) {
|
||||
return isSubtypeOf2(B, objectNone);
|
||||
}
|
||||
if (S != null) {
|
||||
return isSubtypeOf2(S, objectNone);
|
||||
}
|
||||
}
|
||||
// * if `T0` is `FutureOr<S>` for some `S`,
|
||||
// then `T0 <: T1` iff `S <: Object`
|
||||
|
@ -1376,21 +1391,24 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
return isSubtypeOf2(S0, T1) && isSubtypeOf2(nullNone, T1);
|
||||
}
|
||||
|
||||
// Type Variable Reflexivity 1: if T0 is a type variable X0 or a promoted
|
||||
// type variables X0 & S0 and T1 is X0 then:
|
||||
// * T0 <: T1
|
||||
if (T0 is TypeParameterTypeImpl &&
|
||||
T1 is TypeParameterTypeImpl &&
|
||||
T1.promotedBound == null &&
|
||||
T0.element == T1.element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Right Promoted Variable: if `T1` is a promoted type variable `X1 & S1`:
|
||||
// * `T0 <: T1` iff `T0 <: X1` and `T0 <: S1`
|
||||
if (T0 is TypeParameterTypeImpl) {
|
||||
if (T1 is TypeParameterTypeImpl && T0.definition == T1.definition) {
|
||||
var S0 = T0.element.bound ?? objectQuestion;
|
||||
var S1 = T1.element.bound ?? objectQuestion;
|
||||
if (isSubtypeOf2(S0, S1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var T0_element = T0.element;
|
||||
if (T0_element is TypeParameterMember) {
|
||||
return isSubtypeOf2(T0_element.bound, T1);
|
||||
}
|
||||
if (T1 is TypeParameterTypeImpl && T1.promotedBound != null) {
|
||||
var X1 = TypeParameterTypeImpl(
|
||||
element: T1.element,
|
||||
nullabilitySuffix: T1.nullabilitySuffix,
|
||||
);
|
||||
return isSubtypeOf2(T0, X1) && isSubtypeOf2(T0, T1.promotedBound);
|
||||
}
|
||||
|
||||
// Right FutureOr: if `T1` is `FutureOr<S1>` then:
|
||||
|
@ -1414,8 +1432,12 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
// * or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
|
||||
// * or `T0` is `X0 & S0` and `S0 <: T1`
|
||||
if (T0 is TypeParameterTypeImpl) {
|
||||
var S0 = T0.element.bound ?? objectQuestion;
|
||||
if (isSubtypeOf2(S0, T1)) {
|
||||
var S0 = T0.promotedBound;
|
||||
if (S0 != null && isSubtypeOf2(S0, T1)) {
|
||||
return true;
|
||||
}
|
||||
var B0 = T0.element.bound;
|
||||
if (B0 != null && isSubtypeOf2(B0, T1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1438,8 +1460,14 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
// or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
|
||||
// or `T0` is `X0 & S0` and `S0 <: T1`
|
||||
if (T0 is TypeParameterTypeImpl) {
|
||||
var S0 = T0.element.bound ?? objectQuestion;
|
||||
return isSubtypeOf2(S0, T1);
|
||||
var S0 = T0.promotedBound;
|
||||
if (S0 != null && isSubtypeOf2(S0, T1)) {
|
||||
return true;
|
||||
}
|
||||
var B0 = T0.element.bound;
|
||||
if (B0 != null && isSubtypeOf2(B0, T1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// iff
|
||||
return false;
|
||||
|
@ -1457,8 +1485,13 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
// Left Type Variable Bound: `T0` is a type variable `X0` with bound `B0`
|
||||
// * and `B0 <: T1`
|
||||
if (T0 is TypeParameterTypeImpl) {
|
||||
var S0 = T0.element.bound ?? objectQuestion;
|
||||
if (isSubtypeOf2(S0, T1)) {
|
||||
var S0 = T0.promotedBound;
|
||||
if (S0 != null && isSubtypeOf2(S0, T1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var B0 = T0.element.bound;
|
||||
if (B0 != null && isSubtypeOf2(B0, T1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1604,9 +1637,10 @@ class Dart2TypeSystem extends TypeSystem {
|
|||
if (from is TypeParameterType) {
|
||||
if (isSubtypeOf2(to, from.bound ?? DynamicTypeImpl.instance)) {
|
||||
var declaration = from.element.declaration;
|
||||
var newElement = TypeParameterMember(declaration, null, to);
|
||||
return newElement.instantiate(
|
||||
return TypeParameterTypeImpl(
|
||||
element: declaration,
|
||||
nullabilitySuffix: from.nullabilitySuffix,
|
||||
promotedBound: to,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3564,32 +3598,29 @@ abstract class TypeSystem implements public.TypeSystem {
|
|||
|
||||
if (type is TypeParameterTypeImpl) {
|
||||
var element = type.element;
|
||||
var promotedBound =
|
||||
promoteToNonNull(element.bound ?? typeProvider.objectType);
|
||||
var identicalBound = identical(promotedBound, element.bound);
|
||||
if (identicalBound) {
|
||||
if (type.nullabilitySuffix == NullabilitySuffix.none) {
|
||||
return type;
|
||||
} else {
|
||||
return TypeParameterTypeImpl(
|
||||
element: element,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Note: we need to use `element.declaration` because `element` might
|
||||
// itself be a TypeParameterMember (due to a previous promotion), and
|
||||
// you can't create a TypeParameterMember wrapping a
|
||||
// TypeParameterMember.
|
||||
|
||||
// NonNull(X & T) = X & NonNull(T)
|
||||
if (type.promotedBound != null) {
|
||||
var promotedBound = promoteToNonNull(type.promotedBound);
|
||||
return TypeParameterTypeImpl(
|
||||
element: TypeParameterMember(
|
||||
element.declaration,
|
||||
null,
|
||||
promotedBound,
|
||||
),
|
||||
element: element,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
// NonNull(X) = X & NonNull(B), where B is the bound of X
|
||||
var promotedBound = element.bound != null
|
||||
? promoteToNonNull(element.bound)
|
||||
: typeProvider.objectType;
|
||||
if (identical(promotedBound, element.bound)) {
|
||||
promotedBound = null;
|
||||
}
|
||||
return TypeParameterTypeImpl(
|
||||
element: element,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
return (type as TypeImpl).withNullability(NullabilitySuffix.none);
|
||||
|
|
|
@ -7,7 +7,6 @@ import 'package:analyzer/dart/element/nullability_suffix.dart';
|
|||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/dart/element/type_provider.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/resolver/variance.dart';
|
||||
import 'package:analyzer/src/generated/utilities_dart.dart';
|
||||
|
@ -473,12 +472,49 @@ mixin ElementsTypesMixin {
|
|||
return parameter;
|
||||
}
|
||||
|
||||
TypeParameterMember promoteTypeParameter(
|
||||
TypeParameterTypeImpl promotedTypeParameterType({
|
||||
@required TypeParameterElement element,
|
||||
@required NullabilitySuffix nullabilitySuffix,
|
||||
@required DartType promotedBound,
|
||||
}) {
|
||||
return TypeParameterTypeImpl(
|
||||
element: element,
|
||||
nullabilitySuffix: nullabilitySuffix,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
TypeParameterTypeImpl promotedTypeParameterTypeNone(
|
||||
TypeParameterElement element,
|
||||
DartType bound,
|
||||
DartType promotedBound,
|
||||
) {
|
||||
assert(element is! TypeParameterMember);
|
||||
return TypeParameterMember(element, null, bound);
|
||||
return promotedTypeParameterType(
|
||||
element: element,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
TypeParameterTypeImpl promotedTypeParameterTypeQuestion(
|
||||
TypeParameterElement element,
|
||||
DartType promotedBound,
|
||||
) {
|
||||
return promotedTypeParameterType(
|
||||
element: element,
|
||||
nullabilitySuffix: NullabilitySuffix.question,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
TypeParameterTypeImpl promotedTypeParameterTypeStar(
|
||||
TypeParameterElement element,
|
||||
DartType promotedBound,
|
||||
) {
|
||||
return promotedTypeParameterType(
|
||||
element: element,
|
||||
nullabilitySuffix: NullabilitySuffix.star,
|
||||
promotedBound: promotedBound,
|
||||
);
|
||||
}
|
||||
|
||||
ParameterElement requiredParameter({
|
||||
|
|
|
@ -13,7 +13,6 @@ import 'package:analyzer/error/listener.dart';
|
|||
import 'package:analyzer/src/dart/analysis/session.dart';
|
||||
import 'package:analyzer/src/dart/ast/token.dart' show KeywordToken;
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/resolver/variance.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
|
@ -3326,13 +3325,12 @@ class TryPromoteToTest extends AbstractTypeSystemTest {
|
|||
|
||||
test_typeParameter() {
|
||||
void check(
|
||||
TypeParameterType type,
|
||||
TypeParameterElement expectedDeclaration,
|
||||
TypeParameterTypeImpl type,
|
||||
TypeParameterElement expectedElement,
|
||||
DartType expectedBound,
|
||||
) {
|
||||
var actualElement = type.element as TypeParameterMember;
|
||||
expect(actualElement.declaration, expectedDeclaration);
|
||||
expect(actualElement.bound, expectedBound);
|
||||
expect(type.element, expectedElement);
|
||||
expect(type.promotedBound, expectedBound);
|
||||
}
|
||||
|
||||
var T = typeParameter('T');
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:analyzer/dart/element/element.dart';
|
|||
import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/analysis/testing_data.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/util/ast_data_extractor.dart';
|
||||
|
||||
|
@ -73,10 +72,11 @@ class _TypePromotionDataInterpreter implements DataInterpreter<DartType> {
|
|||
|
||||
@override
|
||||
String getText(DartType actualData) {
|
||||
if (actualData is TypeParameterType) {
|
||||
if (actualData is TypeParameterTypeImpl) {
|
||||
var element = actualData.element;
|
||||
if (element is TypeParameterMember) {
|
||||
return '${element.name} & ${_typeToString(element.bound)}';
|
||||
var promotedBound = actualData.promotedBound;
|
||||
if (promotedBound != null) {
|
||||
return '${element.name} & ${_typeToString(promotedBound)}';
|
||||
}
|
||||
}
|
||||
return _typeToString(actualData);
|
||||
|
|
|
@ -7,7 +7,6 @@ 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_provider.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/type_visitor.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
|
||||
|
@ -415,51 +414,45 @@ class NormalizeTypeTest with ElementsTypesMixin {
|
|||
|
||||
// * if S is Never then Never
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, neverNone),
|
||||
),
|
||||
promotedTypeParameterTypeNone(T, neverNone),
|
||||
neverNone,
|
||||
);
|
||||
|
||||
// * if S is a top type then X
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, objectQuestion),
|
||||
),
|
||||
promotedTypeParameterTypeNone(T, objectQuestion),
|
||||
typeParameterTypeNone(T),
|
||||
);
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, futureOrQuestion(objectNone)),
|
||||
),
|
||||
promotedTypeParameterTypeNone(T, futureOrQuestion(objectNone)),
|
||||
typeParameterTypeNone(T),
|
||||
);
|
||||
|
||||
// * if S is X then X
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, typeParameterTypeNone(T)),
|
||||
),
|
||||
promotedTypeParameterTypeNone(T, typeParameterTypeNone(T)),
|
||||
typeParameterTypeNone(T),
|
||||
);
|
||||
|
||||
// * if S is Object and NORM(B) is Object where B is the bound of X then X
|
||||
T = typeParameter('T', bound: objectNone);
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, futureOrNone(objectNone)),
|
||||
),
|
||||
promotedTypeParameterTypeNone(T, futureOrNone(objectNone)),
|
||||
typeParameterTypeNone(T),
|
||||
);
|
||||
|
||||
// else X & S
|
||||
T = typeParameter('T');
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, futureOrNone(neverNone)),
|
||||
promotedTypeParameterType(
|
||||
element: T,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
promotedBound: futureOrNone(neverNone),
|
||||
),
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(T, futureNone(neverNone)),
|
||||
promotedTypeParameterType(
|
||||
element: T,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
promotedBound: futureNone(neverNone),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -517,24 +510,7 @@ T2: ${_typeString(T2 as TypeImpl)}
|
|||
var typeParameterCollector = _TypeParameterCollector();
|
||||
DartTypeVisitor.visit(type, typeParameterCollector);
|
||||
for (var typeParameter in typeParameterCollector.typeParameters) {
|
||||
if (typeParameter is TypeParameterMember) {
|
||||
var base = typeParameter.declaration;
|
||||
var baseBound = base.bound;
|
||||
if (baseBound != null) {
|
||||
var baseBoundStr = baseBound.getDisplayString(withNullability: true);
|
||||
typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
|
||||
}
|
||||
|
||||
var bound = typeParameter.bound;
|
||||
var boundStr = bound.getDisplayString(withNullability: true);
|
||||
typeStr += ', ${typeParameter.name} & ' + boundStr;
|
||||
} else {
|
||||
var bound = typeParameter.bound;
|
||||
if (bound != null) {
|
||||
var boundStr = bound.getDisplayString(withNullability: true);
|
||||
typeStr += ', ${typeParameter.name} extends ' + boundStr;
|
||||
}
|
||||
}
|
||||
typeStr += ', $typeParameter';
|
||||
}
|
||||
return typeStr;
|
||||
}
|
||||
|
@ -547,7 +523,7 @@ T2: ${_typeString(T2 as TypeImpl)}
|
|||
}
|
||||
|
||||
class _TypeParameterCollector extends DartTypeVisitor<void> {
|
||||
final Set<TypeParameterElement> typeParameters = {};
|
||||
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
|
||||
|
@ -590,7 +566,31 @@ class _TypeParameterCollector extends DartTypeVisitor<void> {
|
|||
@override
|
||||
void visitTypeParameterType(TypeParameterType type) {
|
||||
if (!functionTypeParameters.contains(type.element)) {
|
||||
typeParameters.add(type.element);
|
||||
var bound = type.element.bound;
|
||||
var promotedBound = (type as TypeParameterTypeImpl).promotedBound;
|
||||
|
||||
if (bound == null && promotedBound == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var str = '';
|
||||
|
||||
if (bound != null) {
|
||||
var boundStr = bound.getDisplayString(withNullability: true);
|
||||
str += '${type.element.name} extends ' + boundStr;
|
||||
}
|
||||
|
||||
if (promotedBound != null) {
|
||||
var promotedBoundStr = promotedBound.getDisplayString(
|
||||
withNullability: true,
|
||||
);
|
||||
if (str.isNotEmpty) {
|
||||
str += ', ';
|
||||
}
|
||||
str += '${type.element.name} & ' + promotedBoundStr;
|
||||
}
|
||||
|
||||
typeParameters.add(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ 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_provider.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
@ -572,58 +572,137 @@ class PromoteToNonNullTest extends _NullableBase {
|
|||
_check(nullStar, neverNone);
|
||||
}
|
||||
|
||||
test_typeParameter_noneBound() {
|
||||
test_typeParameter_bound_dynamic() {
|
||||
var element = typeParameter('T', bound: dynamicNone);
|
||||
|
||||
var result = typeSystem.promoteToNonNull(
|
||||
typeParameterTypeNone(element),
|
||||
) as TypeParameterTypeImpl;
|
||||
expect(result.element, same(element));
|
||||
expect(result.promotedBound, isNull);
|
||||
expect(result.nullabilitySuffix, NullabilitySuffix.none);
|
||||
}
|
||||
|
||||
test_typeParameter_bound_none() {
|
||||
var element = typeParameter('T', bound: intNone);
|
||||
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeNone(element),
|
||||
baseElement: element,
|
||||
element: element,
|
||||
promotedBound: null,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeQuestion(element),
|
||||
baseElement: element,
|
||||
element: element,
|
||||
promotedBound: null,
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_nullBound() {
|
||||
test_typeParameter_bound_null() {
|
||||
var element = typeParameter('T', bound: null);
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeNone(element),
|
||||
baseElement: element,
|
||||
expectedBound: objectNone,
|
||||
element: element,
|
||||
promotedBound: objectNone,
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_questionBound() {
|
||||
test_typeParameter_bound_question() {
|
||||
var element = typeParameter('T', bound: intQuestion);
|
||||
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeNone(element),
|
||||
baseElement: element,
|
||||
expectedBound: intNone,
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeQuestion(element),
|
||||
baseElement: element,
|
||||
expectedBound: intNone,
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeStar(element),
|
||||
baseElement: element,
|
||||
expectedBound: intNone,
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_starBound() {
|
||||
test_typeParameter_bound_star() {
|
||||
var element = typeParameter('T', bound: intStar);
|
||||
|
||||
_checkTypeParameter(
|
||||
typeParameterTypeNone(element),
|
||||
baseElement: element,
|
||||
expectedBound: intNone,
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_promotedBound_none() {
|
||||
var element = typeParameter('T', bound: numQuestion);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeNone(element, intNone),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeQuestion(element, intNone),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeStar(element, intNone),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_promotedBound_question() {
|
||||
var element = typeParameter('T', bound: numQuestion);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeNone(element, intQuestion),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeQuestion(element, intQuestion),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeStar(element, intQuestion),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_promotedBound_star() {
|
||||
var element = typeParameter('T', bound: numQuestion);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeNone(element, intStar),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeQuestion(element, intStar),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
|
||||
_checkTypeParameter(
|
||||
promotedTypeParameterTypeStar(element, intStar),
|
||||
element: element,
|
||||
promotedBound: intNone,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -636,22 +715,14 @@ class PromoteToNonNullTest extends _NullableBase {
|
|||
expect(result, expected);
|
||||
}
|
||||
|
||||
/// If [expectedBound] is `null`, the element of the result must be the same
|
||||
/// as the [baseElement]. Otherwise the element of the result must be a
|
||||
/// [TypeParameterMember] with the [baseElement] and the [expectedBound].
|
||||
void _checkTypeParameter(
|
||||
TypeParameterType type, {
|
||||
@required TypeParameterElement baseElement,
|
||||
DartType expectedBound,
|
||||
@required TypeParameterElement element,
|
||||
@required DartType promotedBound,
|
||||
}) {
|
||||
var actual = typeSystem.promoteToNonNull(type);
|
||||
if (expectedBound != null) {
|
||||
var actualMember = actual.element as TypeParameterMember;
|
||||
expect(actualMember.declaration, same(baseElement));
|
||||
expect(actualMember.bound, expectedBound);
|
||||
} else {
|
||||
expect(actual.element, same(baseElement));
|
||||
}
|
||||
var actual = typeSystem.promoteToNonNull(type) as TypeParameterTypeImpl;
|
||||
expect(actual.element, same(element));
|
||||
expect(actual.promotedBound, promotedBound);
|
||||
expect(actual.nullabilitySuffix, NullabilitySuffix.none);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,6 @@
|
|||
import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
|
@ -48,95 +47,6 @@ class TypeParameterElementTest extends _TypeParameterElementBase {
|
|||
expect(T1 == T2, isFalse);
|
||||
expect(T2 == T1, isFalse);
|
||||
}
|
||||
|
||||
test_equal_elementMember_sameBase_differentBounds() {
|
||||
var T = typeParameter('T');
|
||||
_setEnclosingElement(T);
|
||||
|
||||
var M = TypeParameterMember(T, null, typeProvider.intType);
|
||||
|
||||
expect(_equal(T, M), isTrue);
|
||||
expect(_equal(M, T), isTrue);
|
||||
}
|
||||
|
||||
test_equal_elementMember_sameBase_equalBounds() {
|
||||
var T = typeParameter('T', bound: typeProvider.intType);
|
||||
_setEnclosingElement(T);
|
||||
|
||||
var M = TypeParameterMember(T, null, typeProvider.intType);
|
||||
|
||||
expect(_equal(T, M), isTrue);
|
||||
expect(_equal(M, T), isTrue);
|
||||
}
|
||||
|
||||
test_equal_memberMember2_differentBase() {
|
||||
var T1 = typeParameter('T');
|
||||
var T2 = typeParameter('T');
|
||||
|
||||
var M1 = TypeParameterMember(T1, null, typeProvider.numType);
|
||||
var M2 = TypeParameterMember(T2, null, typeProvider.numType);
|
||||
|
||||
expect(M1 == M2, isFalse);
|
||||
}
|
||||
|
||||
test_equal_memberMember2_sameBase_differentBounds() {
|
||||
var T = typeParameter('T');
|
||||
|
||||
var M1 = TypeParameterMember(T, null, typeProvider.intType);
|
||||
var M2 = TypeParameterMember(T, null, typeProvider.doubleType);
|
||||
|
||||
expect(M1 == M2, isTrue);
|
||||
}
|
||||
|
||||
test_equal_memberMember2_sameBase_equalBounds() {
|
||||
var T = typeParameter('T');
|
||||
|
||||
var M1 = TypeParameterMember(T, null, typeProvider.numType);
|
||||
var M2 = TypeParameterMember(T, null, typeProvider.numType);
|
||||
|
||||
expect(M1 == M2, isTrue);
|
||||
expect(M2 == M1, isTrue);
|
||||
}
|
||||
|
||||
test_equal_memberMember_differentBase() {
|
||||
var T1 = typeParameter('T1');
|
||||
var T2 = typeParameter('T2');
|
||||
|
||||
_setEnclosingElement(T1);
|
||||
_setEnclosingElement(T2);
|
||||
|
||||
var M1 = TypeParameterMember(T1, null, typeProvider.numType);
|
||||
var M2 = TypeParameterMember(T2, null, typeProvider.numType);
|
||||
|
||||
expect(M1 == M2, isFalse);
|
||||
}
|
||||
|
||||
test_equal_memberMember_sameBase_differentBounds() {
|
||||
var T = typeParameter('T');
|
||||
_setEnclosingElement(T);
|
||||
|
||||
var M1 = TypeParameterMember(T, null, typeProvider.intType);
|
||||
var M2 = TypeParameterMember(T, null, typeProvider.doubleType);
|
||||
|
||||
expect(M1 == M2, isTrue);
|
||||
}
|
||||
|
||||
test_equal_memberMember_sameBase_equalBounds() {
|
||||
var T = typeParameter('T');
|
||||
_setEnclosingElement(T);
|
||||
|
||||
var M1 = TypeParameterMember(T, null, typeProvider.numType);
|
||||
var M2 = TypeParameterMember(T, null, typeProvider.numType);
|
||||
|
||||
expect(M1 == M2, isTrue);
|
||||
expect(M2 == M1, isTrue);
|
||||
}
|
||||
|
||||
/// We use this method to work around the lint for using `==` for values
|
||||
/// that are not of the same type.
|
||||
static bool _equal(a, b) {
|
||||
return a == b;
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
|
@ -178,20 +88,33 @@ class TypeParameterTypeTest extends _TypeParameterElementBase {
|
|||
_assertEqual(typeParameterTypeStar(T1), typeParameterTypeNone(T2), isFalse);
|
||||
}
|
||||
|
||||
test_equal_sameElement_differentBounds() {
|
||||
test_equal_sameElement_promotedBounds() {
|
||||
var T = typeParameter('T');
|
||||
_setEnclosingElement(T);
|
||||
|
||||
var T1 = TypeParameterMember(T, null, typeProvider.intType);
|
||||
var T2 = TypeParameterMember(T, null, typeProvider.doubleType);
|
||||
_assertEqual(
|
||||
promotedTypeParameterTypeNone(T, intNone),
|
||||
promotedTypeParameterTypeNone(T, intNone),
|
||||
isTrue,
|
||||
);
|
||||
|
||||
_assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T1), isTrue);
|
||||
_assertEqual(
|
||||
promotedTypeParameterTypeNone(T, intNone),
|
||||
promotedTypeParameterTypeNone(T, doubleNone),
|
||||
isFalse,
|
||||
);
|
||||
|
||||
_assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isFalse);
|
||||
_assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isFalse);
|
||||
_assertEqual(
|
||||
promotedTypeParameterTypeNone(T, intNone),
|
||||
typeParameterTypeNone(T),
|
||||
isFalse,
|
||||
);
|
||||
|
||||
_assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T), isFalse);
|
||||
_assertEqual(typeParameterTypeNone(T), typeParameterTypeNone(T1), isFalse);
|
||||
_assertEqual(
|
||||
typeParameterTypeNone(T),
|
||||
promotedTypeParameterTypeNone(T, intNone),
|
||||
isFalse,
|
||||
);
|
||||
}
|
||||
|
||||
test_equal_sameElements() {
|
||||
|
|
|
@ -7,7 +7,6 @@ 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_provider.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/type_visitor.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
|
||||
|
@ -112,7 +111,6 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase {
|
|||
|
||||
test_isBottom() {
|
||||
TypeParameterElement T;
|
||||
TypeParameterMember T2;
|
||||
|
||||
// BOTTOM(Never) is true
|
||||
isBottom(neverNone);
|
||||
|
@ -122,15 +120,13 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase {
|
|||
// BOTTOM(X&T) is true iff BOTTOM(T)
|
||||
T = typeParameter('T', bound: objectQuestion);
|
||||
|
||||
T2 = promoteTypeParameter(T, neverNone);
|
||||
isBottom(typeParameterTypeNone(T2));
|
||||
isBottom(typeParameterTypeQuestion(T2));
|
||||
isBottom(typeParameterTypeStar(T2));
|
||||
isBottom(promotedTypeParameterTypeNone(T, neverNone));
|
||||
isBottom(promotedTypeParameterTypeQuestion(T, neverNone));
|
||||
isBottom(promotedTypeParameterTypeStar(T, neverNone));
|
||||
|
||||
T2 = promoteTypeParameter(T, neverQuestion);
|
||||
isNotBottom(typeParameterTypeNone(T2));
|
||||
isNotBottom(typeParameterTypeQuestion(T2));
|
||||
isNotBottom(typeParameterTypeStar(T2));
|
||||
isNotBottom(promotedTypeParameterTypeNone(T, neverQuestion));
|
||||
isNotBottom(promotedTypeParameterTypeQuestion(T, neverQuestion));
|
||||
isNotBottom(promotedTypeParameterTypeStar(T, neverQuestion));
|
||||
|
||||
// BOTTOM(X extends T) is true iff BOTTOM(T)
|
||||
T = typeParameter('T', bound: neverNone);
|
||||
|
@ -165,10 +161,9 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase {
|
|||
isNotBottom(typeParameterTypeQuestion(T));
|
||||
isNotBottom(typeParameterTypeStar(T));
|
||||
|
||||
T2 = promoteTypeParameter(typeParameter('T'), intNone);
|
||||
isNotBottom(typeParameterTypeNone(T2));
|
||||
isNotBottom(typeParameterTypeQuestion(T2));
|
||||
isNotBottom(typeParameterTypeStar(T2));
|
||||
isNotBottom(promotedTypeParameterTypeNone(T, intNone));
|
||||
isNotBottom(promotedTypeParameterTypeQuestion(T, intNone));
|
||||
isNotBottom(promotedTypeParameterTypeStar(T, intNone));
|
||||
}
|
||||
|
||||
test_isMoreBottom() {
|
||||
|
@ -238,27 +233,21 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase {
|
|||
|
||||
// MOREBOTTOM(X&T, Y&S) = MOREBOTTOM(T, S)
|
||||
isMoreBottom(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
promotedTypeParameterTypeNone(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
typeParameterTypeQuestion(
|
||||
promoteTypeParameter(
|
||||
typeParameter('S', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
promotedTypeParameterTypeQuestion(
|
||||
typeParameter('S', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
);
|
||||
|
||||
// MOREBOTTOM(X&T, S) = true
|
||||
isMoreBottom(
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
promotedTypeParameterTypeNone(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
typeParameterTypeNone(
|
||||
typeParameter('S', bound: neverNone),
|
||||
|
@ -270,11 +259,9 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase {
|
|||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: neverNone),
|
||||
),
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('S', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
promotedTypeParameterTypeNone(
|
||||
typeParameter('S', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -573,11 +560,9 @@ class LowerBoundTest extends _BoundsTestBase {
|
|||
}
|
||||
|
||||
{
|
||||
var T = typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
var T = promotedTypeParameterTypeNone(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
);
|
||||
check(T, intNone);
|
||||
check(T, intQuestion);
|
||||
|
@ -601,11 +586,9 @@ class LowerBoundTest extends _BoundsTestBase {
|
|||
|
||||
check(
|
||||
neverNone,
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
promotedTypeParameterTypeNone(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1101,10 +1084,18 @@ class LowerBoundTest extends _BoundsTestBase {
|
|||
|
||||
{
|
||||
var T = typeParameter('T', bound: objectQuestion);
|
||||
var T2 = promoteTypeParameter(T, objectNone);
|
||||
check(typeParameterTypeNone(T), typeParameterTypeNone(T2));
|
||||
check(typeParameterTypeQuestion(T), typeParameterTypeNone(T2));
|
||||
check(typeParameterTypeStar(T), typeParameterTypeNone(T2));
|
||||
check(
|
||||
typeParameterTypeNone(T),
|
||||
promotedTypeParameterTypeNone(T, objectNone),
|
||||
);
|
||||
check(
|
||||
typeParameterTypeQuestion(T),
|
||||
promotedTypeParameterTypeNone(T, objectNone),
|
||||
);
|
||||
check(
|
||||
typeParameterTypeStar(T),
|
||||
promotedTypeParameterTypeNone(T, objectNone),
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1300,8 +1291,8 @@ actual: $resultStr
|
|||
|
||||
// Check that the result is a lower bound.
|
||||
if (checkSubtype) {
|
||||
expect(typeSystem.isSubtypeOf(result, T1), true);
|
||||
expect(typeSystem.isSubtypeOf(result, T2), true);
|
||||
expect(typeSystem.isSubtypeOf2(result, T1), true);
|
||||
expect(typeSystem.isSubtypeOf2(result, T2), true);
|
||||
}
|
||||
|
||||
// Check for symmetry.
|
||||
|
@ -1349,11 +1340,9 @@ class UpperBoundTest extends _BoundsTestBase {
|
|||
}
|
||||
|
||||
{
|
||||
var T = typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
var T = promotedTypeParameterTypeNone(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
);
|
||||
check(T, intNone);
|
||||
check(T, intQuestion);
|
||||
|
@ -1377,11 +1366,9 @@ class UpperBoundTest extends _BoundsTestBase {
|
|||
|
||||
check(
|
||||
neverNone,
|
||||
typeParameterTypeNone(
|
||||
promoteTypeParameter(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
promotedTypeParameterTypeNone(
|
||||
typeParameter('T', bound: objectQuestion),
|
||||
neverNone,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -2063,8 +2050,8 @@ actual: $resultStr
|
|||
''');
|
||||
|
||||
// Check that the result is an upper bound.
|
||||
expect(typeSystem.isSubtypeOf(T1, result), true);
|
||||
expect(typeSystem.isSubtypeOf(T2, result), true);
|
||||
expect(typeSystem.isSubtypeOf2(T1, result), true);
|
||||
expect(typeSystem.isSubtypeOf2(T2, result), true);
|
||||
|
||||
// Check for symmetry.
|
||||
result = typeSystem.getLeastUpperBound(T2, T1);
|
||||
|
@ -2150,24 +2137,7 @@ class _BoundsTestBase with ElementsTypesMixin {
|
|||
var typeParameterCollector = _TypeParameterCollector();
|
||||
DartTypeVisitor.visit(type, typeParameterCollector);
|
||||
for (var typeParameter in typeParameterCollector.typeParameters) {
|
||||
if (typeParameter is TypeParameterMember) {
|
||||
var base = typeParameter.declaration;
|
||||
var baseBound = base.bound;
|
||||
if (baseBound != null) {
|
||||
var baseBoundStr = baseBound.getDisplayString(withNullability: true);
|
||||
typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
|
||||
}
|
||||
|
||||
var bound = typeParameter.bound;
|
||||
var boundStr = bound.getDisplayString(withNullability: true);
|
||||
typeStr += ', ${typeParameter.name} & ' + boundStr;
|
||||
} else {
|
||||
var bound = typeParameter.bound;
|
||||
if (bound != null) {
|
||||
var boundStr = bound.getDisplayString(withNullability: true);
|
||||
typeStr += ', ${typeParameter.name} extends ' + boundStr;
|
||||
}
|
||||
}
|
||||
typeStr += ', $typeParameter';
|
||||
}
|
||||
return typeStr;
|
||||
}
|
||||
|
@ -2180,7 +2150,7 @@ class _BoundsTestBase with ElementsTypesMixin {
|
|||
}
|
||||
|
||||
class _TypeParameterCollector extends DartTypeVisitor<void> {
|
||||
final Set<TypeParameterElement> typeParameters = {};
|
||||
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
|
||||
|
@ -2223,7 +2193,31 @@ class _TypeParameterCollector extends DartTypeVisitor<void> {
|
|||
@override
|
||||
void visitTypeParameterType(TypeParameterType type) {
|
||||
if (!functionTypeParameters.contains(type.element)) {
|
||||
typeParameters.add(type.element);
|
||||
var bound = type.element.bound;
|
||||
var promotedBound = (type as TypeParameterTypeImpl).promotedBound;
|
||||
|
||||
if (bound == null && promotedBound == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var str = '';
|
||||
|
||||
if (bound != null) {
|
||||
var boundStr = bound.getDisplayString(withNullability: true);
|
||||
str += '${type.element.name} extends ' + boundStr;
|
||||
}
|
||||
|
||||
if (promotedBound != null) {
|
||||
var promotedBoundStr = promotedBound.getDisplayString(
|
||||
withNullability: true,
|
||||
);
|
||||
if (str.isNotEmpty) {
|
||||
str += ', ';
|
||||
}
|
||||
str += '${type.element.name} & ' + promotedBoundStr;
|
||||
}
|
||||
|
||||
typeParameters.add(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue