Version 2.10.0-134.0.dev
Merge commit 'c9576a1dac4b155be545ac396e2a532a1208d7e9' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart b/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
index 36658b3..21cdd9c 100644
--- a/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
@@ -139,19 +139,10 @@
// If `Q` is a legacy type `Q0*` then the match holds under constraint
// set `C`:
+ // Only if `P` is a subtype match for `Q?` under constraint set `C`.
if (Q_nullability == NullabilitySuffix.star) {
- if (identical(P, DynamicTypeImpl.instance) ||
- identical(P, VoidTypeImpl.instance)) {
- // If `P` is `dynamic` or `void` and `P` is a subtype match
- // for `Q0` under constraint set `C`.
- var Q0 = (Q as TypeImpl).withNullability(NullabilitySuffix.none);
- return trySubtypeMatch(P, Q0, leftSchema);
- } else {
- // Or if `P` is not `dynamic` or `void` and `P` is a subtype match
- // for `Q0?` under constraint set `C`.
- var Qq = (Q as TypeImpl).withNullability(NullabilitySuffix.question);
- return trySubtypeMatch(P, Qq, leftSchema);
- }
+ var Qq = (Q as TypeImpl).withNullability(NullabilitySuffix.question);
+ return trySubtypeMatch(P, Qq, leftSchema);
}
// If `Q` is `FutureOr<Q0>` the match holds under constraint set `C`:
@@ -210,16 +201,6 @@
_constraints.length = rewind;
}
- // Or if `P` is `dynamic` or `void` and `Object` is a subtype match
- // for `Q0` under constraint set `C`.
- if (identical(P, DynamicTypeImpl.instance) ||
- identical(P, VoidTypeImpl.instance)) {
- if (trySubtypeMatch(_typeSystem.objectNone, Q0, leftSchema)) {
- return true;
- }
- _constraints.length = rewind;
- }
-
// Or if `P` is a subtype match for `Q0` under non-empty
// constraint set `C`.
var P_matches_Q0 = trySubtypeMatch(P, Q0, leftSchema);
diff --git a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
index 63715f5..87109c8b 100644
--- a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
@@ -841,29 +841,6 @@
_checkMatch([T], numStar, T_star, true, ['num <: T <: _']);
}
- /// If `Q` is a legacy type `Q0*` then the match holds under constraint
- /// set `C`:
- /// If `P` is `dynamic` or `void` and `P` is a subtype match for `Q0`
- /// under constraint set `C`.
- test_left_top_right_legacy() {
- var U = typeParameter('U', bound: objectNone);
- var U_star = typeParameterTypeStar(U);
-
- _checkMatch([U], dynamicNone, U_star, false, ['dynamic <: U <: _']);
- _checkMatch([U], voidNone, U_star, false, ['void <: U <: _']);
- }
-
- /// If `Q` is `Q0?` the match holds under constraint set `C`:
- /// Or if `P` is `dynamic` or `void` and `Object` is a subtype match
- /// for `Q0` under constraint set `C`.
- test_left_top_right_nullable() {
- var U = typeParameter('U', bound: objectNone);
- var U_question = typeParameterTypeQuestion(U);
-
- _checkMatch([U], dynamicNone, U_question, false, ['Object <: U <: _']);
- _checkMatch([U], voidNone, U_question, false, ['Object <: U <: _']);
- }
-
/// If `P` is a type variable `X` in `L`, then the match holds:
/// Under constraint `_ <: X <: Q`.
test_left_typeParameter() {
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 0f36155..80975a0 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -2600,34 +2600,4 @@
assertType(findNode.cascade('A()'), 'A');
}
-
- test_typeArgumentTypes_generic_inferred_leftTop_dynamic() async {
- await assertNoErrorsInCode('''
-void foo<T extends Object>(T? value) {}
-
-void f(dynamic o) {
- foo(o);
-}
-''');
-
- assertTypeArgumentTypes(
- findNode.methodInvocation('foo(o)'),
- ['Object'],
- );
- }
-
- test_typeArgumentTypes_generic_inferred_leftTop_void() async {
- await assertNoErrorsInCode('''
-void foo<T extends Object>(List<T?> value) {}
-
-void f(List<void> o) {
- foo(o);
-}
-''');
-
- assertTypeArgumentTypes(
- findNode.methodInvocation('foo(o)'),
- ['Object'],
- );
- }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 5b3cbd7..b7a9d24 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -2965,76 +2965,84 @@
return combinedMemberSignatureResult =
declarations.first.getMember(hierarchy);
}
- bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;
- DartType thisType = hierarchy.coreTypes
- .thisInterfaceType(classBuilder.cls, classBuilder.library.nonNullable);
- List<DartType> candidateTypes = new List<DartType>(declarations.length);
ClassMember bestSoFar;
int bestSoFarIndex;
- DartType bestTypeSoFar;
Map<DartType, int> mutualSubtypes;
- for (int candidateIndex = declarations.length - 1;
- candidateIndex >= 0;
- candidateIndex--) {
- ClassMember candidate = declarations[candidateIndex];
- Member target = candidate.getMember(hierarchy);
- assert(target != null,
- "No member computed for ${candidate} (${candidate.runtimeType})");
- DartType candidateType = computeMemberType(hierarchy, thisType, target);
- if (!isNonNullableByDefault) {
- candidateType = legacyErasure(hierarchy.coreTypes, candidateType);
- }
- candidateTypes[candidateIndex] = candidateType;
- if (bestSoFar == null) {
- bestSoFar = candidate;
- bestTypeSoFar = candidateType;
- bestSoFarIndex = candidateIndex;
- } else {
- if (isMoreSpecific(hierarchy, candidateType, bestTypeSoFar)) {
- debug?.log("Combined Member Signature: ${candidate.fullName} "
- "${candidateType} <: ${bestSoFar.fullName} ${bestTypeSoFar}");
- if (isNonNullableByDefault &&
- isMoreSpecific(hierarchy, bestTypeSoFar, candidateType)) {
- if (mutualSubtypes == null) {
- mutualSubtypes = {
- bestTypeSoFar: bestSoFarIndex,
- candidateType: candidateIndex
- };
- } else {
- mutualSubtypes[candidateType] = candidateIndex;
- }
- } else {
- mutualSubtypes = null;
- }
- bestSoFarIndex = candidateIndex;
+ if (declarations.length == 1) {
+ bestSoFar = declarations[0];
+ bestSoFarIndex = 0;
+ } else {
+ DartType thisType = hierarchy.coreTypes.thisInterfaceType(
+ classBuilder.cls, classBuilder.library.nonNullable);
+ bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;
+
+ DartType bestTypeSoFar;
+ List<DartType> candidateTypes = new List<DartType>(declarations.length);
+ for (int candidateIndex = declarations.length - 1;
+ candidateIndex >= 0;
+ candidateIndex--) {
+ ClassMember candidate = declarations[candidateIndex];
+ Member target = candidate.getMember(hierarchy);
+ assert(target != null,
+ "No member computed for ${candidate} (${candidate.runtimeType})");
+ DartType candidateType = computeMemberType(hierarchy, thisType, target);
+ if (!isNonNullableByDefault) {
+ candidateType = legacyErasure(hierarchy.coreTypes, candidateType);
+ }
+ candidateTypes[candidateIndex] = candidateType;
+ if (bestSoFar == null) {
bestSoFar = candidate;
bestTypeSoFar = candidateType;
+ bestSoFarIndex = candidateIndex;
} else {
- debug?.log("Combined Member Signature: "
- "${candidate.fullName} !<: ${bestSoFar.fullName}");
- }
- }
- }
- if (bestSoFar != null) {
- debug?.log("Combined Member Signature bestSoFar: ${bestSoFar.fullName}");
- for (int candidateIndex = 0;
- candidateIndex < declarations.length;
- candidateIndex++) {
- ClassMember candidate = declarations[candidateIndex];
- DartType candidateType = candidateTypes[candidateIndex];
- if (!isMoreSpecific(hierarchy, bestTypeSoFar, candidateType)) {
- debug?.log("Combined Member Signature: "
- "${bestSoFar.fullName} !<: ${candidate.fullName}");
-
- if (!shouldOverrideProblemBeOverlooked(classBuilder)) {
- bestSoFar = null;
- bestTypeSoFar = null;
- mutualSubtypes = null;
+ if (isMoreSpecific(hierarchy, candidateType, bestTypeSoFar)) {
+ debug?.log("Combined Member Signature: ${candidate.fullName} "
+ "${candidateType} <: ${bestSoFar.fullName} ${bestTypeSoFar}");
+ if (isNonNullableByDefault &&
+ isMoreSpecific(hierarchy, bestTypeSoFar, candidateType)) {
+ if (mutualSubtypes == null) {
+ mutualSubtypes = {
+ bestTypeSoFar: bestSoFarIndex,
+ candidateType: candidateIndex
+ };
+ } else {
+ mutualSubtypes[candidateType] = candidateIndex;
+ }
+ } else {
+ mutualSubtypes = null;
+ }
+ bestSoFarIndex = candidateIndex;
+ bestSoFar = candidate;
+ bestTypeSoFar = candidateType;
+ } else {
+ debug?.log("Combined Member Signature: "
+ "${candidate.fullName} !<: ${bestSoFar.fullName}");
}
- break;
+ }
+ }
+ if (bestSoFar != null) {
+ debug?.log("Combined Member Signature bestSoFar: "
+ "${bestSoFar.fullName}");
+ for (int candidateIndex = 0;
+ candidateIndex < declarations.length;
+ candidateIndex++) {
+ ClassMember candidate = declarations[candidateIndex];
+ DartType candidateType = candidateTypes[candidateIndex];
+ if (!isMoreSpecific(hierarchy, bestTypeSoFar, candidateType)) {
+ debug?.log("Combined Member Signature: "
+ "${bestSoFar.fullName} !<: ${candidate.fullName}");
+
+ if (!shouldOverrideProblemBeOverlooked(classBuilder)) {
+ bestSoFar = null;
+ bestTypeSoFar = null;
+ mutualSubtypes = null;
+ }
+ break;
+ }
}
}
}
+
if (bestSoFar == null) {
String name = classBuilder.fullNameForErrors;
int length = classBuilder.isAnonymousMixinApplication ? 1 : name.length;
@@ -3058,16 +3066,16 @@
debug?.log("Combined Member Signature of ${fullNameForErrors}: "
"${bestSoFar.fullName}");
- ProcedureKind kind = ProcedureKind.Method;
- Member bestMemberSoFar = bestSoFar.getMember(hierarchy);
- if (bestSoFar.isProperty) {
- kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
- } else if (bestMemberSoFar is Procedure &&
- bestMemberSoFar.kind == ProcedureKind.Operator) {
- kind = ProcedureKind.Operator;
- }
-
if (modifyKernel) {
+ ProcedureKind kind = ProcedureKind.Method;
+ Member bestMemberSoFar = bestSoFar.getMember(hierarchy);
+ if (bestSoFar.isProperty) {
+ kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
+ } else if (bestMemberSoFar is Procedure &&
+ bestMemberSoFar.kind == ProcedureKind.Operator) {
+ kind = ProcedureKind.Operator;
+ }
+
debug?.log("Combined Member Signature of ${fullNameForErrors}: new "
"ForwardingNode($classBuilder, $bestSoFar, $declarations, $kind)");
Member stub = new ForwardingNode(
diff --git a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
index 5fa02e2..0ed93a7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -11,9 +11,12 @@
Expression,
Field,
FunctionNode,
+ FunctionType,
Member,
Name,
NamedExpression,
+ NamedType,
+ Nullability,
Procedure,
ProcedureKind,
ReturnStatement,
@@ -83,6 +86,203 @@
/// forwarding stubs if necessary.
Member finalize() => _computeCovarianceFixes();
+ /// Creates a getter member signature for [interfaceMember] with the given
+ /// [type].
+ Member _createGetterMemberSignature(Member interfaceMember, DartType type) {
+ Procedure referenceFrom;
+ if (classBuilder.referencesFromIndexed != null) {
+ referenceFrom = classBuilder.referencesFromIndexed
+ .lookupProcedureNotSetter(name.name);
+ }
+ return new Procedure(name, kind, new FunctionNode(null, returnType: type),
+ isAbstract: true,
+ isMemberSignature: true,
+ fileUri: enclosingClass.fileUri,
+ memberSignatureOrigin: interfaceMember,
+ reference: referenceFrom?.reference)
+ ..startFileOffset = enclosingClass.fileOffset
+ ..fileOffset = enclosingClass.fileOffset
+ ..parent = enclosingClass;
+ }
+
+ /// Creates a setter member signature for [interfaceMember] with the given
+ /// [type]. The flags of parameter is set according to [isCovariant] and
+ /// [isGenericCovariantImpl] and the [parameterName] is used, if provided.
+ Member _createSetterMemberSignature(Member interfaceMember, DartType type,
+ {bool isCovariant, bool isGenericCovariantImpl, String parameterName}) {
+ assert(isCovariant != null);
+ assert(isGenericCovariantImpl != null);
+ Procedure referenceFrom;
+ if (classBuilder.referencesFromIndexed != null) {
+ referenceFrom =
+ classBuilder.referencesFromIndexed.lookupProcedureSetter(name.name);
+ }
+ return new Procedure(
+ name,
+ kind,
+ new FunctionNode(null,
+ returnType: const VoidType(),
+ positionalParameters: [
+ new VariableDeclaration(parameterName ?? '_',
+ type: type, isCovariant: isCovariant)
+ ..isGenericCovariantImpl = isGenericCovariantImpl
+ ]),
+ isAbstract: true,
+ isMemberSignature: true,
+ fileUri: enclosingClass.fileUri,
+ memberSignatureOrigin: interfaceMember,
+ reference: referenceFrom?.reference)
+ ..startFileOffset = enclosingClass.fileOffset
+ ..fileOffset = enclosingClass.fileOffset
+ ..parent = enclosingClass;
+ }
+
+ /// Creates a legacy member signature for the field [interfaceMember] if the
+ /// type of [interfaceMember] contains non-legacy nullabilities.
+ Member _createLegacyMemberSignatureForField(Field interfaceMember) {
+ DartType type = interfaceMember.type;
+ if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+ Substitution substitution =
+ _substitutionFor(null, interfaceMember, enclosingClass);
+ type = substitution.substituteType(type);
+ }
+ DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+ if (legacyType == null) {
+ return interfaceMember;
+ } else {
+ // We base the decision to add a member signature on whether the legacy
+ // erasure of the declared type is different from the declared type, i.e.
+ // whether the declared type contained non-legacy nullabilities.
+ //
+ // This is slightly different from checking whether the legacy erasure of
+ // the inherited type is different from the
+ if (kind == ProcedureKind.Getter) {
+ return _createGetterMemberSignature(interfaceMember, legacyType);
+ } else {
+ assert(kind == ProcedureKind.Setter);
+ return _createSetterMemberSignature(interfaceMember, legacyType,
+ isCovariant: interfaceMember.isCovariant,
+ isGenericCovariantImpl: interfaceMember.isGenericCovariantImpl);
+ }
+ }
+ }
+
+ /// Creates a legacy member signature for procedure [interfaceMember] if the
+ /// type of [interfaceMember] contains non-legacy nullabilities.
+ Member _createLegacyMemberSignatureForProcedure(Procedure interfaceMember) {
+ if (interfaceMember.kind == ProcedureKind.Getter) {
+ DartType type = interfaceMember.getterType;
+ if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+ Substitution substitution =
+ _substitutionFor(null, interfaceMember, enclosingClass);
+ type = substitution.substituteType(type);
+ }
+ DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+ if (legacyType == null) {
+ return interfaceMember;
+ } else {
+ return _createGetterMemberSignature(interfaceMember, legacyType);
+ }
+ } else if (interfaceMember.kind == ProcedureKind.Setter) {
+ DartType type = interfaceMember.setterType;
+ if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+ Substitution substitution =
+ _substitutionFor(null, interfaceMember, enclosingClass);
+ type = substitution.substituteType(type);
+ }
+ DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+ if (legacyType == null) {
+ return interfaceMember;
+ } else {
+ VariableDeclaration parameter =
+ interfaceMember.function.positionalParameters.first;
+ return _createSetterMemberSignature(interfaceMember, legacyType,
+ isCovariant: parameter.isCovariant,
+ isGenericCovariantImpl: parameter.isGenericCovariantImpl,
+ parameterName: parameter.name);
+ }
+ } else {
+ FunctionNode function = interfaceMember.function;
+ FunctionType type = function.computeFunctionType(Nullability.legacy);
+ if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+ Substitution substitution =
+ _substitutionFor(null, interfaceMember, enclosingClass);
+ type = substitution.substituteType(type);
+ }
+ FunctionType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+ if (legacyType == null) {
+ return interfaceMember;
+ }
+ Procedure referenceFrom;
+ if (classBuilder.referencesFromIndexed != null) {
+ referenceFrom = classBuilder.referencesFromIndexed
+ .lookupProcedureNotSetter(name.name);
+ }
+ List<VariableDeclaration> positionalParameters = [];
+ for (int i = 0; i < function.positionalParameters.length; i++) {
+ VariableDeclaration parameter = function.positionalParameters[i];
+ DartType parameterType = legacyType.positionalParameters[i];
+ if (i == 0 && interfaceMember == hierarchy.coreTypes.objectEquals) {
+ // In legacy code we special case `Object.==` to infer `dynamic`
+ // instead `Object!`.
+ parameterType = const DynamicType();
+ }
+ positionalParameters.add(new VariableDeclaration(parameter.name,
+ type: parameterType, isCovariant: parameter.isCovariant)
+ ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
+ }
+ List<VariableDeclaration> namedParameters = [];
+ int namedParameterCount = function.namedParameters.length;
+ if (namedParameterCount == 1) {
+ NamedType namedType = legacyType.namedParameters.first;
+ VariableDeclaration parameter = function.namedParameters.first;
+ namedParameters.add(new VariableDeclaration(parameter.name,
+ type: namedType.type, isCovariant: parameter.isCovariant)
+ ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
+ } else if (namedParameterCount > 1) {
+ Map<String, DartType> namedTypes = {};
+ for (NamedType namedType in legacyType.namedParameters) {
+ namedTypes[namedType.name] = namedType.type;
+ }
+ for (int i = 0; i < namedParameterCount; i++) {
+ VariableDeclaration parameter = function.namedParameters[i];
+ DartType parameterType = namedTypes[parameter.name];
+ namedParameters.add(new VariableDeclaration(parameter.name,
+ type: parameterType, isCovariant: parameter.isCovariant)
+ ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
+ }
+ }
+ return new Procedure(
+ name,
+ kind,
+ new FunctionNode(null,
+ typeParameters: legacyType.typeParameters,
+ returnType: legacyType.returnType,
+ positionalParameters: positionalParameters,
+ namedParameters: namedParameters,
+ requiredParameterCount: function.requiredParameterCount),
+ isAbstract: true,
+ isMemberSignature: true,
+ fileUri: enclosingClass.fileUri,
+ memberSignatureOrigin: interfaceMember,
+ reference: referenceFrom?.reference)
+ ..startFileOffset = enclosingClass.fileOffset
+ ..fileOffset = enclosingClass.fileOffset
+ ..parent = enclosingClass;
+ }
+ }
+
+ /// Creates a legacy member signature for [interfaceMember] if the type of
+ /// [interfaceMember] contains non-legacy nullabilities.
+ Member _createLegacyMemberSignature(Member interfaceMember) {
+ if (interfaceMember is Field) {
+ return _createLegacyMemberSignatureForField(interfaceMember);
+ } else {
+ assert(interfaceMember is Procedure);
+ return _createLegacyMemberSignatureForProcedure(interfaceMember);
+ }
+ }
+
/// Tag the parameters of [interfaceMember] that need type checks
///
/// Parameters can need type checks for calls coming from statically typed
@@ -95,6 +295,18 @@
/// stub is introduced as a place to put the checks.
Member _computeCovarianceFixes() {
Member interfaceMember = combinedMemberSignatureResult.getMember(hierarchy);
+ if (_candidates.length == 1) {
+ // Covariance can only come from [interfaceMember] so we never need a
+ // forwarding stub.
+ if (interfaceMember.isNonNullableByDefault &&
+ !classBuilder.library.isNonNullableByDefault) {
+ // Create a member signature with the legacy erasure type.
+ return _createLegacyMemberSignature(interfaceMember);
+ } else {
+ // Nothing to do.
+ return interfaceMember;
+ }
+ }
List<TypeParameter> interfaceMemberTypeParameters =
interfaceMember.function?.typeParameters ?? [];
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index a35454f..0ca4f6d 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1016,6 +1016,7 @@
equivalence
equivalent
equivalents
+erasure
erroneous
error
errors
@@ -1809,6 +1810,7 @@
meant
measurably
measure
+measurements
mechanism
medium
meet
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart
new file mode 100644
index 0000000..a167112
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.
+
+// @dart=2.8
+
+import 'covariant_from_opt_in_lib.dart';
+
+class SubClass extends Class with Mixin {
+ void covariant(SubClass cls) {} // ok
+ void invariant(SubClass cls) {} // error
+ void contravariant(Object cls) {} // ok
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline.expect
new file mode 100644
index 0000000..4a8f587
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+// @dart = 2.8
+import 'covariant_from_opt_in_lib.dart';
+
+class SubClass extends Class with Mixin {
+ void covariant(SubClass cls) {}
+ void invariant(SubClass cls) {}
+ void contravariant(Object cls) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0c09e22
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+// @dart = 2.8
+import 'covariant_from_opt_in_lib.dart';
+
+class SubClass extends Class with Mixin {
+ void contravariant(Object cls) {}
+ void covariant(SubClass cls) {}
+ void invariant(SubClass cls) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..2571ea6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.weak.expect
@@ -0,0 +1,62 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart:11:27: Error: The parameter 'cls' of the method 'SubClass.invariant' has type 'SubClass', which does not match the corresponding type, 'Class', in the overridden method, 'Class with Mixin.invariant'.
+// - 'SubClass' is from 'pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart'.
+// - 'Class' is from 'pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart'.
+// Change to a supertype of 'Class', or, for a covariant parameter, a subtype.
+// void invariant(SubClass cls) {} // error
+// ^
+// pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart:9:7: Context: This is the overridden method ('invariant').
+// class SubClass extends Class with Mixin {
+// ^
+//
+import self as self;
+import "covariant_from_opt_in_lib.dart" as cov;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///covariant_from_opt_in_lib.dart";
+
+abstract class _SubClass&Class&Mixin = cov::Class with cov::Mixin /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_SubClass&Class&Mixin*
+ : super cov::Class::•()
+ ;
+ abstract member-signature method covariant(covariant cov::Class* cls) → void; -> cov::Class::covariant
+ abstract member-signature method invariant(cov::Class* cls) → void; -> cov::Class::invariant
+ abstract member-signature method contravariant(cov::Class* cls) → void; -> cov::Class::contravariant
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class SubClass extends self::_SubClass&Class&Mixin {
+ synthetic constructor •() → self::SubClass*
+ : super self::_SubClass&Class&Mixin::•()
+ ;
+ method covariant(covariant self::SubClass* cls) → void {}
+ method invariant(self::SubClass* cls) → void {}
+ method contravariant(core::Object* cls) → void {}
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as cov;
+import "dart:core" as core;
+
+abstract class Mixin extends core::Object /*isMixinDeclaration*/ {
+}
+abstract class Class extends core::Object {
+ synthetic constructor •() → cov::Class
+ : super core::Object::•()
+ ;
+ abstract method covariant(covariant cov::Class cls) → void;
+ abstract method invariant(cov::Class cls) → void;
+ abstract method contravariant(cov::Class cls) → void;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart
new file mode 100644
index 0000000..a10e376
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, 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.
+
+mixin Mixin {}
+
+abstract class Class {
+ void covariant(covariant Class cls);
+ void invariant(Class cls);
+ void contravariant(Class cls);
+}
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index d9272d6..fee0310 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -67,6 +67,7 @@
nnbd/nullable_receiver: TypeCheckError
nnbd/potentially_nullable_access: TypeCheckError
nnbd_mixed/bad_mixins: TypeCheckError
+nnbd_mixed/covariant_from_opt_in: TypeCheckError
nnbd_mixed/inheritance_from_opt_in: TypeCheckError
nnbd_mixed/issue41567: TypeCheckError
nnbd_mixed/messages_with_types_opt_in: TypeCheckError
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 481479e..98fb84a 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1235,8 +1235,10 @@
leaveScope(memberScope: true);
_currentlyInNonimplementation = currentlyInNonimplementationSaved;
- assert((node.forwardingStubSuperTarget != null) ||
- !(node.isForwardingStub && node.function.body != null));
+ assert(
+ (node.forwardingStubSuperTarget != null) ||
+ !(node.isForwardingStub && node.function.body != null),
+ "Invalid forwarding stub $node.");
}
@override
diff --git a/tests/language/inference/dynamic_nullable_test.dart b/tests/language/inference/dynamic_nullable_test.dart
index 46b6591..6bcb121 100644
--- a/tests/language/inference/dynamic_nullable_test.dart
+++ b/tests/language/inference/dynamic_nullable_test.dart
@@ -55,7 +55,7 @@
var c = C.list(o);
var f = bar(o);
- var l = o.whereNotNull();
+ var l = o.whereNotNull;
c.expectStaticType<Exactly<C<Object>>>();
Expect.type<C<Object>>(c); // Run-time type is subtype of C<Object>.
diff --git a/tools/VERSION b/tools/VERSION
index 941fd96..66e08aa 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 133
+PRERELEASE 134
PRERELEASE_PATCH 0
\ No newline at end of file