mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:21:21 +00:00
[cfe] Implement subtype relation for ExtensionType
Change-Id: I725c6abd4ad2ec7fe217e271fbe60d57af443f7a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196933 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
6a7aaf5bc3
commit
cc621431f9
|
@ -38,6 +38,9 @@ class ExtendedClass;
|
|||
class ExtendedGenericClass<X>;
|
||||
extension Extension on ExtendedClass;
|
||||
extension GenericExtension<Y> on ExtendedGenericClass<Y>;
|
||||
extension TopExtension on dynamic;
|
||||
extension GenericTopExtension<Z> on dynamic;
|
||||
class ExtendedSubclass extends ExtendedClass;
|
||||
""";
|
||||
|
||||
const String expectedSdk = """
|
||||
|
@ -89,10 +92,16 @@ class ExtendedClass extends self::Object {
|
|||
}
|
||||
class ExtendedGenericClass<X extends self::Object? = dynamic> extends self::Object {
|
||||
}
|
||||
class ExtendedSubclass extends self::ExtendedClass {
|
||||
}
|
||||
extension Extension on self::ExtendedClass {
|
||||
}
|
||||
extension GenericExtension<Y extends self::Object? = dynamic> on self::ExtendedGenericClass<Y%> {
|
||||
}
|
||||
extension TopExtension on dynamic {
|
||||
}
|
||||
extension GenericTopExtension<Z extends self::Object? = dynamic> on dynamic {
|
||||
}
|
||||
""";
|
||||
|
||||
Component parseSdk(Uri uri, TypeParserEnvironment environment) {
|
||||
|
|
|
@ -1042,5 +1042,32 @@ abstract class SubtypeTest<T, E> {
|
|||
isSubtype("List<int?>?", "List<int?>?");
|
||||
isSubtype("T & int?", "T & int?", typeParameters: "T extends Object?");
|
||||
isSubtype("T? & int?", "T? & int?", typeParameters: "T extends Object");
|
||||
|
||||
// Tests for extension types.
|
||||
isSubtype("Never", "Extension");
|
||||
isSubtype("Never", "GenericExtension<Never>");
|
||||
isSubtype("Extension", "dynamic");
|
||||
isSubtype("Extension", "void");
|
||||
isSubtype("Extension", "Object?");
|
||||
isSubtype("Extension", "FutureOr<dynamic>");
|
||||
isSubtype("GenericExtension<dynamic>", "dynamic");
|
||||
isSubtype("GenericExtension<dynamic>", "void");
|
||||
isSubtype("GenericExtension<dynamic>", "Object?");
|
||||
isSubtype("GenericExtension<dynamic>", "FutureOr<dynamic>");
|
||||
isSubtype("dynamic", "TopExtension");
|
||||
isSubtype("void", "TopExtension");
|
||||
isSubtype("Object?", "TopExtension");
|
||||
isSubtype("FutureOr<dynamic>", "TopExtension");
|
||||
isSubtype("num", "TopExtension");
|
||||
isSubtype("dynamic", "GenericTopExtension<String>");
|
||||
isSubtype("void", "GenericTopExtension<String>");
|
||||
isSubtype("Object?", "GenericTopExtension<String>");
|
||||
isSubtype("FutureOr<dynamic>", "GenericTopExtension<String>");
|
||||
isSubtype("num", "GenericTopExtension<String>");
|
||||
isNotSubtype("Extension", "ExtendedClass");
|
||||
isNotSubtype("GenericExtension<num>", "ExtendedGenericClass<num>");
|
||||
isSubtype("ExtendedClass", "Extension");
|
||||
isSubtype("ExtendedGenericClass<num>", "GenericExtension<num>");
|
||||
isSubtype("ExtendedSubclass", "Extension");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/extension_types/issue45775.dart:10:13: Error: A value of type 'Foo' can't be assigned to a variable of type 'Bar'.
|
||||
// - 'Foo' is from 'pkg/front_end/testcases/extension_types/issue45775.dart'.
|
||||
// Bar bar = Foo();
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
|
@ -18,8 +10,5 @@ class Foo extends core::Object {
|
|||
extension Bar on self::Foo {
|
||||
}
|
||||
static method main() → void {
|
||||
self::Bar bar = let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/issue45775.dart:10:13: Error: A value of type 'Foo' can't be assigned to a variable of type 'Bar'.
|
||||
- 'Foo' is from 'pkg/front_end/testcases/extension_types/issue45775.dart'.
|
||||
Bar bar = Foo();
|
||||
^" in new self::Foo::•() as{TypeError,ForNonNullableByDefault} self::Bar;
|
||||
self::Bar bar = new self::Foo::•();
|
||||
}
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/extension_types/issue45775.dart:10:13: Error: A value of type 'Foo' can't be assigned to a variable of type 'Bar'.
|
||||
// - 'Foo' is from 'pkg/front_end/testcases/extension_types/issue45775.dart'.
|
||||
// Bar bar = Foo();
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
|
@ -18,8 +10,5 @@ class Foo extends core::Object {
|
|||
extension Bar on self::Foo {
|
||||
}
|
||||
static method main() → void {
|
||||
self::Bar bar = let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/issue45775.dart:10:13: Error: A value of type 'Foo' can't be assigned to a variable of type 'Bar'.
|
||||
- 'Foo' is from 'pkg/front_end/testcases/extension_types/issue45775.dart'.
|
||||
Bar bar = Foo();
|
||||
^" in new self::Foo::•() as{TypeError,ForNonNullableByDefault} self::Bar;
|
||||
self::Bar bar = new self::Foo::•();
|
||||
}
|
||||
|
|
|
@ -447,7 +447,6 @@ class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
|
|||
@override
|
||||
IsSubtypeOf isExtensionRelated(
|
||||
ExtensionType s, InterfaceType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +627,6 @@ class IsFunctionSubtypeOf extends TypeRelation<FunctionType> {
|
|||
|
||||
@override
|
||||
IsSubtypeOf isExtensionRelated(ExtensionType s, FunctionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
}
|
||||
|
@ -715,7 +713,6 @@ class IsTypeParameterSubtypeOf extends TypeRelation<TypeParameterType> {
|
|||
@override
|
||||
IsSubtypeOf isExtensionRelated(
|
||||
ExtensionType s, TypeParameterType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
}
|
||||
|
@ -767,8 +764,7 @@ class IsTypedefSubtypeOf extends TypeRelation<TypedefType> {
|
|||
|
||||
@override
|
||||
IsSubtypeOf isExtensionRelated(ExtensionType s, TypedefType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -900,8 +896,9 @@ class IsFutureOrSubtypeOf extends TypeRelation<FutureOrType> {
|
|||
|
||||
@override
|
||||
IsSubtypeOf isExtensionRelated(ExtensionType s, FutureOrType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
// Rule 11.
|
||||
return types.performNullabilityAwareSubtypeCheck(
|
||||
s, t.typeArgument.withDeclaredNullability(t.nullability));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -966,7 +963,6 @@ class IsIntersectionSubtypeOf extends TypeRelation<TypeParameterType> {
|
|||
@override
|
||||
IsSubtypeOf isExtensionRelated(
|
||||
ExtensionType s, TypeParameterType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
}
|
||||
|
@ -1022,7 +1018,6 @@ class IsNullTypeSubtypeOf implements TypeRelation<NullType> {
|
|||
|
||||
@override
|
||||
IsSubtypeOf isExtensionRelated(ExtensionType s, NullType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
}
|
||||
|
@ -1077,7 +1072,6 @@ class IsNeverTypeSubtypeOf implements TypeRelation<NeverType> {
|
|||
|
||||
@override
|
||||
IsSubtypeOf isExtensionRelated(ExtensionType s, NeverType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
}
|
||||
|
@ -1087,62 +1081,54 @@ class IsExtensionTypeSubtypeOf implements TypeRelation<ExtensionType> {
|
|||
|
||||
@override
|
||||
IsSubtypeOf isDynamicRelated(DynamicType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isVoidRelated(VoidType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isInterfaceRelated(
|
||||
InterfaceType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isIntersectionRelated(
|
||||
TypeParameterType intersection, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(intersection, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isFunctionRelated(FunctionType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isFutureOrRelated(FutureOrType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isTypeParameterRelated(
|
||||
TypeParameterType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isTypedefRelated(TypedefType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
return const IsSubtypeOf.never();
|
||||
return types.performNullabilityAwareSubtypeCheck(s, t.onType);
|
||||
}
|
||||
|
||||
@override
|
||||
IsSubtypeOf isExtensionRelated(
|
||||
ExtensionType s, ExtensionType t, Types types) {
|
||||
// TODO(dmitryas): Use with the actual subtyping rules for extension types.
|
||||
if (s.extension != t.extension) {
|
||||
return const IsSubtypeOf.never();
|
||||
}
|
||||
// TODO(dmitryas): Check if subtyping or mutual subtyping should be used.
|
||||
return types
|
||||
.areTypeArgumentsOfSubtypeKernel(
|
||||
s.typeArguments, t.typeArguments, t.extension.typeParameters)
|
||||
|
|
|
@ -327,6 +327,9 @@ class _KernelFromParsedType implements Visitor<Node, TypeParserEnvironment> {
|
|||
} else if (declaration is Typedef) {
|
||||
return new TypedefType(declaration,
|
||||
interpretParsedNullability(node.parsedNullability), kernelArguments);
|
||||
} else if (declaration is Extension) {
|
||||
return new ExtensionType(declaration,
|
||||
interpretParsedNullability(node.parsedNullability), kernelArguments);
|
||||
} else {
|
||||
throw "Unhandled ${declaration.runtimeType}";
|
||||
}
|
||||
|
@ -380,7 +383,7 @@ class _KernelFromParsedType implements Visitor<Node, TypeParserEnvironment> {
|
|||
..addAll(parameters);
|
||||
{
|
||||
TypeParserEnvironment environment = parameterEnvironment.environment;
|
||||
InterfaceType onType =
|
||||
DartType onType =
|
||||
node.onType?.accept<Node, TypeParserEnvironment>(this, environment);
|
||||
ext.onType = onType;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue