Version 2.10.0-129.0.dev

Merge commit '52794e61417df36b96f54228cf014b15cb258954' into 'dev'
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..b1b6388 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.isRequired)
+          ..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 5882a79..0073a80 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/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/sdk/BUILD.gn b/sdk/BUILD.gn
index ae81ef8..c121a26 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -591,11 +591,11 @@
   outputs =
       [ "$root_out_dir/dart-sdk/bin/third_party/wasmer/{{source_file_part}}" ]
   if (is_win) {
-    sources = [ "$target_out_dir/../../wasmer_wrapper.dll" ]
+    sources = [ "$root_out_dir/wasmer_wrapper.dll" ]
   } else if (is_mac) {
-    sources = [ "$target_out_dir/../../libwasmer_wrapper.dylib" ]
+    sources = [ "$root_out_dir/libwasmer_wrapper.dylib" ]
   } else {
-    sources = [ "$target_out_dir/../../libwasmer_wrapper.so" ]
+    sources = [ "$root_out_dir/libwasmer_wrapper.so" ]
   }
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index 255ff78..14a7a99 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 128
+PRERELEASE 129
 PRERELEASE_PATCH 0
\ No newline at end of file