mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:49:47 +00:00
analyzer: Tidy up 'proper rename' support
Change-Id: I5edaaa168c17b9c55f1dc942797373c983d70bcc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218781 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
parent
5e990591b9
commit
67ab9b22e5
|
@ -643,7 +643,7 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
|
|||
TypeAliasElement? viaTypeAlias;
|
||||
if (typeElement is TypeAliasElementImpl) {
|
||||
if (constructorFunctionType.typeFormals.isNotEmpty &&
|
||||
!typeElement.isProperRename()) {
|
||||
!typeElement.isProperRename) {
|
||||
// The type alias is not a proper rename of the aliased class, so
|
||||
// the constructor tear-off is distinct from the associated
|
||||
// constructor function of the aliased class.
|
||||
|
|
|
@ -5482,6 +5482,34 @@ class TypeAliasElementImpl extends _ExistingElementImpl
|
|||
CompilationUnitElement get enclosingElement =>
|
||||
super.enclosingElement as CompilationUnitElement;
|
||||
|
||||
/// Returns whether this alias is a "proper rename" of [aliasedClass], as
|
||||
/// defined in the constructor-tearoffs specification.
|
||||
bool get isProperRename {
|
||||
var aliasedType_ = aliasedType;
|
||||
if (aliasedType_ is! InterfaceType) {
|
||||
return false;
|
||||
}
|
||||
var aliasedClass = aliasedType_.element;
|
||||
var typeArguments = aliasedType_.typeArguments;
|
||||
var typeParameterCount = typeParameters.length;
|
||||
if (typeParameterCount != aliasedClass.typeParameters.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < typeParameterCount; i++) {
|
||||
var bound = typeParameters[i].bound ?? library.typeProvider.dynamicType;
|
||||
var aliasedBound = aliasedClass.typeParameters[i].bound ??
|
||||
library.typeProvider.dynamicType;
|
||||
if (!library.typeSystem.isSubtypeOf(bound, aliasedBound) ||
|
||||
!library.typeSystem.isSubtypeOf(aliasedBound, bound)) {
|
||||
return false;
|
||||
}
|
||||
if (typeParameters[i] != typeArguments[i].element) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
ElementKind get kind {
|
||||
if (isNonFunctionTypeAliasesEnabled) {
|
||||
|
@ -5582,37 +5610,6 @@ class TypeAliasElementImpl extends _ExistingElementImpl
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns whether this alias is a "proper rename" of [aliasedClass], as
|
||||
/// defined in the constructor-tearoffs specification.
|
||||
bool isProperRename() {
|
||||
var aliasedType_ = aliasedType;
|
||||
if (aliasedType_ is! InterfaceType) {
|
||||
return false;
|
||||
}
|
||||
var aliasedClass = aliasedType_.element;
|
||||
var typeArguments = aliasedType_.typeArguments;
|
||||
var typeParameterCount = typeParameters.length;
|
||||
if (typeParameterCount != aliasedClass.typeParameters.length) {
|
||||
return false;
|
||||
}
|
||||
if (typeParameterCount != typeArguments.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < typeParameterCount; i++) {
|
||||
var bound = typeParameters[i].bound ?? library.typeProvider.dynamicType;
|
||||
var aliasedBound = aliasedClass.typeParameters[i].bound ??
|
||||
library.typeProvider.dynamicType;
|
||||
if (!library.typeSystem.isSubtypeOf(bound, aliasedBound) ||
|
||||
!library.typeSystem.isSubtypeOf(aliasedBound, bound)) {
|
||||
return false;
|
||||
}
|
||||
if (typeParameters[i] != typeArguments[i].element) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void setLinkedData(Reference reference, ElementLinkedData linkedData) {
|
||||
this.reference = reference;
|
||||
reference.element = this;
|
||||
|
|
|
@ -64,6 +64,18 @@ const a = identical(MyC.new, C.new);
|
|||
);
|
||||
}
|
||||
|
||||
test_identical_constructorReference_aliasIsNotProperRename_differentCount2() async {
|
||||
await resolveTestCode('''
|
||||
class C<T, U> {}
|
||||
typedef MyC<T> = C;
|
||||
const a = identical(MyC.new, C.new);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('a'),
|
||||
_boolValue(false),
|
||||
);
|
||||
}
|
||||
|
||||
test_identical_constructorReference_aliasIsNotProperRename_differentOrder() async {
|
||||
await resolveTestCode('''
|
||||
class C<T, U> {}
|
||||
|
@ -124,7 +136,7 @@ const a = identical(MyC<int>.new, (MyC.new)<int>);
|
|||
);
|
||||
}
|
||||
|
||||
test_identical_constructorReference_aliasIsProperRename_mutualSubtypes() async {
|
||||
test_identical_constructorReference_aliasIsProperRename_mutualSubtypes_dynamic() async {
|
||||
await resolveTestCode('''
|
||||
class C<T> {}
|
||||
typedef MyC<T extends Object?> = C<T>;
|
||||
|
@ -136,6 +148,18 @@ const a = identical(MyC<int>.new, MyC<int>.new);
|
|||
);
|
||||
}
|
||||
|
||||
test_identical_constructorReference_aliasIsProperRename_mutualSubtypes_futureOr() async {
|
||||
await resolveTestCode('''
|
||||
class C<T extends num> {}
|
||||
typedef MyC<T extends FutureOr<num>> = C<T>;
|
||||
const a = identical(MyC<int>.new, MyC<int>.new);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('a'),
|
||||
_boolValue(true),
|
||||
);
|
||||
}
|
||||
|
||||
test_identical_constructorReference_aliasIsProperRename_uninstantiated() async {
|
||||
await resolveTestCode('''
|
||||
class C<T> {}
|
||||
|
|
Loading…
Reference in a new issue