anchor.diff:            destinationType.typeArguments.length);
         for (int i = 0; i < sourceType.typeArguments.length; i++) {
           _checkAssignment(destinationType.typeArguments[i],
  -            sourceType.typeArguments[i], expression);
  +            sourceType.typeArguments[i], expressionChecks,
  +            hard: false);
         }
       } else if (destinationType.type.isDynamic || sourceType.type.isDynamic) {
         // ok; nothing further to do.
  
positive.code:   @override
    DecoratedType visitReturnStatement(ReturnStatement node) {
      if (node.expression == null) {
        _checkAssignment(_currentFunctionType.returnType, _nullType, null);
      } else {
        _handleAssignment(_currentFunctionType.returnType, node.expression);
      }
  
negative.code:   }
  
    /// Creates the necessary constraint(s) for an assignment from [sourceType] to
    /// [destinationType].  [expressionChecks] tracks checks that might have to be
    /// done on the type of an expression.  [hard] indicates whether a hard edge
    /// should be created.
    void _checkAssignment(DecoratedType destinationType, DecoratedType sourceType,
        ExpressionChecks expressionChecks,
        {@required bool hard}) {
      NullabilityNode.recordAssignment(
          sourceType.node, destinationType.node, _guards, _graph,
          hard: hard);
      // TODO(paulberry): generalize this.
      if ((_isSimple(sourceType) || destinationType.type.isObject) &&
          _isSimple(destinationType)) {
  