[cfe] Add calls to isExtensionRelated to subtype implementation
Closes #45775.
Bug: https://github.com/dart-lang/sdk/issues/45775
Change-Id: Ibffdd24b1a691b2149323dbc984c0d3ae7134c25
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196120
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/testcases/extension_types/extension_on_nullable.dart b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart
new file mode 100644
index 0000000..ea57240
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2021, 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.
+
+class A {}
+
+extension E on A? {
+ void foo() {}
+}
+
+bar(E e) => e.foo();
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.strong.expect b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.strong.expect
new file mode 100644
index 0000000..3074033
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.strong.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+extension E on self::A? {
+ method foo = self::E|foo;
+ tearoff foo = self::E|get#foo;
+}
+static method E|foo(lowered final self::A? #this) → void {}
+static method E|get#foo(lowered final self::A? #this) → () → void
+ return () → void => self::E|foo(#this);
+static method bar(self::E e) → dynamic
+ return self::E|foo(e);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.textual_outline.expect
new file mode 100644
index 0000000..37161fe
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A {}
+
+extension E on A? {
+ void foo() {}
+}
+
+bar(E e) => e.foo();
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a6cd4d8
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+bar(E e) => e.foo();
+
+class A {}
+
+extension E on A? {
+ void foo() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.weak.expect b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.weak.expect
new file mode 100644
index 0000000..3074033
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.weak.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+extension E on self::A? {
+ method foo = self::E|foo;
+ tearoff foo = self::E|get#foo;
+}
+static method E|foo(lowered final self::A? #this) → void {}
+static method E|get#foo(lowered final self::A? #this) → () → void
+ return () → void => self::E|foo(#this);
+static method bar(self::E e) → dynamic
+ return self::E|foo(e);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.weak.outline.expect
new file mode 100644
index 0000000..c897d7f
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/extension_on_nullable.dart.weak.outline.expect
@@ -0,0 +1,20 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+}
+extension E on self::A? {
+ method foo = self::E|foo;
+ tearoff foo = self::E|get#foo;
+}
+static method E|foo(lowered final self::A? #this) → void
+ ;
+static method E|get#foo(lowered final self::A? #this) → () → void
+ return () → void => self::E|foo(#this);
+static method bar(self::E e) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extension_types/issue45775.dart b/pkg/front_end/testcases/extension_types/issue45775.dart
new file mode 100644
index 0000000..012fff6
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue45775.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2021, 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.
+
+class Foo {}
+
+extension Bar on Foo {}
+
+void main() {
+ Bar bar = Foo();
+}
diff --git a/pkg/front_end/testcases/extension_types/issue45775.dart.strong.expect b/pkg/front_end/testcases/extension_types/issue45775.dart.strong.expect
new file mode 100644
index 0000000..f5b3d09
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue45775.dart.strong.expect
@@ -0,0 +1,25 @@
+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;
+
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ : super 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;
+}
diff --git a/pkg/front_end/testcases/extension_types/issue45775.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/issue45775.dart.textual_outline.expect
new file mode 100644
index 0000000..a30a73d
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue45775.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+class Foo {}
+
+extension Bar on Foo {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extension_types/issue45775.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/issue45775.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a30a73d
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue45775.dart.textual_outline_modelled.expect
@@ -0,0 +1,5 @@
+class Foo {}
+
+extension Bar on Foo {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extension_types/issue45775.dart.weak.expect b/pkg/front_end/testcases/extension_types/issue45775.dart.weak.expect
new file mode 100644
index 0000000..f5b3d09
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue45775.dart.weak.expect
@@ -0,0 +1,25 @@
+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;
+
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ : super 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;
+}
diff --git a/pkg/front_end/testcases/extension_types/issue45775.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/issue45775.dart.weak.outline.expect
new file mode 100644
index 0000000..621635e
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue45775.dart.weak.outline.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ ;
+}
+extension Bar on self::Foo {
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index dc7cac2..b9f3dfa 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE.md file.
const_functions/const_functions_const_factory: VerificationError
+extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index c0d86e6..6403bd3 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -6,6 +6,8 @@
# Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
# strong-mode enabled.
+extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
+extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 6b0b79c..c8b4bc7 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,6 +6,8 @@
# the round trip for Kernel textual serialization where the initial binary
# Kernel files are produced by compiling Dart code via Fasta.
+extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
+extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 9af0078..865813b 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -10,6 +10,8 @@
general/error_recovery/issue_39058.crash: SemiFuzzFailure
regress/utf_16_le_content.crash: SemiFuzzCrash
+extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
+extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/kernel/lib/src/types.dart b/pkg/kernel/lib/src/types.dart
index 550417c..47c4b89 100644
--- a/pkg/kernel/lib/src/types.dart
+++ b/pkg/kernel/lib/src/types.dart
@@ -112,6 +112,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else if (t is FunctionType) {
const IsFunctionSubtypeOf relation = const IsFunctionSubtypeOf();
@@ -131,6 +133,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else if (t is TypeParameterType) {
if (t.promotedBound == null) {
@@ -152,6 +156,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else {
const IsIntersectionSubtypeOf relation =
@@ -172,6 +178,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
}
} else if (t is TypedefType) {
@@ -192,6 +200,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else if (t is FutureOrType) {
const IsFutureOrSubtypeOf relation = const IsFutureOrSubtypeOf();
@@ -211,6 +221,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else if (t is NullType) {
const IsNullTypeSubtypeOf relation = const IsNullTypeSubtypeOf();
@@ -230,6 +242,8 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else if (t is NeverType) {
const IsNeverTypeSubtypeOf relation = const IsNeverTypeSubtypeOf();
@@ -249,6 +263,30 @@
return relation.isTypedefRelated(s, t, this);
} else if (s is FutureOrType) {
return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
+ }
+ } else if (t is ExtensionType) {
+ const IsExtensionTypeSubtypeOf relation =
+ const IsExtensionTypeSubtypeOf();
+ if (s is DynamicType) {
+ return relation.isDynamicRelated(s, t, this);
+ } else if (s is VoidType) {
+ return relation.isVoidRelated(s, t, this);
+ } else if (s is InterfaceType) {
+ return relation.isInterfaceRelated(s, t, this);
+ } else if (s is FunctionType) {
+ return relation.isFunctionRelated(s, t, this);
+ } else if (s is TypeParameterType) {
+ return s.promotedBound == null
+ ? relation.isTypeParameterRelated(s, t, this)
+ : relation.isIntersectionRelated(s, t, this);
+ } else if (s is TypedefType) {
+ return relation.isTypedefRelated(s, t, this);
+ } else if (s is FutureOrType) {
+ return relation.isFutureOrRelated(s, t, this);
+ } else if (s is ExtensionType) {
+ return relation.isExtensionRelated(s, t, this);
}
} else {
throw "Unhandled type: ${t.runtimeType}";