Version 2.15.0-71.0.dev

Merge commit 'b9c4b68f231f61f576f98560adbb84f02d4caadc' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index 64d60d5..fe7fc3e 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
 name: _fe_analyzer_shared
-version: 24.0.0
+version: 25.0.0
 description: Logic that is shared between the front_end and analyzer packages.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
 
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index cdaf236..d2b2f22 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 2.2.0
+* Improvements in constructors tear-off implementation.
+
 ## 2.1.0
 * Changed `AnalysisResult.path` to be non-nullable.
 * Changed `ParsedLibraryResult.units` to be non-nullable.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index b3749f5..5f6cc0f 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 2.1.0
+version: 2.2.0
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
@@ -7,7 +7,7 @@
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared: ^24.0.0
+  _fe_analyzer_shared: ^25.0.0
   cli_util: ^0.3.0
   collection: ^1.15.0
   convert: ^3.0.0
diff --git a/pkg/dart2js_info/README.md b/pkg/dart2js_info/README.md
index 2f2fe11..28ec26f 100644
--- a/pkg/dart2js_info/README.md
+++ b/pkg/dart2js_info/README.md
@@ -23,8 +23,6 @@
 
 ## Status
 
-[![Build Status](https://github.com/dart-lang/dart2js_info/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/dart2js_info/actions?query=workflow%3A"Dart+CI"+branch%3Amaster)
-
 Currently, most tools available here can be used to analyze code-size and
 attribution of code-size to different parts of your app. With time, we hope to
 add more data to the info files, and include better tools to help
diff --git a/tests/language/covariant/override_covariant_both_test.dart b/tests/language/covariant/override_covariant_both_test.dart
new file mode 100644
index 0000000..0a381c7
--- /dev/null
+++ b/tests/language/covariant/override_covariant_both_test.dart
@@ -0,0 +1,508 @@
+// 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.
+
+// Test cases where an inherited method has a parameter `p0` that
+// corresponds to a parameter `p1` in the interface, where `p0` and `p1` are
+// both covariant-by-declaration.
+//
+// The library contains groups of classes depending on each other, and there
+// is no connection between the groups. Each group has a number (0 .. 17)
+// which is used at the end of most names in the group. For example, the first
+// group consists of the classes `B0`, `C0`, `DD0`, and `D0`. The group number
+// is shown as `#` in the remainder of this comment.
+//
+// In every group, the classes `C#` and `D#` are concrete leaf classes
+// exhibiting the situation of interest, that is, an inherited implementation
+// of the method `m` as well as a signature for `m` in the interface of the
+// class, with a parameter that has the above-mentioned properties.
+//
+// The parameter type in the implementation and the parameter type in the
+// method signature is (`num`, `num`), (`int`, `num`) and (`num`, `int`),
+// respectively, such that we test a covariant, contravariant and invariant
+// parameter type relationship in the overrides.
+//
+// In every group, the class `B#` contains the implementation of the method
+// `m` which is inherited. Class `A#` and mixin `M#`, present in some groups,
+// are used to provide the method implementation to `B#` using a mixin
+// application.
+//
+// The classes `BB#`, `I#`, `DD#`, `J#`, and `JJ#` are helper classes for `C#`
+// and `#D`.
+//
+// Class `BB#` is a subclass of `B#` and a superclass of `C#` and `D#`; it
+// introduces the method signature of `m` into the superclass chain.
+//
+// Class `DD#` is implemented by `D#`. Classes `I#`, `J#`, and `JJ#` are
+// implemented by `C#` or `D#`. Class `DD#` and `JJ#` ensure that `m` can be
+// called with an argument of type `Object`. Class `I#` and `J#` introduce the
+// method signature to `C#` or `D#` via an `implements` relation.
+//
+// Finally, `main` contains test cases where the dynamic type check is
+// incurred, using variable types and arguments that make the type check
+// fail whenever possible.
+//
+// The comments below about 'Superclass' and 'interface' indicate the way in
+// which the superclass of `C#` and `D#` is structured (it can be a regular
+// class or a mixin), and the way in which the superinterface that provides
+// the method signature is structured (it can be declared in `C#` or `D#`,
+// "immediate", or it can be obtained via an `extends` relation or via an
+// `implements` relation).
+
+import 'package:expect/expect.dart';
+
+// Superclass: regular, interface: immediate.
+
+class B0 {
+  void m(covariant num x) {}
+}
+
+class C0 extends B0 {
+  void m(covariant num x);
+}
+
+abstract class DD0 {
+  void m(covariant Object x);
+}
+
+class D0 extends B0 implements DD0 {
+  void m(num x);
+}
+
+class B1 {
+  void m(covariant int x) {}
+}
+
+class C1 extends B1 {
+  void m(covariant num x);
+}
+
+abstract class DD1 {
+  void m(covariant Object x);
+}
+
+class D1 extends B1 implements DD1 {
+  void m(num x);
+}
+
+class B2 {
+  void m(covariant num x) {}
+}
+
+class C2 extends B2 {
+  void m(covariant int x);
+}
+
+abstract class DD2 {
+  void m(covariant Object x);
+}
+
+class D2 extends B2 implements DD2 {
+  void m(int x);
+}
+
+// Superclass: regular, interface: extends.
+
+class B3 {
+  void m(covariant num x) {}
+}
+
+abstract class BB3 extends B3 {
+  void m(covariant num x);
+}
+
+class C3 extends BB3 {}
+
+abstract class DD3 {
+  void m(covariant Object x);
+}
+
+class D3 extends BB3 implements DD3 {}
+
+class B4 {
+  void m(covariant int x) {}
+}
+
+abstract class BB4 extends B4 {
+  void m(covariant num x);
+}
+
+class C4 extends BB4 {}
+
+abstract class DD4 {
+  void m(covariant Object x);
+}
+
+class D4 extends BB4 implements DD4 {}
+
+class B5 {
+  void m(covariant num x) {}
+}
+
+abstract class BB5 extends B5 {
+  void m(covariant int x);
+}
+
+class C5 extends BB5 {}
+
+abstract class DD5 {
+  void m(covariant Object x);
+}
+
+class D5 extends BB5 implements DD5 {}
+
+// Superclass: regular, interface: implements.
+
+class B6 {
+  void m(covariant num x) {}
+}
+
+abstract class I6 {
+  void m(covariant num x);
+}
+
+class C6 extends B6 implements I6 {}
+
+abstract class JJ6 {
+  void m(covariant Object x);
+}
+
+abstract class J6 {
+  void m(num x);
+}
+
+class D6 extends B6 implements J6, JJ6 {}
+
+class B7 {
+  void m(covariant int x) {}
+}
+
+abstract class I7 {
+  void m(covariant num x);
+}
+
+class C7 extends B7 implements I7 {}
+
+abstract class JJ7 {
+  void m(covariant Object x);
+}
+
+abstract class J7 {
+  void m(num x);
+}
+
+class D7 extends B7 implements J7, JJ7 {}
+
+class B8 {
+  void m(covariant num x) {}
+}
+
+abstract class I8 {
+  void m(covariant int x);
+}
+
+class C8 extends B8 implements I8 {}
+
+abstract class JJ8 {
+  void m(covariant Object x);
+}
+
+abstract class J8 {
+  void m(int x);
+}
+
+class D8 extends B8 implements J8, JJ8 {}
+
+// Superclass: mixed-in, interface: immediate.
+
+class A9 {}
+
+mixin M9 {
+  void m(covariant num x) {}
+}
+
+class B9 extends A9 with M9 {}
+
+class C9 extends B9 {
+  void m(covariant num x);
+}
+
+abstract class DD9 {
+  void m(covariant Object x);
+}
+
+class D9 extends B9 implements DD9 {
+  void m(num x);
+}
+
+class A10 {}
+
+mixin M10 {
+  void m(covariant int x) {}
+}
+
+class B10 extends A10 with M10 {}
+
+class C10 extends B10 {
+  void m(covariant num x);
+}
+
+abstract class DD10 {
+  void m(covariant Object x);
+}
+
+class D10 extends B10 implements DD10 {
+  void m(num x);
+}
+
+class A11 {}
+
+mixin M11 {
+  void m(covariant num x) {}
+}
+
+class B11 extends A11 with M11 {}
+
+class C11 extends B11 {
+  void m(covariant int x);
+}
+
+abstract class DD11 {
+  void m(covariant Object x);
+}
+
+class D11 extends B11 implements DD11 {
+  void m(int x);
+}
+
+// Superclass: mixed-in, interface: extends.
+
+class A12 {}
+
+mixin M12 {
+  void m(covariant num x) {}
+}
+
+class B12 extends A12 with M12 {}
+
+abstract class BB12 extends B12 {
+  void m(covariant num x);
+}
+
+class C12 extends BB12 {}
+
+abstract class DD12 {
+  void m(covariant Object x);
+}
+
+class D12 extends BB12 implements DD12 {}
+
+class A13 {}
+
+mixin M13 {
+  void m(covariant int x) {}
+}
+
+class B13 extends A13 with M13 {}
+
+abstract class BB13 extends B13 {
+  void m(covariant num x);
+}
+
+class C13 extends BB13 {}
+
+abstract class DD13 {
+  void m(covariant Object x);
+}
+
+class D13 extends BB13 implements DD13 {}
+
+class A14 {}
+
+mixin M14 {
+  void m(covariant num x) {}
+}
+
+class B14 extends A14 with M14 {}
+
+abstract class BB14 extends B14 {
+  void m(covariant int x);
+}
+
+class C14 extends BB14 {}
+
+abstract class DD14 {
+  void m(covariant Object x);
+}
+
+class D14 extends BB14 implements DD14 {}
+
+// Superclass: mixed-in, interface: implements.
+
+class A15 {}
+
+mixin M15 {
+  void m(covariant num x) {}
+}
+
+class B15 extends A15 with M15 {}
+
+abstract class I15 {
+  void m(covariant num x);
+}
+
+class C15 extends B15 implements I15 {}
+
+abstract class JJ15 {
+  void m(covariant Object x);
+}
+
+abstract class J15 {
+  void m(num x);
+}
+
+class D15 extends B15 implements J15, JJ15 {}
+
+class A16 {}
+
+mixin M16 {
+  void m(covariant int x) {}
+}
+
+class B16 extends A16 with M16 {}
+
+abstract class I16 {
+  void m(covariant num x);
+}
+
+class C16 extends B16 implements I16 {}
+
+abstract class JJ16 {
+  void m(covariant Object x);
+}
+
+abstract class J16 {
+  void m(num x);
+}
+
+class D16 extends B16 implements J16, JJ16 {}
+
+class A17 {}
+
+mixin M17 {
+  void m(covariant num x) {}
+}
+
+class B17 extends A17 with M17 {}
+
+abstract class I17 {
+  void m(covariant int x);
+}
+
+class C17 extends B17 implements I17 {}
+
+abstract class JJ17 {
+  void m(covariant Object x);
+}
+
+abstract class J17 {
+  void m(int x);
+}
+
+class D17 extends B17 implements J17, JJ17 {}
+
+void main() {
+  // Demonstrate that each leaf class requires and has a dynamic
+  // type check (which is most likely placed in a forwarding stub).
+  const o = Object();
+
+  B0 x0 = C0();
+  x0.m(0.0);
+  DD0 y0 = D0();
+  Expect.throws(() => y0.m(o));
+
+  C1 x1 = C1();
+  Expect.throws(() => x1.m(1.1));
+  DD1 y1 = D1();
+  Expect.throws(() => y1.m(o));
+
+  B2 x2 = C2();
+  x2.m(2.2);
+  DD2 y2 = D2();
+  Expect.throws(() => y2.m(o));
+
+  B3 x3 = C3();
+  x3.m(3.3);
+  DD3 y3 = D3();
+  Expect.throws(() => y3.m(o));
+
+  C4 x4 = C4();
+  Expect.throws(() => x4.m(4.4));
+  DD4 y4 = D4();
+  Expect.throws(() => y4.m(o));
+
+  B5 x5 = C5();
+  x5.m(5.5);
+  DD5 y5 = D5();
+  Expect.throws(() => y5.m(o));
+
+  B6 x6 = C6();
+  x6.m(6.6);
+  JJ6 y6 = D6();
+  Expect.throws(() => y6.m(o));
+
+  C7 x7 = C7();
+  Expect.throws(() => x7.m(7.7));
+  JJ7 y7 = D7();
+  Expect.throws(() => y7.m(o));
+
+  B8 x8 = C8();
+  x8.m(8.8);
+  JJ8 y8 = D8();
+  Expect.throws(() => y8.m(o));
+
+  B9 x9 = C9();
+  x9.m(1.1);
+  DD9 y9 = D9();
+  Expect.throws(() => y9.m(o));
+
+  C10 x10 = C10();
+  Expect.throws(() => x10.m(10.10));
+  DD10 y10 = D10();
+  Expect.throws(() => y10.m(o));
+
+  B11 x11 = C11();
+  x11.m(11.11);
+  DD11 y11 = D11();
+  Expect.throws(() => y11.m(o));
+
+  B12 x12 = C12();
+  x12.m(12.12);
+  DD12 y12 = D12();
+  Expect.throws(() => y12.m(o));
+
+  C13 x13 = C13();
+  Expect.throws(() => x13.m(13.13));
+  DD13 y13 = D13();
+  Expect.throws(() => y13.m(o));
+
+  B14 x14 = C14();
+  x14.m(14.14);
+  DD14 y14 = D14();
+  Expect.throws(() => y14.m(o));
+
+  B15 x15 = C15();
+  x15.m(15.15);
+  JJ15 y15 = D15();
+  Expect.throws(() => y15.m(o));
+
+  C16 x16 = C16();
+  Expect.throws(() => x16.m(16.16));
+  JJ16 y16 = D16();
+  Expect.throws(() => y16.m(o));
+
+  B17 x17 = C17();
+  x17.m(17.17);
+  JJ17 y17 = D17();
+  Expect.throws(() => y17.m(o));
+}
diff --git a/tests/language/covariant/override_covariant_class_test.dart b/tests/language/covariant/override_covariant_class_test.dart
new file mode 100644
index 0000000..7de1b69
--- /dev/null
+++ b/tests/language/covariant/override_covariant_class_test.dart
@@ -0,0 +1,525 @@
+// 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.
+
+// Test error detection where an inherited method has a parameter `p0`
+// that corresponds to a parameter `p1` in the interface, where `p1` is
+// covariant-by-class and -by-declaration where needed, but `p0` is not.
+//
+// The library contains groups of classes depending on each other, and there
+// is no connection between the groups. Each group has a number (0 .. 17)
+// which is used at the end of most names in the group. For example, the first
+// group consists of the classes `B0`, `C0`, `DD0`, and `D0`. The group number
+// is shown as `#` in the remainder of this comment.
+//
+// In every group, the classes `C#` and `D#` are concrete leaf classes
+// exhibiting the situation of interest, that is, an inherited implementation
+// of the method `m` as well as a signature for `m` in the interface of the
+// class, with a parameter that has the above-mentioned properties.
+//
+// The parameter type in the implementation and the parameter type in the
+// method signature is (`num`, `num`), (`int`, `num`) and (`num`, `int`),
+// respectively, such that we test a covariant, contravariant and invariant
+// parameter type relationship in the overrides.
+//
+// In every group, the class `B#` contains the implementation of the method
+// `m` which is inherited. Class `A#` and mixin `M#`, present in some groups,
+// are used to provide the method implementation to `B#` using a mixin
+// application.
+//
+// The classes `BB#`, `I#`, `DD#`, `J#`, and `JJ#` are helper classes for `C#`
+// and `#D`.
+//
+// Class `BB#` is a subclass of `B#` and a superclass of `C#` and `D#`; it
+// introduces the method signature of `m` into the superclass chain.
+//
+// Class `DD#` is implemented by `D#`. Classes `I#`, `J#`, and `JJ#` are
+// implemented by `C#` or `D#`. Class `DD#` and `JJ#` ensure that `m` can be
+// called with an argument of type `Object`. Class `I#` and `J#` introduce the
+// method signature to `C#` or `D#` via an `implements` relation.
+//
+// Finally, `main` contains test cases where the dynamic type check is
+// incurred, using variable types and arguments that make the type check
+// fail whenever possible.
+//
+// The comments below about 'Superclass' and 'interface' indicate the way in
+// which the superclass of `C#` and `D#` is structured (it can be a regular
+// class or a mixin), and the way in which the superinterface that provides
+// the method signature is structured (it can be declared in `C#` or `D#`,
+// "immediate", or it can be obtained via an `extends` relation or via an
+// `implements` relation).
+
+import 'package:expect/expect.dart';
+
+// Superclass: regular, interface: immediate.
+
+class B0 {
+  void m(num x) {}
+}
+
+abstract class CC0<X extends num> extends B0 {
+  void m(covariant X x);
+}
+
+class C0 extends CC0<num> {}
+
+abstract class DD0<X> {
+  void m(X x);
+}
+
+class D0 extends B0 implements DD0<num> {
+  void m(num x);
+}
+
+// Following the pattern, the classes `B1` .. `D1` are as shown below. They
+// are commented out, because the declaration `CC1.m` is an error, because
+// its parameter has a type which is neither a subtype nor a supertype of
+// the parameter type in `B1.m`. It is not useful to change the bound of `X`
+// in `CC1` to `int`, because that yields a set of classes with exactly the
+// same properties as those of `B0` .. `D0` (just change `num` to `int`
+// everywhere).
+//
+// class B1 {
+//   void m(int x) {}
+// }
+//
+// abstract class CC1<X extends num> extends B1 {
+//   void m(covariant X x);
+// }
+//
+// class C1 extends CC1<int> {}
+//
+// abstract class DD1<X> {
+//   void m(X x);
+// }
+//
+// class D1 extends B1 implements DD1<int> {
+//   void m(int x);
+// }
+
+class B2 {
+  void m(num x) {}
+}
+
+abstract class CC2<X extends int> extends B2 {
+  void m(covariant X x);
+}
+
+class C2 extends CC2<int> {}
+
+abstract class DD2<X> {
+  void m(X x);
+}
+
+class D2 extends B2 implements DD2<int> {
+  void m(num x);
+}
+
+// Superclass: regular, interface: extends.
+
+class B3 {
+  void m(num x) {}
+}
+
+abstract class BB3<X extends num> extends B3 {
+  void m(covariant X x);
+}
+
+class C3 extends BB3<num> {}
+
+abstract class DD3<X extends num> {
+  void m(X x);
+}
+
+class D3 extends BB3<num> implements DD3<num> {}
+
+class B4 {
+  void m(int x) {}
+}
+
+abstract class BB4<X extends int> extends B4 {
+  void m(covariant X x);
+}
+
+class C4 extends BB4<int> {}
+
+abstract class DD4<X extends num> {
+  void m(X x);
+}
+
+class D4 extends BB4<int> implements DD4<int> {}
+
+class B5 {
+  void m(num x) {}
+}
+
+abstract class BB5<X extends int> extends B5 {
+  void m(covariant X x);
+}
+
+class C5 extends BB5<int> {}
+
+abstract class DD5<X extends int> {
+  void m(X x);
+}
+
+class D5 extends BB5<int> implements DD5<int> {}
+
+// Superclass: regular, interface: implements.
+
+class B6 {
+  void m(num x) {}
+}
+
+abstract class I6<X extends num> {
+  void m(X x);
+}
+
+class C6 extends B6 implements I6<num> {}
+
+abstract class JJ6 {
+  void m(Object x);
+}
+
+abstract class J6<X extends num> implements JJ6 {
+  void m(covariant X x);
+}
+
+class D6 extends B6 implements J6<num> {}
+
+class B7 {
+  void m(int x) {}
+}
+
+abstract class I7<X extends num> {
+  void m(X x);
+}
+
+class C7 extends B7 implements I7<int> {}
+
+abstract class JJ7 {
+  void m(Object x);
+}
+
+abstract class J7<X extends num> implements JJ7 {
+  void m(covariant X x);
+}
+
+class D7 extends B7 implements J7<int> {}
+
+class B8 {
+  void m(num x) {}
+}
+
+abstract class I8<X extends int> {
+  void m(X x);
+}
+
+class C8 extends B8 implements I8<int> {}
+
+abstract class JJ8 {
+  void m(Object x);
+}
+
+abstract class J8<X extends int> implements JJ8 {
+  void m(covariant X x);
+}
+
+class D8 extends B8 implements J8<int> {}
+
+// Superclass: mixed-in, interface: immediate.
+
+class A9 {}
+
+mixin M9 {
+  void m(num x) {}
+}
+
+class B9 extends A9 with M9 {}
+
+abstract class CC9<X extends num> extends B9 {
+  void m(covariant X x);
+}
+
+class C9 extends CC9<num> {}
+
+abstract class DD9<X> {
+  void m(X x);
+}
+
+class D9 extends B9 implements DD9<num> {
+  void m(num x);
+}
+
+class A10 {}
+
+mixin M10 {
+  void m(int x) {}
+}
+
+class B10 extends A10 with M10 {}
+
+abstract class CC10<X extends int> extends B10 {
+  void m(covariant X x);
+}
+
+class C10 extends CC10<int> {}
+
+abstract class DD10<X> {
+  void m(X x);
+}
+
+class D10 extends B10 implements DD10<int> {
+  void m(int x);
+}
+
+class A11 {}
+
+mixin M11 {
+  void m(num x) {}
+}
+
+class B11 extends A11 with M11 {}
+
+abstract class CC11<X extends int> extends B11 {
+  void m(covariant X x);
+}
+
+class C11 extends CC11<int> {}
+
+abstract class DD11<X> {
+  void m(X x);
+}
+
+class D11 extends B11 implements DD11<int> {
+  void m(num x);
+}
+
+// Superclass: mixed-in, interface: extends.
+
+class A12 {}
+
+mixin M12 {
+  void m(num x) {}
+}
+
+class B12 extends A12 with M12 {}
+
+abstract class BB12<X extends num> extends B12 {
+  void m(covariant X x);
+}
+
+class C12 extends BB12<num> {}
+
+abstract class DD12<X extends num> {
+  void m(X x);
+}
+
+class D12 extends BB12<num> implements DD12<num> {}
+
+class A13 {}
+
+mixin M13 {
+  void m(int x) {}
+}
+
+class B13 extends A13 with M13 {}
+
+abstract class BB13<X extends int> extends B13 {
+  void m(covariant X x);
+}
+
+class C13 extends BB13<int> {}
+
+abstract class DD13<X extends num> {
+  void m(X x);
+}
+
+class D13 extends BB13<int> implements DD13<int> {}
+
+class A14 {}
+
+mixin M14 {
+  void m(num x) {}
+}
+
+class B14 extends A14 with M14 {}
+
+abstract class BB14<X extends int> extends B14 {
+  void m(covariant X x);
+}
+
+class C14 extends BB14<int> {}
+
+abstract class DD14<X extends int> {
+  void m(X x);
+}
+
+class D14 extends BB14<int> implements DD14<int> {}
+
+// Superclass: mixed-in, interface: implements.
+
+class A15 {}
+
+mixin M15 {
+  void m(num x) {}
+}
+
+class B15 extends A15 with M15 {}
+
+abstract class I15<X extends num> {
+  void m(X x);
+}
+
+class C15 extends B15 implements I15<num> {}
+
+abstract class JJ15 {
+  void m(Object x);
+}
+
+abstract class J15<X extends num> implements JJ15 {
+  void m(covariant X x);
+}
+
+class D15 extends B15 implements J15<num> {}
+
+class A16 {}
+
+mixin M16 {
+  void m(int x) {}
+}
+
+class B16 extends A16 with M16 {}
+
+abstract class I16<X extends num> {
+  void m(X x);
+}
+
+class C16 extends B16 implements I16<int> {}
+
+abstract class JJ16 {
+  void m(Object x);
+}
+
+abstract class J16<X extends num> implements JJ16 {
+  void m(covariant X x);
+}
+
+class D16 extends B16 implements J16<int> {}
+
+class A17 {}
+
+mixin M17 {
+  void m(num x) {}
+}
+
+class B17 extends A17 with M17 {}
+
+abstract class I17<X extends int> {
+  void m(X x);
+}
+
+class C17 extends B17 implements I17<int> {}
+
+abstract class JJ17 {
+  void m(Object x);
+}
+
+abstract class J17<X extends int> implements JJ17 {
+  void m(covariant X x);
+}
+
+class D17 extends B17 implements J17<int> {}
+
+void main() {
+  // Demonstrate that each leaf class requires and has a dynamic
+  // type check (which is most likely placed in a forwarding stub).
+  const o = Object();
+
+  CC0<Object?> x0 = C0();
+  Expect.throws(() => x0.m(o));
+  DD0<Object?> y0 = D0();
+  Expect.throws(() => y0.m(o));
+
+  // Group 1 was eliminated, see comment containing `class B1`.
+
+  CC2<Object?> x2 = C2();
+  Expect.throws(() => x2.m(o));
+  DD2<Object?> y2 = D2();
+  Expect.throws(() => y2.m(o));
+
+  BB3<Object?> x3 = C3();
+  Expect.throws(() => x3.m(o));
+  DD3<Object?> y3 = D3();
+  Expect.throws(() => y3.m(o));
+
+  BB4<Object?> x4 = C4();
+  Expect.throws(() => x4.m(o));
+  DD4<Object?> y4 = D4();
+  Expect.throws(() => y4.m(o));
+
+  BB5<Object?> x5 = C5();
+  Expect.throws(() => x5.m(o));
+  DD5<Object?> y5 = D5();
+  Expect.throws(() => y5.m(o));
+
+  I6<Object?> x6 = C6();
+  Expect.throws(() => x6.m(o));
+  JJ6 y6 = D6();
+  Expect.throws(() => y6.m(o));
+
+  I7<Object?> x7 = C7();
+  Expect.throws(() => x7.m(o));
+  JJ7 y7 = D7();
+  Expect.throws(() => y7.m(o));
+
+  I8<Object?> x8 = C8();
+  Expect.throws(() => x8.m(o));
+  JJ8 y8 = D8();
+  Expect.throws(() => y8.m(o));
+
+  CC9<Object?> x9 = C9();
+  Expect.throws(() => x9.m(o));
+  DD9<Object?> y9 = D9();
+  Expect.throws(() => y9.m(o));
+
+  CC10<Object?> x10 = C10();
+  Expect.throws(() => x10.m(o));
+  DD10<Object?> y10 = D10();
+  Expect.throws(() => y10.m(o));
+
+  CC11<Object?> x11 = C11();
+  Expect.throws(() => x11.m(o));
+  DD11<Object?> y11 = D11();
+  Expect.throws(() => y11.m(o));
+
+  BB12<Object?> x12 = C12();
+  Expect.throws(() => x12.m(o));
+  DD12<Object?> y12 = D12();
+  Expect.throws(() => y12.m(o));
+
+  BB13<Object?> x13 = C13();
+  Expect.throws(() => x13.m(o));
+  DD13<Object?> y13 = D13();
+  Expect.throws(() => y13.m(o));
+
+  BB14<Object?> x14 = C14();
+  Expect.throws(() => x14.m(o));
+  DD14<Object?> y14 = D14();
+  Expect.throws(() => y14.m(o));
+
+  I15<Object?> x15 = C15();
+  Expect.throws(() => x15.m(o));
+  JJ15 y15 = D15();
+  Expect.throws(() => y15.m(o));
+
+  I16<Object?> x16 = C16();
+  Expect.throws(() => x16.m(o));
+  JJ16 y16 = D16();
+  Expect.throws(() => y16.m(o));
+
+  I17<Object?> x17 = C17();
+  Expect.throws(() => x17.m(o));
+  JJ17 y17 = D17();
+  Expect.throws(() => y17.m(o));
+}
diff --git a/tests/language/covariant/override_covariant_interface_test.dart b/tests/language/covariant/override_covariant_interface_test.dart
new file mode 100644
index 0000000..c0fdafb
--- /dev/null
+++ b/tests/language/covariant/override_covariant_interface_test.dart
@@ -0,0 +1,511 @@
+// 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.
+
+// Test the handling of a situation where an inherited method has a parameter
+// `p0` that corresponds to a parameter `p1` in the interface, where `p1`
+// is covariant-by-declaration, but `p0` is not. In this case, the inherited
+// method may need to be overridden by an implicitly induced stub, because
+// it must perform a dynamic type check on its parameter, and the inherited
+// method doesn't do that.
+//
+// The library contains groups of classes depending on each other, and there
+// is no connection between the groups. Each group has a number (0 .. 17)
+// which is used at the end of most names in the group. For example, the first
+// group consists of the classes `B0`, `C0`, `DD0`, and `D0`. The group number
+// is shown as `#` in the remainder of this comment.
+//
+// In every group, the classes `C#` and `D#` are concrete leaf classes
+// exhibiting the situation of interest, that is, an inherited implementation
+// of the method `m` as well as a signature for `m` in the interface of the
+// class, with a parameter that has the above-mentioned properties.
+//
+// The parameter type in the implementation and the parameter type in the
+// method signature is (`num`, `num`), (`int`, `num`) and (`num`, `int`),
+// respectively, such that we test a covariant, contravariant and invariant
+// parameter type relationship in the overrides.
+//
+// In every group, the class `B#` contains the implementation of the method
+// `m` which is inherited. Class `A#` and mixin `M#`, present in some groups,
+// are used to provide the method implementation to `B#` using a mixin
+// application.
+//
+// The classes `BB#`, `I#`, `DD#`, `J#`, and `JJ#` are helper classes for `C#`
+// and `#D`.
+//
+// Class `BB#` is a subclass of `B#` and a superclass of `C#` and `D#`; it
+// introduces the method signature of `m` into the superclass chain.
+//
+// Class `DD#` is implemented by `D#`. Classes `I#`, `J#`, and `JJ#` are
+// implemented by `C#` or `D#`. Class `DD#` and `JJ#` ensure that `m` can be
+// called with an argument of type `Object`. Class `I#` and `J#` introduce the
+// method signature to `C#` or `D#` via an `implements` relation.
+//
+// Finally, `main` contains test cases where the dynamic type check is
+// incurred, using variable types and arguments that make the type check
+// fail whenever possible.
+//
+// The comments below about 'Superclass' and 'interface' indicate the way in
+// which the superclass of `C#` and `D#` is structured (it can be a regular
+// class or a mixin), and the way in which the superinterface that provides
+// the method signature is structured (it can be declared in `C#` or `D#`,
+// "immediate", or it can be obtained via an `extends` relation or via an
+// `implements` relation).
+
+import 'package:expect/expect.dart';
+
+// Superclass: regular, interface: immediate.
+
+class B0 {
+  void m(num x) {}
+}
+
+class C0 extends B0 {
+  void m(covariant num x);
+}
+
+abstract class DD0 {
+  void m(Object x);
+}
+
+class D0 extends B0 implements DD0 {
+  void m(covariant num x);
+}
+
+class B1 {
+  void m(int x) {}
+}
+
+class C1 extends B1 {
+  void m(covariant num x);
+}
+
+abstract class DD1 {
+  void m(Object x);
+}
+
+class D1 extends B1 implements DD1 {
+  void m(covariant num x);
+}
+
+class B2 {
+  void m(num x) {}
+}
+
+class C2 extends B2 {
+  void m(covariant int x);
+}
+
+abstract class DD2 {
+  void m(Object x);
+}
+
+class D2 extends B2 implements DD2 {
+  void m(covariant int x);
+}
+
+// Superclass: regular, interface: extends.
+
+class B3 {
+  void m(num x) {}
+}
+
+abstract class BB3 extends B3 {
+  void m(covariant num x);
+}
+
+class C3 extends BB3 {}
+
+abstract class DD3 {
+  void m(Object x);
+}
+
+class D3 extends BB3 implements DD3 {}
+
+class B4 {
+  void m(int x) {}
+}
+
+abstract class BB4 extends B4 {
+  void m(covariant num x);
+}
+
+class C4 extends BB4 {}
+
+abstract class DD4 {
+  void m(Object x);
+}
+
+class D4 extends BB4 implements DD4 {}
+
+class B5 {
+  void m(num x) {}
+}
+
+abstract class BB5 extends B5 {
+  void m(covariant int x);
+}
+
+class C5 extends BB5 {}
+
+abstract class DD5 {
+  void m(Object x);
+}
+
+class D5 extends BB5 implements DD5 {}
+
+// Superclass: regular, interface: implements.
+
+class B6 {
+  void m(num x) {}
+}
+
+abstract class I6 {
+  void m(covariant num x);
+}
+
+class C6 extends B6 implements I6 {}
+
+abstract class JJ6 {
+  void m(Object x);
+}
+
+abstract class J6 implements JJ6 {
+  void m(covariant num x);
+}
+
+class D6 extends B6 implements J6 {}
+
+class B7 {
+  void m(int x) {}
+}
+
+abstract class I7 {
+  void m(covariant num x);
+}
+
+class C7 extends B7 implements I7 {}
+
+abstract class JJ7 {
+  void m(Object x);
+}
+
+abstract class J7 implements JJ7 {
+  void m(covariant num x);
+}
+
+class D7 extends B7 implements J7 {}
+
+class B8 {
+  void m(num x) {}
+}
+
+abstract class I8 {
+  void m(covariant int x);
+}
+
+class C8 extends B8 implements I8 {}
+
+abstract class JJ8 {
+  void m(Object x);
+}
+
+abstract class J8 implements JJ8 {
+  void m(covariant int x);
+}
+
+class D8 extends B8 implements J8 {}
+
+// Superclass: mixed-in, interface: immediate.
+
+class A9 {}
+
+mixin M9 {
+  void m(num x) {}
+}
+
+class B9 extends A9 with M9 {}
+
+class C9 extends B9 {
+  void m(covariant num x);
+}
+
+abstract class DD9 {
+  void m(Object x);
+}
+
+class D9 extends B9 implements DD9 {
+  void m(covariant num x);
+}
+
+class A10 {}
+
+mixin M10 {
+  void m(int x) {}
+}
+
+class B10 extends A10 with M10 {}
+
+class C10 extends B10 {
+  void m(covariant num x);
+}
+
+abstract class DD10 {
+  void m(Object x);
+}
+
+class D10 extends B10 implements DD10 {
+  void m(covariant num x);
+}
+
+class A11 {}
+
+mixin M11 {
+  void m(num x) {}
+}
+
+class B11 extends A11 with M11 {}
+
+class C11 extends B11 {
+  void m(covariant int x);
+}
+
+abstract class DD11 {
+  void m(Object x);
+}
+
+class D11 extends B11 implements DD11 {
+  void m(covariant int x);
+}
+
+// Superclass: mixed-in, interface: extends.
+
+class A12 {}
+
+mixin M12 {
+  void m(num x) {}
+}
+
+class B12 extends A12 with M12 {}
+
+abstract class BB12 extends B12 {
+  void m(covariant num x);
+}
+
+class C12 extends BB12 {}
+
+abstract class DD12 {
+  void m(Object x);
+}
+
+class D12 extends BB12 implements DD12 {}
+
+class A13 {}
+
+mixin M13 {
+  void m(int x) {}
+}
+
+class B13 extends A13 with M13 {}
+
+abstract class BB13 extends B13 {
+  void m(covariant num x);
+}
+
+class C13 extends BB13 {}
+
+abstract class DD13 {
+  void m(Object x);
+}
+
+class D13 extends BB13 implements DD13 {}
+
+class A14 {}
+
+mixin M14 {
+  void m(num x) {}
+}
+
+class B14 extends A14 with M14 {}
+
+abstract class BB14 extends B14 {
+  void m(covariant int x);
+}
+
+class C14 extends BB14 {}
+
+abstract class DD14 {
+  void m(Object x);
+}
+
+class D14 extends BB14 implements DD14 {}
+
+// Superclass: mixed-in, interface: implements.
+
+class A15 {}
+
+mixin M15 {
+  void m(num x) {}
+}
+
+class B15 extends A15 with M15 {}
+
+abstract class I15 {
+  void m(covariant num x);
+}
+
+class C15 extends B15 implements I15 {}
+
+abstract class JJ15 {
+  void m(Object x);
+}
+
+abstract class J15 implements JJ15 {
+  void m(covariant num x);
+}
+
+class D15 extends B15 implements J15 {}
+
+class A16 {}
+
+mixin M16 {
+  void m(int x) {}
+}
+
+class B16 extends A16 with M16 {}
+
+abstract class I16 {
+  void m(covariant num x);
+}
+
+class C16 extends B16 implements I16 {}
+
+abstract class JJ16 {
+  void m(Object x);
+}
+
+abstract class J16 implements JJ16 {
+  void m(covariant num x);
+}
+
+class D16 extends B16 implements J16 {}
+
+class A17 {}
+
+mixin M17 {
+  void m(num x) {}
+}
+
+class B17 extends A17 with M17 {}
+
+abstract class I17 {
+  void m(covariant int x);
+}
+
+class C17 extends B17 implements I17 {}
+
+abstract class JJ17 {
+  void m(Object x);
+}
+
+abstract class J17 implements JJ17 {
+  void m(covariant int x);
+}
+
+class D17 extends B17 implements J17 {}
+
+void main() {
+  // Demonstrate that each leaf class requires and has a dynamic
+  // type check (which is most likely placed in a forwarding stub).
+  const o = Object();
+
+  B0 x0 = C0();
+  x0.m(0.0);
+  DD0 y0 = D0();
+  Expect.throws(() => y0.m(o));
+
+  C1 x1 = C1();
+  Expect.throws(() => x1.m(1.1));
+  DD1 y1 = D1();
+  Expect.throws(() => y1.m(o));
+
+  B2 x2 = C2();
+  x2.m(2.2);
+  DD2 y2 = D2();
+  Expect.throws(() => y2.m(o));
+
+  B3 x3 = C3();
+  x3.m(3.3);
+  DD3 y3 = D3();
+  Expect.throws(() => y3.m(o));
+
+  C4 x4 = C4();
+  Expect.throws(() => x4.m(4.4));
+  DD4 y4 = D4();
+  Expect.throws(() => y4.m(o));
+
+  B5 x5 = C5();
+  x5.m(5.5);
+  DD5 y5 = D5();
+  Expect.throws(() => y5.m(o));
+
+  B6 x6 = C6();
+  x6.m(6.6);
+  JJ6 y6 = D6();
+  Expect.throws(() => y6.m(o));
+
+  C7 x7 = C7();
+  Expect.throws(() => x7.m(7.7));
+  JJ7 y7 = D7();
+  Expect.throws(() => y7.m(o));
+
+  B8 x8 = C8();
+  x8.m(8.8);
+  JJ8 y8 = D8();
+  Expect.throws(() => y8.m(o));
+
+  B9 x9 = C9();
+  x9.m(1.1);
+  DD9 y9 = D9();
+  Expect.throws(() => y9.m(o));
+
+  C10 x10 = C10();
+  Expect.throws(() => x10.m(10.10));
+  DD10 y10 = D10();
+  Expect.throws(() => y10.m(o));
+
+  B11 x11 = C11();
+  x11.m(11.11);
+  DD11 y11 = D11();
+  Expect.throws(() => y11.m(o));
+
+  B12 x12 = C12();
+  x12.m(12.12);
+  DD12 y12 = D12();
+  Expect.throws(() => y12.m(o));
+
+  C13 x13 = C13();
+  Expect.throws(() => x13.m(13.13));
+  DD13 y13 = D13();
+  Expect.throws(() => y13.m(o));
+
+  B14 x14 = C14();
+  x14.m(14.14);
+  DD14 y14 = D14();
+  Expect.throws(() => y14.m(o));
+
+  B15 x15 = C15();
+  x15.m(15.15);
+  JJ15 y15 = D15();
+  Expect.throws(() => y15.m(o));
+
+  C16 x16 = C16();
+  Expect.throws(() => x16.m(16.16));
+  JJ16 y16 = D16();
+  Expect.throws(() => y16.m(o));
+
+  B17 x17 = C17();
+  x17.m(17.17);
+  JJ17 y17 = D17();
+  Expect.throws(() => y17.m(o));
+}
diff --git a/tests/language/covariant/override_covariant_superclass_test.dart b/tests/language/covariant/override_covariant_superclass_test.dart
new file mode 100644
index 0000000..5c78272
--- /dev/null
+++ b/tests/language/covariant/override_covariant_superclass_test.dart
@@ -0,0 +1,508 @@
+// 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.
+
+// Test cases where an inherited method has a parameter `p0` that
+// corresponds to a parameter `p1` in the interface, where `p0` is
+// covariant-by-declaration, but `p1` is not.
+//
+// The library contains groups of classes depending on each other, and there
+// is no connection between the groups. Each group has a number (0 .. 17)
+// which is used at the end of most names in the group. For example, the first
+// group consists of the classes `B0`, `C0`, `DD0`, and `D0`. The group number
+// is shown as `#` in the remainder of this comment.
+//
+// In every group, the classes `C#` and `D#` are concrete leaf classes
+// exhibiting the situation of interest, that is, an inherited implementation
+// of the method `m` as well as a signature for `m` in the interface of the
+// class, with a parameter that has the above-mentioned properties.
+//
+// The parameter type in the implementation and the parameter type in the
+// method signature is (`num`, `num`), (`int`, `num`) and (`num`, `int`),
+// respectively, such that we test a covariant, contravariant and invariant
+// parameter type relationship in the overrides.
+//
+// In every group, the class `B#` contains the implementation of the method
+// `m` which is inherited. Class `A#` and mixin `M#`, present in some groups,
+// are used to provide the method implementation to `B#` using a mixin
+// application.
+//
+// The classes `BB#`, `I#`, `DD#`, `J#`, and `JJ#` are helper classes for `C#`
+// and `#D`.
+//
+// Class `BB#` is a subclass of `B#` and a superclass of `C#` and `D#`; it
+// introduces the method signature of `m` into the superclass chain.
+//
+// Class `DD#` is implemented by `D#`. Classes `I#`, `J#`, and `JJ#` are
+// implemented by `C#` or `D#`. Class `DD#` and `JJ#` ensure that `m` can be
+// called with an argument of type `Object`. Class `I#` and `J#` introduce the
+// method signature to `C#` or `D#` via an `implements` relation.
+//
+// Finally, `main` contains test cases where the dynamic type check is
+// incurred, using variable types and arguments that make the type check
+// fail whenever possible.
+//
+// The comments below about 'Superclass' and 'interface' indicate the way in
+// which the superclass of `C#` and `D#` is structured (it can be a regular
+// class or a mixin), and the way in which the superinterface that provides
+// the method signature is structured (it can be declared in `C#` or `D#`,
+// "immediate", or it can be obtained via an `extends` relation or via an
+// `implements` relation).
+
+import 'package:expect/expect.dart';
+
+// Superclass: regular, interface: immediate.
+
+class B0 {
+  void m(covariant num x) {}
+}
+
+class C0 extends B0 {
+  void m(num x);
+}
+
+abstract class DD0 {
+  void m(Object x);
+}
+
+class D0 extends B0 implements DD0 {
+  void m(num x);
+}
+
+class B1 {
+  void m(covariant int x) {}
+}
+
+class C1 extends B1 {
+  void m(num x);
+}
+
+abstract class DD1 {
+  void m(Object x);
+}
+
+class D1 extends B1 implements DD1 {
+  void m(num x);
+}
+
+class B2 {
+  void m(covariant num x) {}
+}
+
+class C2 extends B2 {
+  void m(int x);
+}
+
+abstract class DD2 {
+  void m(Object x);
+}
+
+class D2 extends B2 implements DD2 {
+  void m(int x);
+}
+
+// Superclass: regular, interface: extends.
+
+class B3 {
+  void m(covariant num x) {}
+}
+
+abstract class BB3 extends B3 {
+  void m(num x);
+}
+
+class C3 extends BB3 {}
+
+abstract class DD3 {
+  void m(Object x);
+}
+
+class D3 extends BB3 implements DD3 {}
+
+class B4 {
+  void m(covariant int x) {}
+}
+
+abstract class BB4 extends B4 {
+  void m(num x);
+}
+
+class C4 extends BB4 {}
+
+abstract class DD4 {
+  void m(Object x);
+}
+
+class D4 extends BB4 implements DD4 {}
+
+class B5 {
+  void m(covariant num x) {}
+}
+
+abstract class BB5 extends B5 {
+  void m(int x);
+}
+
+class C5 extends BB5 {}
+
+abstract class DD5 {
+  void m(Object x);
+}
+
+class D5 extends BB5 implements DD5 {}
+
+// Superclass: regular, interface: implements.
+
+class B6 {
+  void m(covariant num x) {}
+}
+
+abstract class I6 {
+  void m(num x);
+}
+
+class C6 extends B6 implements I6 {}
+
+abstract class JJ6 {
+  void m(Object x);
+}
+
+abstract class J6 {
+  void m(num x);
+}
+
+class D6 extends B6 implements J6, JJ6 {}
+
+class B7 {
+  void m(covariant int x) {}
+}
+
+abstract class I7 {
+  void m(num x);
+}
+
+class C7 extends B7 implements I7 {}
+
+abstract class JJ7 {
+  void m(Object x);
+}
+
+abstract class J7 {
+  void m(num x);
+}
+
+class D7 extends B7 implements J7, JJ7 {}
+
+class B8 {
+  void m(covariant num x) {}
+}
+
+abstract class I8 {
+  void m(int x);
+}
+
+class C8 extends B8 implements I8 {}
+
+abstract class JJ8 {
+  void m(Object x);
+}
+
+abstract class J8 {
+  void m(int x);
+}
+
+class D8 extends B8 implements J8, JJ8 {}
+
+// Superclass: mixed-in, interface: immediate.
+
+class A9 {}
+
+mixin M9 {
+  void m(covariant num x) {}
+}
+
+class B9 extends A9 with M9 {}
+
+class C9 extends B9 {
+  void m(num x);
+}
+
+abstract class DD9 {
+  void m(Object x);
+}
+
+class D9 extends B9 implements DD9 {
+  void m(num x);
+}
+
+class A10 {}
+
+mixin M10 {
+  void m(covariant int x) {}
+}
+
+class B10 extends A10 with M10 {}
+
+class C10 extends B10 {
+  void m(num x);
+}
+
+abstract class DD10 {
+  void m(Object x);
+}
+
+class D10 extends B10 implements DD10 {
+  void m(num x);
+}
+
+class A11 {}
+
+mixin M11 {
+  void m(covariant num x) {}
+}
+
+class B11 extends A11 with M11 {}
+
+class C11 extends B11 {
+  void m(int x);
+}
+
+abstract class DD11 {
+  void m(Object x);
+}
+
+class D11 extends B11 implements DD11 {
+  void m(int x);
+}
+
+// Superclass: mixed-in, interface: extends.
+
+class A12 {}
+
+mixin M12 {
+  void m(covariant num x) {}
+}
+
+class B12 extends A12 with M12 {}
+
+abstract class BB12 extends B12 {
+  void m(num x);
+}
+
+class C12 extends BB12 {}
+
+abstract class DD12 {
+  void m(Object x);
+}
+
+class D12 extends BB12 implements DD12 {}
+
+class A13 {}
+
+mixin M13 {
+  void m(covariant int x) {}
+}
+
+class B13 extends A13 with M13 {}
+
+abstract class BB13 extends B13 {
+  void m(num x);
+}
+
+class C13 extends BB13 {}
+
+abstract class DD13 {
+  void m(Object x);
+}
+
+class D13 extends BB13 implements DD13 {}
+
+class A14 {}
+
+mixin M14 {
+  void m(covariant num x) {}
+}
+
+class B14 extends A14 with M14 {}
+
+abstract class BB14 extends B14 {
+  void m(int x);
+}
+
+class C14 extends BB14 {}
+
+abstract class DD14 {
+  void m(Object x);
+}
+
+class D14 extends BB14 implements DD14 {}
+
+// Superclass: mixed-in, interface: implements.
+
+class A15 {}
+
+mixin M15 {
+  void m(covariant num x) {}
+}
+
+class B15 extends A15 with M15 {}
+
+abstract class I15 {
+  void m(num x);
+}
+
+class C15 extends B15 implements I15 {}
+
+abstract class JJ15 {
+  void m(Object x);
+}
+
+abstract class J15 {
+  void m(num x);
+}
+
+class D15 extends B15 implements J15, JJ15 {}
+
+class A16 {}
+
+mixin M16 {
+  void m(covariant int x) {}
+}
+
+class B16 extends A16 with M16 {}
+
+abstract class I16 {
+  void m(num x);
+}
+
+class C16 extends B16 implements I16 {}
+
+abstract class JJ16 {
+  void m(Object x);
+}
+
+abstract class J16 {
+  void m(num x);
+}
+
+class D16 extends B16 implements J16, JJ16 {}
+
+class A17 {}
+
+mixin M17 {
+  void m(covariant num x) {}
+}
+
+class B17 extends A17 with M17 {}
+
+abstract class I17 {
+  void m(int x);
+}
+
+class C17 extends B17 implements I17 {}
+
+abstract class JJ17 {
+  void m(Object x);
+}
+
+abstract class J17 {
+  void m(int x);
+}
+
+class D17 extends B17 implements J17, JJ17 {}
+
+void main() {
+  // Demonstrate that each leaf class requires and has a dynamic
+  // type check (which is most likely placed in a forwarding stub).
+  const o = Object();
+
+  B0 x0 = C0();
+  x0.m(0.0);
+  DD0 y0 = D0();
+  Expect.throws(() => y0.m(o));
+
+  C1 x1 = C1();
+  Expect.throws(() => x1.m(1.1));
+  DD1 y1 = D1();
+  Expect.throws(() => y1.m(o));
+
+  B2 x2 = C2();
+  x2.m(2.2);
+  DD2 y2 = D2();
+  Expect.throws(() => y2.m(o));
+
+  B3 x3 = C3();
+  x3.m(3.3);
+  DD3 y3 = D3();
+  Expect.throws(() => y3.m(o));
+
+  C4 x4 = C4();
+  Expect.throws(() => x4.m(4.4));
+  DD4 y4 = D4();
+  Expect.throws(() => y4.m(o));
+
+  B5 x5 = C5();
+  x5.m(5.5);
+  DD5 y5 = D5();
+  Expect.throws(() => y5.m(o));
+
+  B6 x6 = C6();
+  x6.m(6.6);
+  JJ6 y6 = D6();
+  Expect.throws(() => y6.m(o));
+
+  C7 x7 = C7();
+  Expect.throws(() => x7.m(7.7));
+  JJ7 y7 = D7();
+  Expect.throws(() => y7.m(o));
+
+  B8 x8 = C8();
+  x8.m(8.8);
+  JJ8 y8 = D8();
+  Expect.throws(() => y8.m(o));
+
+  B9 x9 = C9();
+  x9.m(1.1);
+  DD9 y9 = D9();
+  Expect.throws(() => y9.m(o));
+
+  C10 x10 = C10();
+  Expect.throws(() => x10.m(10.10));
+  DD10 y10 = D10();
+  Expect.throws(() => y10.m(o));
+
+  B11 x11 = C11();
+  x11.m(11.11);
+  DD11 y11 = D11();
+  Expect.throws(() => y11.m(o));
+
+  B12 x12 = C12();
+  x12.m(12.12);
+  DD12 y12 = D12();
+  Expect.throws(() => y12.m(o));
+
+  C13 x13 = C13();
+  Expect.throws(() => x13.m(13.13));
+  DD13 y13 = D13();
+  Expect.throws(() => y13.m(o));
+
+  B14 x14 = C14();
+  x14.m(14.14);
+  DD14 y14 = D14();
+  Expect.throws(() => y14.m(o));
+
+  B15 x15 = C15();
+  x15.m(15.15);
+  JJ15 y15 = D15();
+  Expect.throws(() => y15.m(o));
+
+  C16 x16 = C16();
+  Expect.throws(() => x16.m(16.16));
+  JJ16 y16 = D16();
+  Expect.throws(() => y16.m(o));
+
+  B17 x17 = C17();
+  x17.m(17.17);
+  JJ17 y17 = D17();
+  Expect.throws(() => y17.m(o));
+}
diff --git a/tools/VERSION b/tools/VERSION
index 5e0638b..3897460 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 70
+PRERELEASE 71
 PRERELEASE_PATCH 0
\ No newline at end of file